From 6e557fe2a10cc1cb649a175f8bad3c2e47d5e2ba Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Tue, 19 Mar 2024 07:47:14 -0700 Subject: [PATCH 01/94] standardise json formatting --- .gitignore | 1 - .prettierignore | 1 + .vscode/launch.json | 76 +++++++++++----------- .vscode/settings.json | 60 +++++++++++------- .vscode/tasks.json | 26 ++++---- tslint.json | 143 ++++++++++++++++++------------------------ 6 files changed, 148 insertions(+), 159 deletions(-) create mode 100644 .prettierignore diff --git a/.gitignore b/.gitignore index f800a1642..7178f4122 100644 --- a/.gitignore +++ b/.gitignore @@ -36,4 +36,3 @@ test/fixtures/objective-c/quicktype /.bsp .metals .scala-build -.vscode diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000..c4dbe99c9 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +test/inputs/* diff --git a/.vscode/launch.json b/.vscode/launch.json index 7c36e6c8a..1cbad2c56 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,40 +1,40 @@ { - // Use IntelliSense to learn about possible Node.js debug attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "quicktype", - "type": "node", - "request": "launch", - "program": "${workspaceRoot}/node_modules/ts-node/dist/_bin.js", - "runtimeArgs": ["--nolazy"], - "args": [ - "--project", - "src/cli/tsconfig.json", - "src/cli/index.ts", - "--lang", - "dart", - "--src-lang", - "json", - "./test/inputs/json/priority/blns-object.json" - ], - "cwd": "${workspaceRoot}", - "protocol": "inspector" - }, - { - "name": "test", - "type": "node", - "request": "launch", - "program": "${workspaceRoot}/node_modules/ts-node/dist/_bin.js", - "args": ["--project", "test/tsconfig.json", "test/test.ts"], - "cwd": "${workspaceRoot}", - "protocol": "inspector", - "env": { - "CPUs": "1", - "FIXTURE": "golang" - } - } - ] + // Use IntelliSense to learn about possible Node.js debug attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "quicktype", + "type": "node", + "request": "launch", + "program": "${workspaceRoot}/node_modules/ts-node/dist/_bin.js", + "runtimeArgs": ["--nolazy"], + "args": [ + "--project", + "src/cli/tsconfig.json", + "src/cli/index.ts", + "--lang", + "dart", + "--src-lang", + "json", + "./test/inputs/json/priority/blns-object.json" + ], + "cwd": "${workspaceRoot}", + "protocol": "inspector" + }, + { + "name": "test", + "type": "node", + "request": "launch", + "program": "${workspaceRoot}/node_modules/ts-node/dist/_bin.js", + "args": ["--project", "test/tsconfig.json", "test/test.ts"], + "cwd": "${workspaceRoot}", + "protocol": "inspector", + "env": { + "CPUs": "1", + "FIXTURE": "golang" + } + } + ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index ea68a90d3..f872151c0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,25 +1,37 @@ { - // Place your settings in this file to overwrite default and user settings. - "editor.formatOnSave": true, - "spellright.ignoreFiles": [ - "**/.gitignore", - "**/.spellignore" - ], - "search.exclude": { - "**/.git": true, - "**/node_modules": true, - "**/bower_components": true, - "**/tmp": true, - "output": true, - "**/obj": true, - "**/bin": true, - "test/inputs": true, - "test/runs": true, - "app/build": true, - "elm-stuff": true, - "dist": true - }, - "explorer.excludeGitIgnore": false, - "spellright.documentTypes": [], - "java.configuration.updateBuildConfiguration": "automatic" -} \ No newline at end of file + // Place your settings in this file to overwrite default and user settings. + "editor.formatOnSave": true, + "spellright.ignoreFiles": ["**/.gitignore", "**/.spellignore"], + "search.exclude": { + "**/.git": true, + "**/node_modules": true, + "**/bower_components": true, + "**/tmp": true, + "output": true, + "**/obj": true, + "**/bin": true, + "test/inputs": true, + "test/runs": true, + "app/build": true, + "elm-stuff": true, + "dist": true + }, + "explorer.excludeGitIgnore": false, + "spellright.documentTypes": [], + "java.configuration.updateBuildConfiguration": "automatic", + + "[json]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.wordWrap": "on", + "editor.insertSpaces": true, + "editor.tabSize": 4, + "editor.detectIndentation": false + }, + "[jsonc]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.wordWrap": "on", + "editor.insertSpaces": true, + "editor.tabSize": 4, + "editor.detectIndentation": false + } +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json index d41fa1af8..f36e83f3d 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,15 +1,13 @@ { - // See https://go.microsoft.com/fwlink/?LinkId=733558 - // for the documentation about the tasks.json format - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "script": "tslint", - "group": "build", - "problemMatcher": [ - "$tslint5" - ] - } - ] -} \ No newline at end of file + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "script": "tslint", + "group": "build", + "problemMatcher": ["$tslint5"] + } + ] +} diff --git a/tslint.json b/tslint.json index 6bfd49e76..ac74002e7 100644 --- a/tslint.json +++ b/tslint.json @@ -1,88 +1,67 @@ { - "rules": { - "await-promise": true, - "promise-function-async": true, - "no-floating-promises": true, - "align": [true, "parameters", "statements"], - "ban": false, - "class-name": true, - "comment-format": [true, "check-space"], - "curly": false, - "eofline": false, - "forin": true, - "indent": [true, "spaces", 4], - "interface-name": [true, "never-prefix"], - "jsdoc-format": true, - "jsx-no-lambda": false, - "jsx-no-multiline-js": false, - "label-position": true, - "max-line-length": false, - "member-ordering": [true, "static-before-instance"], + "rules": { + "await-promise": true, + "promise-function-async": true, + "no-floating-promises": true, + "align": [true, "parameters", "statements"], + "ban": false, + "class-name": true, + "comment-format": [true, "check-space"], + "curly": false, + "eofline": false, + "forin": true, + "indent": [true, "spaces", 4], + "interface-name": [true, "never-prefix"], + "jsdoc-format": true, + "jsx-no-lambda": false, + "jsx-no-multiline-js": false, + "label-position": true, + "max-line-length": false, + "member-ordering": [true, "static-before-instance"], - "no-any": false, + "no-any": false, - "no-arg": true, - "no-bitwise": false, - "no-console": [ - false, - "log", - "error", - "debug", - "info", - "time", - "timeEnd", - "trace" - ], - "no-consecutive-blank-lines": true, - "no-construct": true, - "no-debugger": true, - "no-duplicate-variable": true, - "no-empty": [true, "allow-empty-catch"], - "no-eval": true, - "no-shadowed-variable": true, - "no-string-literal": false, - "no-switch-case-fall-through": true, - "no-trailing-whitespace": false, - "no-unsafe-any": false, - "no-unused-expression": true, - "no-use-before-declare": false, - "no-unused-variable": true, - "no-var-keyword": true, - "no-void-expression": false, - "strict-boolean-expressions": true, - "one-line": [ - true, - "check-catch", - "check-else", - "check-open-brace", - "check-whitespace" - ], - "quotemark": [true, "double", "avoid-escape"], - "radix": true, - "semicolon": [true, "always", "ignore-bound-class-methods"], - "switch-default": true, + "no-arg": true, + "no-bitwise": false, + "no-console": [false, "log", "error", "debug", "info", "time", "timeEnd", "trace"], + "no-consecutive-blank-lines": true, + "no-construct": true, + "no-debugger": true, + "no-duplicate-variable": true, + "no-empty": [true, "allow-empty-catch"], + "no-eval": true, + "no-shadowed-variable": true, + "no-string-literal": false, + "no-switch-case-fall-through": true, + "no-trailing-whitespace": false, + "no-unsafe-any": false, + "no-unused-expression": true, + "no-use-before-declare": false, + "no-unused-variable": true, + "no-var-keyword": true, + "no-void-expression": false, + "strict-boolean-expressions": true, + "one-line": [true, "check-catch", "check-else", "check-open-brace", "check-whitespace"], + "quotemark": [true, "double", "avoid-escape"], + "radix": true, + "semicolon": [true, "always", "ignore-bound-class-methods"], + "switch-default": true, - "trailing-comma": false, + "trailing-comma": false, - "triple-equals": [true, "allow-null-check"], - "typedef": [true, "parameter", "property-declaration"], - "typedef-whitespace": [ - true, - { - "call-signature": "nospace", - "index-signature": "nospace", - "parameter": "nospace", - "property-declaration": "nospace", - "variable-declaration": "nospace" - } - ], - "variable-name": [ - true, - "ban-keywords", - "check-format", - "allow-leading-underscore", - "allow-pascal-case" - ], - "whitespace": [false] - } + "triple-equals": [true, "allow-null-check"], + "typedef": [true, "parameter", "property-declaration"], + "typedef-whitespace": [ + true, + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + } + ], + "variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore", "allow-pascal-case"], + "whitespace": [false] + } } From 2648d2d83bce21a12b26254749082c9f3c85ab40 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 30 Mar 2024 09:24:16 -0700 Subject: [PATCH 02/94] fix @types in deps --- package-lock.json | 2 +- packages/quicktype-core/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index ad7704b81..efcbd204d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2350,7 +2350,6 @@ "license": "Apache-2.0", "dependencies": { "@glideapps/ts-necessities": "2.1.3", - "@types/urijs": "^1.19.19", "browser-or-node": "^2.1.1", "collection-utils": "^1.0.1", "cross-fetch": "^4.0.0", @@ -2373,6 +2372,7 @@ "@types/pluralize": "0.0.30", "@types/readable-stream": "2.3.15", "@types/unicode-properties": "^1.3.0", + "@types/urijs": "^1.19.19", "@types/yaml": "^1.9.7", "tslint": "^6.1.3", "typescript": "4.9.5" diff --git a/packages/quicktype-core/package.json b/packages/quicktype-core/package.json index 1ca3eb970..226fc0630 100644 --- a/packages/quicktype-core/package.json +++ b/packages/quicktype-core/package.json @@ -13,7 +13,6 @@ }, "dependencies": { "@glideapps/ts-necessities": "2.1.3", - "@types/urijs": "^1.19.19", "browser-or-node": "^2.1.1", "collection-utils": "^1.0.1", "is-url": "^1.2.4", @@ -36,6 +35,7 @@ "@types/pluralize": "0.0.30", "@types/readable-stream": "2.3.15", "@types/unicode-properties": "^1.3.0", + "@types/urijs": "^1.19.19", "@types/yaml": "^1.9.7", "tslint": "^6.1.3", "typescript": "4.9.5" From a7cec76f8e208ac15f363c221ffa8acca697a657 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Tue, 19 Mar 2024 07:47:14 -0700 Subject: [PATCH 03/94] add file association for schema files --- .vscode/settings.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index f872151c0..f57596256 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,6 @@ { // Place your settings in this file to overwrite default and user settings. "editor.formatOnSave": true, - "spellright.ignoreFiles": ["**/.gitignore", "**/.spellignore"], "search.exclude": { "**/.git": true, "**/node_modules": true, @@ -17,9 +16,12 @@ "dist": true }, "explorer.excludeGitIgnore": false, - "spellright.documentTypes": [], "java.configuration.updateBuildConfiguration": "automatic", + "files.associations": { + "*.schema": "jsonc" + }, + "[json]": { "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.wordWrap": "on", From 03e2f124788228fbee5084455afe0ab879396d49 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 30 Mar 2024 09:41:54 -0700 Subject: [PATCH 04/94] uses const type for All array --- packages/quicktype-core/src/language/All.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/quicktype-core/src/language/All.ts b/packages/quicktype-core/src/language/All.ts index 19313870a..1fda99773 100644 --- a/packages/quicktype-core/src/language/All.ts +++ b/packages/quicktype-core/src/language/All.ts @@ -28,7 +28,7 @@ import { TypeScriptZodTargetLanguage } from "./TypeScriptZod"; import { PhpTargetLanguage } from "./Php"; import { TypeScriptEffectSchemaTargetLanguage } from "./TypeScriptEffectSchema"; -export const all: TargetLanguage[] = [ +export const all = [ new CSharpTargetLanguage(), new GoTargetLanguage(), new RustTargetLanguage(), @@ -55,12 +55,14 @@ export const all: TargetLanguage[] = [ new TypeScriptZodTargetLanguage(), new TypeScriptEffectSchemaTargetLanguage(), new PhpTargetLanguage() -]; +] as const; -export function languageNamed(name: string, targetLanguages?: TargetLanguage[]): TargetLanguage | undefined { - if (targetLanguages === undefined) { - targetLanguages = all; - } +all satisfies readonly TargetLanguage[]; + +export function languageNamed( + name: string, + targetLanguages: readonly TargetLanguage[] = all +): TargetLanguage | undefined { const maybeTargetLanguage = iterableFind( targetLanguages, l => l.names.indexOf(name) >= 0 || l.displayName === name From dcf6d31a66a116e25cdd26edb98e64590a2158b5 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 30 Mar 2024 09:42:16 -0700 Subject: [PATCH 05/94] move python args to own constructor --- packages/quicktype-core/src/language/All.ts | 2 +- packages/quicktype-core/src/language/Python.ts | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/quicktype-core/src/language/All.ts b/packages/quicktype-core/src/language/All.ts index 1fda99773..f286bb183 100644 --- a/packages/quicktype-core/src/language/All.ts +++ b/packages/quicktype-core/src/language/All.ts @@ -49,7 +49,7 @@ export const all = [ new JSONSchemaTargetLanguage(), new RubyTargetLanguage(), new DartTargetLanguage(), - new PythonTargetLanguage("Python", ["python", "py"], "py"), + new PythonTargetLanguage(), new PikeTargetLanguage(), new HaskellTargetLanguage(), new TypeScriptZodTargetLanguage(), diff --git a/packages/quicktype-core/src/language/Python.ts b/packages/quicktype-core/src/language/Python.ts index bce7db095..56182a0a9 100644 --- a/packages/quicktype-core/src/language/Python.ts +++ b/packages/quicktype-core/src/language/Python.ts @@ -130,6 +130,10 @@ export const pythonOptions = { }; export class PythonTargetLanguage extends TargetLanguage { + constructor() { + super("Python", ["python", "py"], "py"); + } + protected getOptions(): Option[] { return [pythonOptions.features, pythonOptions.justTypes, pythonOptions.nicePropertyNames]; } From a834d2c1ed827206b1c5e9e13bb903e5a0f18963 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 30 Mar 2024 10:00:10 -0700 Subject: [PATCH 06/94] make constructor first in misc languages --- packages/quicktype-core/src/language/Crystal.ts | 8 ++++---- .../src/language/JavaScriptPropTypes.ts | 8 ++++---- packages/quicktype-core/src/language/Rust.ts | 8 ++++---- .../src/language/TypeScriptEffectSchema.ts | 8 ++++---- .../quicktype-core/src/language/TypeScriptZod.ts | 12 +++++++----- 5 files changed, 23 insertions(+), 21 deletions(-) diff --git a/packages/quicktype-core/src/language/Crystal.ts b/packages/quicktype-core/src/language/Crystal.ts index 3b469fe15..ae08ac743 100644 --- a/packages/quicktype-core/src/language/Crystal.ts +++ b/packages/quicktype-core/src/language/Crystal.ts @@ -23,14 +23,14 @@ import { Option } from "../RendererOptions"; import { RenderContext } from "../Renderer"; export class CrystalTargetLanguage extends TargetLanguage { - protected makeRenderer(renderContext: RenderContext): CrystalRenderer { - return new CrystalRenderer(this, renderContext); - } - constructor() { super("Crystal", ["crystal", "cr", "crystallang"], "cr"); } + protected makeRenderer(renderContext: RenderContext): CrystalRenderer { + return new CrystalRenderer(this, renderContext); + } + protected get defaultIndentation(): string { return " "; } diff --git a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts index 7d6d90612..7d35dca10 100644 --- a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts +++ b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts @@ -40,14 +40,14 @@ export const javaScriptPropTypesOptions = { }; export class JavaScriptPropTypesTargetLanguage extends TargetLanguage { - protected getOptions(): Option[] { - return [javaScriptPropTypesOptions.acronymStyle, javaScriptPropTypesOptions.converters]; - } - constructor(displayName = "JavaScript PropTypes", names: string[] = ["javascript-prop-types"], extension = "js") { super(displayName, names, extension); } + protected getOptions(): Option[] { + return [javaScriptPropTypesOptions.acronymStyle, javaScriptPropTypesOptions.converters]; + } + protected makeRenderer( renderContext: RenderContext, untypedOptionValues: { [name: string]: any } diff --git a/packages/quicktype-core/src/language/Rust.ts b/packages/quicktype-core/src/language/Rust.ts index 56b464161..f938483d5 100644 --- a/packages/quicktype-core/src/language/Rust.ts +++ b/packages/quicktype-core/src/language/Rust.ts @@ -112,14 +112,14 @@ const namingStyles: Record = { }; export class RustTargetLanguage extends TargetLanguage { - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): RustRenderer { - return new RustRenderer(this, renderContext, getOptionValues(rustOptions, untypedOptionValues)); - } - constructor() { super("Rust", ["rust", "rs", "rustlang"], "rs"); } + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): RustRenderer { + return new RustRenderer(this, renderContext, getOptionValues(rustOptions, untypedOptionValues)); + } + protected getOptions(): Option[] { return [ rustOptions.density, diff --git a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts index 18d5d2c30..4e46b65e3 100644 --- a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts +++ b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts @@ -26,10 +26,6 @@ export const typeScriptEffectSchemaOptions = { }; export class TypeScriptEffectSchemaTargetLanguage extends TargetLanguage { - protected getOptions(): Option[] { - return []; - } - constructor( displayName: string = "TypeScript Effect Schema", names: string[] = ["typescript-effect-schema"], @@ -38,6 +34,10 @@ export class TypeScriptEffectSchemaTargetLanguage extends TargetLanguage { super(displayName, names, extension); } + protected getOptions(): Option[] { + return []; + } + protected makeRenderer( renderContext: RenderContext, untypedOptionValues: { [name: string]: any } diff --git a/packages/quicktype-core/src/language/TypeScriptZod.ts b/packages/quicktype-core/src/language/TypeScriptZod.ts index b2197624a..00f67ecdb 100644 --- a/packages/quicktype-core/src/language/TypeScriptZod.ts +++ b/packages/quicktype-core/src/language/TypeScriptZod.ts @@ -37,10 +37,6 @@ export const typeScriptZodOptions = { }; export class TypeScriptZodTargetLanguage extends TargetLanguage { - protected getOptions(): Option[] { - return []; - } - constructor( displayName: string = "TypeScript Zod", names: string[] = ["typescript-zod"], @@ -49,6 +45,10 @@ export class TypeScriptZodTargetLanguage extends TargetLanguage { super(displayName, names, extension); } + protected getOptions(): Option[] { + return []; + } + get stringTypeMapping(): StringTypeMapping { const mapping: Map = new Map(); const dateTimeType = "date-time"; @@ -328,7 +328,9 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { if (passNum > MAX_PASSES) { //giving up order.push(...deferredIndices); - console.warn("Exceeded maximum number of passes when determining output order, output may contain forward references"); + console.warn( + "Exceeded maximum number of passes when determining output order, output may contain forward references" + ); } } while (indices.length > 0 && passNum <= MAX_PASSES); From 7101e241c72ab65852c00260dfffc110bcbc7656 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 30 Mar 2024 10:24:43 -0700 Subject: [PATCH 07/94] add generics to TargetLanguage for names and extension --- packages/quicktype-core/src/TargetLanguage.ts | 14 +++++++++----- packages/quicktype-core/src/language/CJSON.ts | 12 +++--------- packages/quicktype-core/src/language/CPlusPlus.ts | 6 +++--- packages/quicktype-core/src/language/CSharp.ts | 2 +- packages/quicktype-core/src/language/Crystal.ts | 2 +- packages/quicktype-core/src/language/Dart.ts | 6 +++--- packages/quicktype-core/src/language/Elm.ts | 2 +- packages/quicktype-core/src/language/Golang.ts | 2 +- packages/quicktype-core/src/language/Haskell.ts | 2 +- packages/quicktype-core/src/language/JSONSchema.ts | 2 +- packages/quicktype-core/src/language/Java.ts | 2 +- packages/quicktype-core/src/language/JavaScript.ts | 6 +++--- .../src/language/JavaScriptPropTypes.ts | 10 +++++++--- packages/quicktype-core/src/language/Kotlin.ts | 2 +- .../quicktype-core/src/language/Objective-C.ts | 6 +++++- packages/quicktype-core/src/language/Php.ts | 2 +- packages/quicktype-core/src/language/Pike.ts | 2 +- packages/quicktype-core/src/language/Python.ts | 2 +- packages/quicktype-core/src/language/Rust.ts | 2 +- packages/quicktype-core/src/language/Scala3.ts | 10 +++++----- packages/quicktype-core/src/language/Smithy4s.ts | 10 +++++----- packages/quicktype-core/src/language/Swift.ts | 2 +- .../src/language/TypeScriptEffectSchema.ts | 14 +++++++------- .../quicktype-core/src/language/TypeScriptZod.ts | 10 +++------- packages/quicktype-core/src/language/ruby/index.ts | 2 +- 25 files changed, 67 insertions(+), 65 deletions(-) diff --git a/packages/quicktype-core/src/TargetLanguage.ts b/packages/quicktype-core/src/TargetLanguage.ts index f1c3a90bf..229fa09bb 100644 --- a/packages/quicktype-core/src/TargetLanguage.ts +++ b/packages/quicktype-core/src/TargetLanguage.ts @@ -13,11 +13,15 @@ import { type Comment } from "./support/Comments"; export type MultiFileRenderResult = ReadonlyMap; -export abstract class TargetLanguage { +export abstract class TargetLanguage< + DisplayName extends string = string, + Names extends readonly string[] = readonly string[], + Extension extends string = string +> { constructor( - readonly displayName: string, - readonly names: string[], - readonly extension: string + readonly displayName: DisplayName, + readonly names: Names, + readonly extension: Extension ) {} protected abstract getOptions(): Option[]; @@ -36,7 +40,7 @@ export abstract class TargetLanguage { return { actual, display }; } - get name(): string { + get name(): Names[0] { return defined(this.names[0]); } diff --git a/packages/quicktype-core/src/language/CJSON.ts b/packages/quicktype-core/src/language/CJSON.ts index 8dd1990b2..53cf67fdb 100644 --- a/packages/quicktype-core/src/language/CJSON.ts +++ b/packages/quicktype-core/src/language/CJSON.ts @@ -128,15 +128,9 @@ export const cJSONOptions = { }; /* cJSON generator target language */ -export class CJSONTargetLanguage extends TargetLanguage { - /** - * Constructor - * @param displayName: display name - * @params names: names - * @param extension: extension of files - */ - constructor(displayName = "C (cJSON)", names: string[] = ["cjson", "cJSON"], extension = "h") { - super(displayName, names, extension); +export class CJSONTargetLanguage extends TargetLanguage<"C (cJSON)", ["cjson", "cJSON"], "h"> { + constructor() { + super("C (cJSON)", ["cjson", "cJSON"], "h"); } /** diff --git a/packages/quicktype-core/src/language/CPlusPlus.ts b/packages/quicktype-core/src/language/CPlusPlus.ts index 03cdf6285..5cb3fca31 100644 --- a/packages/quicktype-core/src/language/CPlusPlus.ts +++ b/packages/quicktype-core/src/language/CPlusPlus.ts @@ -118,9 +118,9 @@ export const cPlusPlusOptions = { hideNullOptional: new BooleanOption("hide-null-optional", "Hide null value for optional field", false) }; -export class CPlusPlusTargetLanguage extends TargetLanguage { - constructor(displayName = "C++", names: string[] = ["c++", "cpp", "cplusplus"], extension = "cpp") { - super(displayName, names, extension); +export class CPlusPlusTargetLanguage extends TargetLanguage<"C++", ["c++", "cpp", "cplusplus"], "cpp"> { + constructor() { + super("C++", ["c++", "cpp", "cplusplus"], "cpp"); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/CSharp.ts b/packages/quicktype-core/src/language/CSharp.ts index 627e387be..e3a8d49c3 100644 --- a/packages/quicktype-core/src/language/CSharp.ts +++ b/packages/quicktype-core/src/language/CSharp.ts @@ -194,7 +194,7 @@ export const cSharpOptions = { keepPropertyName: new BooleanOption("keep-property-name", "Keep original field name generate", false) }; -export class CSharpTargetLanguage extends TargetLanguage { +export class CSharpTargetLanguage extends TargetLanguage<"C#", ["cs", "csharp"], "cs"> { constructor() { super("C#", ["cs", "csharp"], "cs"); } diff --git a/packages/quicktype-core/src/language/Crystal.ts b/packages/quicktype-core/src/language/Crystal.ts index ae08ac743..a6d0e5ef1 100644 --- a/packages/quicktype-core/src/language/Crystal.ts +++ b/packages/quicktype-core/src/language/Crystal.ts @@ -22,7 +22,7 @@ import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; import { Option } from "../RendererOptions"; import { RenderContext } from "../Renderer"; -export class CrystalTargetLanguage extends TargetLanguage { +export class CrystalTargetLanguage extends TargetLanguage<"Crystal", ["crystal", "cr", "crystallang"], "cr"> { constructor() { super("Crystal", ["crystal", "cr", "crystallang"], "cr"); } diff --git a/packages/quicktype-core/src/language/Dart.ts b/packages/quicktype-core/src/language/Dart.ts index 6dc40ead6..9fbd5807f 100644 --- a/packages/quicktype-core/src/language/Dart.ts +++ b/packages/quicktype-core/src/language/Dart.ts @@ -61,7 +61,7 @@ export const dartOptions = { partName: new StringOption("part-name", "Use this name in `part` directive", "NAME", "", "secondary") }; -export class DartTargetLanguage extends TargetLanguage { +export class DartTargetLanguage extends TargetLanguage<"Dart", ["dart"], "dart"> { constructor() { super("Dart", ["dart"], "dart"); } @@ -200,8 +200,8 @@ function dartNameStyle(startWithUpper: boolean, upperUnderscore: boolean, origin const firstWordStyle = upperUnderscore ? allUpperWordStyle : startWithUpper - ? firstUpperWordStyle - : allLowerWordStyle; + ? firstUpperWordStyle + : allLowerWordStyle; const restWordStyle = upperUnderscore ? allUpperWordStyle : firstUpperWordStyle; return combineWords( words, diff --git a/packages/quicktype-core/src/language/Elm.ts b/packages/quicktype-core/src/language/Elm.ts index bab36c541..0a7c77f9d 100644 --- a/packages/quicktype-core/src/language/Elm.ts +++ b/packages/quicktype-core/src/language/Elm.ts @@ -34,7 +34,7 @@ export const elmOptions = { moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType") }; -export class ElmTargetLanguage extends TargetLanguage { +export class ElmTargetLanguage extends TargetLanguage<"Elm", ["elm"], "elm"> { constructor() { super("Elm", ["elm"], "elm"); } diff --git a/packages/quicktype-core/src/language/Golang.ts b/packages/quicktype-core/src/language/Golang.ts index fb3c7b8f7..45517c639 100644 --- a/packages/quicktype-core/src/language/Golang.ts +++ b/packages/quicktype-core/src/language/Golang.ts @@ -34,7 +34,7 @@ export const goOptions = { ) }; -export class GoTargetLanguage extends TargetLanguage { +export class GoTargetLanguage extends TargetLanguage<"Go", ["go", "golang"], "go"> { constructor() { super("Go", ["go", "golang"], "go"); } diff --git a/packages/quicktype-core/src/language/Haskell.ts b/packages/quicktype-core/src/language/Haskell.ts index 2bac412e9..5856f32cb 100644 --- a/packages/quicktype-core/src/language/Haskell.ts +++ b/packages/quicktype-core/src/language/Haskell.ts @@ -29,7 +29,7 @@ export const haskellOptions = { moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType") }; -export class HaskellTargetLanguage extends TargetLanguage { +export class HaskellTargetLanguage extends TargetLanguage<"Haskell", ["haskell"], "haskell"> { constructor() { super("Haskell", ["haskell"], "haskell"); } diff --git a/packages/quicktype-core/src/language/JSONSchema.ts b/packages/quicktype-core/src/language/JSONSchema.ts index 2b8a447ba..7249b212f 100644 --- a/packages/quicktype-core/src/language/JSONSchema.ts +++ b/packages/quicktype-core/src/language/JSONSchema.ts @@ -18,7 +18,7 @@ import { addDescriptionToSchema } from "../attributes/Description"; import { Option } from "../RendererOptions"; import { RenderContext } from "../Renderer"; -export class JSONSchemaTargetLanguage extends TargetLanguage { +export class JSONSchemaTargetLanguage extends TargetLanguage<"JSON Schema", ["schema", "json-schema"], "schema"> { constructor() { super("JSON Schema", ["schema", "json-schema"], "schema"); } diff --git a/packages/quicktype-core/src/language/Java.ts b/packages/quicktype-core/src/language/Java.ts index 05ad4b535..64b3c6c2f 100644 --- a/packages/quicktype-core/src/language/Java.ts +++ b/packages/quicktype-core/src/language/Java.ts @@ -53,7 +53,7 @@ export const javaOptions = { lombokCopyAnnotations: new BooleanOption("lombok-copy-annotations", "Copy accessor annotations", true, "secondary") }; -export class JavaTargetLanguage extends TargetLanguage { +export class JavaTargetLanguage extends TargetLanguage<"Java", ["java"], "java"> { constructor() { super("Java", ["java"], "java"); } diff --git a/packages/quicktype-core/src/language/JavaScript.ts b/packages/quicktype-core/src/language/JavaScript.ts index e8e3db9a2..12a18e320 100644 --- a/packages/quicktype-core/src/language/JavaScript.ts +++ b/packages/quicktype-core/src/language/JavaScript.ts @@ -65,9 +65,9 @@ export type JavaScriptTypeAnnotations = { never: string; }; -export class JavaScriptTargetLanguage extends TargetLanguage { - constructor(displayName = "JavaScript", names: string[] = ["javascript", "js", "jsx"], extension = "js") { - super(displayName, names, extension); +export class JavaScriptTargetLanguage extends TargetLanguage<"JavaScript", ["javascript", "js", "jsx"], "js"> { + constructor() { + super("JavaScript", ["javascript", "js", "jsx"], "js"); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts index 7d35dca10..4e8369db2 100644 --- a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts +++ b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts @@ -39,9 +39,13 @@ export const javaScriptPropTypesOptions = { ) }; -export class JavaScriptPropTypesTargetLanguage extends TargetLanguage { - constructor(displayName = "JavaScript PropTypes", names: string[] = ["javascript-prop-types"], extension = "js") { - super(displayName, names, extension); +export class JavaScriptPropTypesTargetLanguage extends TargetLanguage< + "JavaScript PropTypes", + ["javascript-prop-types"], + "js" +> { + constructor() { + super("JavaScript PropTypes", ["javascript-prop-types"], "js"); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/Kotlin.ts b/packages/quicktype-core/src/language/Kotlin.ts index 407b82300..e3e09469d 100644 --- a/packages/quicktype-core/src/language/Kotlin.ts +++ b/packages/quicktype-core/src/language/Kotlin.ts @@ -61,7 +61,7 @@ export const kotlinOptions = { packageName: new StringOption("package", "Package", "PACKAGE", "quicktype") }; -export class KotlinTargetLanguage extends TargetLanguage { +export class KotlinTargetLanguage extends TargetLanguage<"Kotlin", ["kotlin"], "kt"> { constructor() { super("Kotlin", ["kotlin"], "kt"); } diff --git a/packages/quicktype-core/src/language/Objective-C.ts b/packages/quicktype-core/src/language/Objective-C.ts index b1a44e899..facb6174a 100644 --- a/packages/quicktype-core/src/language/Objective-C.ts +++ b/packages/quicktype-core/src/language/Objective-C.ts @@ -43,7 +43,11 @@ export const objcOptions = { extraComments: new BooleanOption("extra-comments", "Extra comments", false) }; -export class ObjectiveCTargetLanguage extends TargetLanguage { +export class ObjectiveCTargetLanguage extends TargetLanguage< + "Objective-C", + ["objc", "objective-c", "objectivec"], + "m" +> { constructor() { super("Objective-C", ["objc", "objective-c", "objectivec"], "m"); } diff --git a/packages/quicktype-core/src/language/Php.ts b/packages/quicktype-core/src/language/Php.ts index 670b09cc1..4933d86d0 100644 --- a/packages/quicktype-core/src/language/Php.ts +++ b/packages/quicktype-core/src/language/Php.ts @@ -34,7 +34,7 @@ export const phpOptions = { acronymStyle: acronymOption(AcronymStyleOptions.Pascal) }; -export class PhpTargetLanguage extends TargetLanguage { +export class PhpTargetLanguage extends TargetLanguage<"PHP", ["php"], "php"> { constructor() { super("PHP", ["php"], "php"); } diff --git a/packages/quicktype-core/src/language/Pike.ts b/packages/quicktype-core/src/language/Pike.ts index d2d9541b7..2e87f5d5a 100644 --- a/packages/quicktype-core/src/language/Pike.ts +++ b/packages/quicktype-core/src/language/Pike.ts @@ -70,7 +70,7 @@ const enumNamingFunction = funPrefixNamer("enumNamer", makeNameStyle("upper-unde const namingFunction = funPrefixNamer("genericNamer", makeNameStyle("underscore", legalizeName)); const namedTypeNamingFunction = funPrefixNamer("typeNamer", makeNameStyle("pascal", legalizeName)); -export class PikeTargetLanguage extends TargetLanguage { +export class PikeTargetLanguage extends TargetLanguage<"Pike", ["pike", "pikelang"], "pmod"> { constructor() { super("Pike", ["pike", "pikelang"], "pmod"); } diff --git a/packages/quicktype-core/src/language/Python.ts b/packages/quicktype-core/src/language/Python.ts index 56182a0a9..f2309db46 100644 --- a/packages/quicktype-core/src/language/Python.ts +++ b/packages/quicktype-core/src/language/Python.ts @@ -129,7 +129,7 @@ export const pythonOptions = { nicePropertyNames: new BooleanOption("nice-property-names", "Transform property names to be Pythonic", true) }; -export class PythonTargetLanguage extends TargetLanguage { +export class PythonTargetLanguage extends TargetLanguage<"Python", ["python", "py"], "py"> { constructor() { super("Python", ["python", "py"], "py"); } diff --git a/packages/quicktype-core/src/language/Rust.ts b/packages/quicktype-core/src/language/Rust.ts index f938483d5..82feb3032 100644 --- a/packages/quicktype-core/src/language/Rust.ts +++ b/packages/quicktype-core/src/language/Rust.ts @@ -111,7 +111,7 @@ const namingStyles: Record = { } }; -export class RustTargetLanguage extends TargetLanguage { +export class RustTargetLanguage extends TargetLanguage<"Rust", ["rust", "rs", "rustlang"], "rs"> { constructor() { super("Rust", ["rust", "rs", "rustlang"], "rs"); } diff --git a/packages/quicktype-core/src/language/Scala3.ts b/packages/quicktype-core/src/language/Scala3.ts index 56437c02b..44ddedc64 100644 --- a/packages/quicktype-core/src/language/Scala3.ts +++ b/packages/quicktype-core/src/language/Scala3.ts @@ -245,10 +245,10 @@ export class Scala3Renderer extends ConvenienceRenderer { delimiter === "curly" ? ["{", "}"] : delimiter === "paren" - ? ["(", ")"] - : delimiter === "none" - ? ["", ""] - : ["{", "})"]; + ? ["(", ")"] + : delimiter === "none" + ? ["", ""] + : ["{", "})"]; this.emitLine(line, " ", open); this.indent(f); this.emitLine(close); @@ -724,7 +724,7 @@ export class CirceRenderer extends Scala3Renderer { } } -export class Scala3TargetLanguage extends TargetLanguage { +export class Scala3TargetLanguage extends TargetLanguage<"Scala3", ["scala3"], "scala"> { constructor() { super("Scala3", ["scala3"], "scala"); } diff --git a/packages/quicktype-core/src/language/Smithy4s.ts b/packages/quicktype-core/src/language/Smithy4s.ts index 3a875be64..203c3b277 100644 --- a/packages/quicktype-core/src/language/Smithy4s.ts +++ b/packages/quicktype-core/src/language/Smithy4s.ts @@ -205,10 +205,10 @@ export class Smithy4sRenderer extends ConvenienceRenderer { delimiter === "curly" ? ["{", "}"] : delimiter === "paren" - ? ["(", ")"] - : delimiter === "none" - ? ["", ""] - : ["{", "})"]; + ? ["(", ")"] + : delimiter === "none" + ? ["", ""] + : ["{", "})"]; this.emitLine(line, " ", open); this.indent(f); this.emitLine(close); @@ -510,7 +510,7 @@ export class Smithy4sRenderer extends ConvenienceRenderer { } } -export class SmithyTargetLanguage extends TargetLanguage { +export class SmithyTargetLanguage extends TargetLanguage<"Smithy", ["Smithy"], "smithy"> { constructor() { super("Smithy", ["Smithy"], "smithy"); } diff --git a/packages/quicktype-core/src/language/Swift.ts b/packages/quicktype-core/src/language/Swift.ts index 04fc431a1..1401079da 100644 --- a/packages/quicktype-core/src/language/Swift.ts +++ b/packages/quicktype-core/src/language/Swift.ts @@ -130,7 +130,7 @@ export interface SwiftProperty { position: ForEachPosition; } -export class SwiftTargetLanguage extends TargetLanguage { +export class SwiftTargetLanguage extends TargetLanguage<"Swift", ["swift", "swift4"], "swift"> { constructor() { super("Swift", ["swift", "swift4"], "swift"); } diff --git a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts index 4e46b65e3..0cab3a764 100644 --- a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts +++ b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts @@ -25,13 +25,13 @@ export const typeScriptEffectSchemaOptions = { justSchema: new BooleanOption("just-schema", "Schema only", false) }; -export class TypeScriptEffectSchemaTargetLanguage extends TargetLanguage { - constructor( - displayName: string = "TypeScript Effect Schema", - names: string[] = ["typescript-effect-schema"], - extension: string = "ts" - ) { - super(displayName, names, extension); +export class TypeScriptEffectSchemaTargetLanguage extends TargetLanguage< + "TypeScript Effect Schema", + ["typescript-effect-schema"], + "ts" +> { + constructor() { + super("TypeScript Effect Schema", ["typescript-effect-schema"], "ts"); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/TypeScriptZod.ts b/packages/quicktype-core/src/language/TypeScriptZod.ts index 00f67ecdb..a37acd5c6 100644 --- a/packages/quicktype-core/src/language/TypeScriptZod.ts +++ b/packages/quicktype-core/src/language/TypeScriptZod.ts @@ -36,13 +36,9 @@ export const typeScriptZodOptions = { justSchema: new BooleanOption("just-schema", "Schema only", false) }; -export class TypeScriptZodTargetLanguage extends TargetLanguage { - constructor( - displayName: string = "TypeScript Zod", - names: string[] = ["typescript-zod"], - extension: string = "ts" - ) { - super(displayName, names, extension); +export class TypeScriptZodTargetLanguage extends TargetLanguage<"TypeScript Zod", ["typescript-zod"], "ts"> { + constructor() { + super("TypeScript Zod", ["typescript-zod"], "ts"); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/ruby/index.ts b/packages/quicktype-core/src/language/ruby/index.ts index 383bdd5ae..178e199c7 100644 --- a/packages/quicktype-core/src/language/ruby/index.ts +++ b/packages/quicktype-core/src/language/ruby/index.ts @@ -51,7 +51,7 @@ export const rubyOptions = { namespace: new StringOption("namespace", "Specify a wrapping Namespace", "NAME", "", "secondary") }; -export class RubyTargetLanguage extends TargetLanguage { +export class RubyTargetLanguage extends TargetLanguage<"Ruby", ["ruby"], "rb"> { constructor() { super("Ruby", ["ruby"], "rb"); } From b17d3f2e07efca5d80223fddb67cb0da7360ffe5 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 30 Mar 2024 11:05:53 -0700 Subject: [PATCH 08/94] fix generics for JavaScript + subclassing --- .../quicktype-core/src/language/JavaScript.ts | 14 +++++++++++--- .../src/language/TypeScriptFlow.ts | 18 +++++++++++++++--- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/packages/quicktype-core/src/language/JavaScript.ts b/packages/quicktype-core/src/language/JavaScript.ts index 12a18e320..6b5273e78 100644 --- a/packages/quicktype-core/src/language/JavaScript.ts +++ b/packages/quicktype-core/src/language/JavaScript.ts @@ -65,9 +65,17 @@ export type JavaScriptTypeAnnotations = { never: string; }; -export class JavaScriptTargetLanguage extends TargetLanguage<"JavaScript", ["javascript", "js", "jsx"], "js"> { - constructor() { - super("JavaScript", ["javascript", "js", "jsx"], "js"); +export class JavaScriptTargetLanguage< + DisplayName extends string = "JavaScript", + Names extends readonly string[] = ["javascript", "js", "jsx"], + Extension extends string = "js" +> extends TargetLanguage { + constructor( + displayName = "JavaScript" as DisplayName, + names = ["javascript", "js", "jsx"] as unknown as Names, + extension = "js" as Extension + ) { + super(displayName, names, extension); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/TypeScriptFlow.ts b/packages/quicktype-core/src/language/TypeScriptFlow.ts index 0c5750006..f8b2cfe11 100644 --- a/packages/quicktype-core/src/language/TypeScriptFlow.ts +++ b/packages/quicktype-core/src/language/TypeScriptFlow.ts @@ -39,7 +39,15 @@ const tsFlowTypeAnnotations = { boolean: ": boolean" }; -export abstract class TypeScriptFlowBaseTargetLanguage extends JavaScriptTargetLanguage { +export abstract class TypeScriptFlowBaseTargetLanguage< + DisplayName extends string, + Names extends readonly string[], + Extension extends string +> extends JavaScriptTargetLanguage { + protected constructor(displayName: DisplayName, names: Names, extension: Extension) { + super(displayName, names, extension); + } + protected getOptions(): Option[] { return [ tsFlowOptions.justTypes, @@ -66,7 +74,11 @@ export abstract class TypeScriptFlowBaseTargetLanguage extends JavaScriptTargetL ): JavaScriptRenderer; } -export class TypeScriptTargetLanguage extends TypeScriptFlowBaseTargetLanguage { +export class TypeScriptTargetLanguage extends TypeScriptFlowBaseTargetLanguage< + "TypeScript", + ["typescript", "ts", "tsx"], + "ts" +> { constructor() { super("TypeScript", ["typescript", "ts", "tsx"], "ts"); } @@ -329,7 +341,7 @@ export class TypeScriptRenderer extends TypeScriptFlowBaseRenderer { } } -export class FlowTargetLanguage extends TypeScriptFlowBaseTargetLanguage { +export class FlowTargetLanguage extends TypeScriptFlowBaseTargetLanguage<"Flow", ["flow"], "js"> { constructor() { super("Flow", ["flow"], "js"); } From c529c530d897512c20fd19fe765b78c957314f12 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 30 Mar 2024 11:21:53 -0700 Subject: [PATCH 09/94] add strict types for language names and display names --- packages/quicktype-core/src/Run.ts | 6 +++-- packages/quicktype-core/src/language/All.ts | 22 +++++++++---------- .../quicktype-core/src/language/JavaScript.ts | 2 +- packages/quicktype-core/src/types.ts | 14 ++++++++++++ 4 files changed, 30 insertions(+), 14 deletions(-) create mode 100644 packages/quicktype-core/src/types.ts diff --git a/packages/quicktype-core/src/Run.ts b/packages/quicktype-core/src/Run.ts index 195417cb9..554f1a862 100644 --- a/packages/quicktype-core/src/Run.ts +++ b/packages/quicktype-core/src/Run.ts @@ -21,7 +21,9 @@ import { makeTransformations } from "./MakeTransformations"; import { TransformedStringTypeKind } from "./Type"; import { type Comment } from "./support/Comments"; -export function getTargetLanguage(nameOrInstance: string | TargetLanguage): TargetLanguage { +import { type LanguageName } from "types"; + +export function getTargetLanguage(nameOrInstance: LanguageName | TargetLanguage): TargetLanguage { if (typeof nameOrInstance === "object") { return nameOrInstance; } @@ -123,7 +125,7 @@ export type NonInferenceOptions = { * or a string specifying one of the names for quicktype's built-in target languages. For example, * both `cs` and `csharp` will generate C#. */ - lang: string | TargetLanguage; + lang: LanguageName | TargetLanguage; /** The input data from which to produce types */ inputData: InputData; /** Put class properties in alphabetical order, instead of in the order found in the JSON */ diff --git a/packages/quicktype-core/src/language/All.ts b/packages/quicktype-core/src/language/All.ts index f286bb183..4bc7ba246 100644 --- a/packages/quicktype-core/src/language/All.ts +++ b/packages/quicktype-core/src/language/All.ts @@ -1,5 +1,3 @@ -import { iterableFind } from "collection-utils"; - import { TargetLanguage } from "../TargetLanguage"; import { CSharpTargetLanguage } from "./CSharp"; @@ -28,6 +26,8 @@ import { TypeScriptZodTargetLanguage } from "./TypeScriptZod"; import { PhpTargetLanguage } from "./Php"; import { TypeScriptEffectSchemaTargetLanguage } from "./TypeScriptEffectSchema"; +import { type LanguageNameMap, type LanguageName } from "../types"; + export const all = [ new CSharpTargetLanguage(), new GoTargetLanguage(), @@ -59,14 +59,14 @@ export const all = [ all satisfies readonly TargetLanguage[]; -export function languageNamed( - name: string, +export function languageNamed( + name: Name, targetLanguages: readonly TargetLanguage[] = all -): TargetLanguage | undefined { - const maybeTargetLanguage = iterableFind( - targetLanguages, - l => l.names.indexOf(name) >= 0 || l.displayName === name - ); - if (maybeTargetLanguage !== undefined) return maybeTargetLanguage; - return iterableFind(targetLanguages, l => l.extension === name); +): LanguageNameMap[Name] { + const foundLanguage = targetLanguages.find(language => language.names.includes(name)); + if (!foundLanguage) { + throw new Error(`Unknown language name: ${name}`); + } + + return foundLanguage as LanguageNameMap[Name]; } diff --git a/packages/quicktype-core/src/language/JavaScript.ts b/packages/quicktype-core/src/language/JavaScript.ts index 6b5273e78..304a6c775 100644 --- a/packages/quicktype-core/src/language/JavaScript.ts +++ b/packages/quicktype-core/src/language/JavaScript.ts @@ -67,7 +67,7 @@ export type JavaScriptTypeAnnotations = { export class JavaScriptTargetLanguage< DisplayName extends string = "JavaScript", - Names extends readonly string[] = ["javascript", "js", "jsx"], + Names extends readonly string[] = readonly ["javascript", "js", "jsx"], Extension extends string = "js" > extends TargetLanguage { constructor( diff --git a/packages/quicktype-core/src/types.ts b/packages/quicktype-core/src/types.ts new file mode 100644 index 000000000..d53fa3b40 --- /dev/null +++ b/packages/quicktype-core/src/types.ts @@ -0,0 +1,14 @@ +import { type TargetLanguage } from "TargetLanguage"; +import type { all } from "./language/All"; + +type AllLanguages = (typeof all)[number]; + +export type LanguageDisplayName = Language["displayName"]; +export type LanguageName = Language["names"][number]; + +export type LanguageDisplayNameMap = { + [Language in AllLanguages as LanguageDisplayName]: Language; +}; +export type LanguageNameMap = { + [Language in AllLanguages as LanguageName]: Language; +}; From 5ca879cbeb74ffb2139d9281943578c8393680ae Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 6 Apr 2024 07:01:24 -0700 Subject: [PATCH 10/94] move language displayName, names, extension to class static members --- packages/quicktype-core/src/TargetLanguage.ts | 18 +++++++++------- packages/quicktype-core/src/language/CJSON.ts | 18 ++++++---------- .../quicktype-core/src/language/CPlusPlus.ts | 10 ++++----- .../quicktype-core/src/language/CSharp.ts | 10 ++++----- .../quicktype-core/src/language/Crystal.ts | 10 ++++----- packages/quicktype-core/src/language/Dart.ts | 14 ++++++------- packages/quicktype-core/src/language/Elm.ts | 10 ++++----- .../quicktype-core/src/language/Golang.ts | 10 ++++----- .../quicktype-core/src/language/Haskell.ts | 10 ++++----- .../quicktype-core/src/language/JSONSchema.ts | 10 ++++----- packages/quicktype-core/src/language/Java.ts | 10 ++++----- .../quicktype-core/src/language/JavaScript.ts | 10 ++++----- .../src/language/JavaScriptPropTypes.ts | 10 ++++----- .../quicktype-core/src/language/Kotlin.ts | 10 ++++----- .../src/language/Objective-C.ts | 10 ++++----- packages/quicktype-core/src/language/Php.ts | 10 ++++----- packages/quicktype-core/src/language/Pike.ts | 10 ++++----- .../quicktype-core/src/language/Python.ts | 10 ++++----- packages/quicktype-core/src/language/Rust.ts | 10 ++++----- .../quicktype-core/src/language/Scala3.ts | 18 ++++++++-------- .../quicktype-core/src/language/Smithy4s.ts | 18 ++++++++-------- packages/quicktype-core/src/language/Swift.ts | 10 ++++----- .../src/language/TypeScriptEffectSchema.ts | 14 +++++-------- .../src/language/TypeScriptFlow.ts | 21 ++++++++++++------- .../src/language/TypeScriptZod.ts | 14 +++++-------- .../quicktype-core/src/language/ruby/index.ts | 18 ++++++++-------- 26 files changed, 159 insertions(+), 164 deletions(-) diff --git a/packages/quicktype-core/src/TargetLanguage.ts b/packages/quicktype-core/src/TargetLanguage.ts index f1c3a90bf..d371594a3 100644 --- a/packages/quicktype-core/src/TargetLanguage.ts +++ b/packages/quicktype-core/src/TargetLanguage.ts @@ -13,12 +13,16 @@ import { type Comment } from "./support/Comments"; export type MultiFileRenderResult = ReadonlyMap; -export abstract class TargetLanguage { - constructor( - readonly displayName: string, - readonly names: string[], - readonly extension: string - ) {} +export interface LanguageConfig { + readonly displayName: string; + readonly names: readonly string[]; + readonly extension: string; +} + +export abstract class TargetLanguage implements LanguageConfig { + abstract readonly displayName: string; + abstract readonly names: readonly string[]; + abstract readonly extension: string; protected abstract getOptions(): Option[]; @@ -36,7 +40,7 @@ export abstract class TargetLanguage { return { actual, display }; } - get name(): string { + get name() { return defined(this.names[0]); } diff --git a/packages/quicktype-core/src/language/CJSON.ts b/packages/quicktype-core/src/language/CJSON.ts index 8dd1990b2..9a1d880b9 100644 --- a/packages/quicktype-core/src/language/CJSON.ts +++ b/packages/quicktype-core/src/language/CJSON.ts @@ -13,7 +13,7 @@ * To print json string from json data use the following: char * string = cJSON_Print(); * To delete json data use the following: cJSON_Delete(); * - * TODO list for futur enhancements: + * TODO list for future enhancements: * - Management of Class, Union and TopLevel should be mutualized to reduce code size and to permit Union and TopLevel having recursive Array/Map * - Types check should be added to verify unwanted inputs (for example a Number passed while a String is expected, etc) * - Constraints should be implemented (verification of Enum values, min/max values for Numbers and min/max length for Strings, regex) @@ -22,7 +22,7 @@ */ /* Imports */ -import { TargetLanguage } from "../TargetLanguage"; +import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; import { Type, TypeKind, ClassType, ArrayType, MapType, EnumType, UnionType } from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; import { NameStyle, Name, Namer, funPrefixNamer } from "../Naming"; @@ -128,16 +128,10 @@ export const cJSONOptions = { }; /* cJSON generator target language */ -export class CJSONTargetLanguage extends TargetLanguage { - /** - * Constructor - * @param displayName: display name - * @params names: names - * @param extension: extension of files - */ - constructor(displayName = "C (cJSON)", names: string[] = ["cjson", "cJSON"], extension = "h") { - super(displayName, names, extension); - } +export class CJSONTargetLanguage extends TargetLanguage implements LanguageConfig { + readonly displayName = "C (cJSON)" as const; + readonly names = ["cjson", "cJSON"] as const; + readonly extension = "h" as const; /** * Return cJSON generator options diff --git a/packages/quicktype-core/src/language/CPlusPlus.ts b/packages/quicktype-core/src/language/CPlusPlus.ts index 03cdf6285..c208a36e2 100644 --- a/packages/quicktype-core/src/language/CPlusPlus.ts +++ b/packages/quicktype-core/src/language/CPlusPlus.ts @@ -8,7 +8,7 @@ import { withDefault } from "collection-utils"; -import { TargetLanguage } from "../TargetLanguage"; +import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; import { Type, TypeKind, ClassType, ClassProperty, ArrayType, MapType, EnumType, UnionType } from "../Type"; import { nullableFromUnion, matchType, removeNullFromUnion, isNamedType, directlyReachableTypes } from "../TypeUtils"; import { NameStyle, Name, Namer, funPrefixNamer, DependencyName } from "../Naming"; @@ -118,10 +118,10 @@ export const cPlusPlusOptions = { hideNullOptional: new BooleanOption("hide-null-optional", "Hide null value for optional field", false) }; -export class CPlusPlusTargetLanguage extends TargetLanguage { - constructor(displayName = "C++", names: string[] = ["c++", "cpp", "cplusplus"], extension = "cpp") { - super(displayName, names, extension); - } +export class CPlusPlusTargetLanguage extends TargetLanguage implements LanguageConfig { + readonly displayName = "C++" as const; + readonly names = ["c++", "cpp", "cplusplus"] as const; + readonly extension = "cpp" as const; protected getOptions(): Option[] { return [ diff --git a/packages/quicktype-core/src/language/CSharp.ts b/packages/quicktype-core/src/language/CSharp.ts index 627e387be..b0c1cea49 100644 --- a/packages/quicktype-core/src/language/CSharp.ts +++ b/packages/quicktype-core/src/language/CSharp.ts @@ -25,7 +25,7 @@ import { import { defined, assert, panic, assertNever } from "../support/Support"; import { Name, DependencyName, Namer, funPrefixNamer, SimpleName } from "../Naming"; import { ConvenienceRenderer, ForbiddenWordsInfo, inferredNameOrder } from "../ConvenienceRenderer"; -import { TargetLanguage } from "../TargetLanguage"; +import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; import { StringOption, EnumOption, Option, BooleanOption, OptionValues, getOptionValues } from "../RendererOptions"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; import { StringTypeMapping } from "../TypeBuilder"; @@ -194,10 +194,10 @@ export const cSharpOptions = { keepPropertyName: new BooleanOption("keep-property-name", "Keep original field name generate", false) }; -export class CSharpTargetLanguage extends TargetLanguage { - constructor() { - super("C#", ["cs", "csharp"], "cs"); - } +export class CSharpTargetLanguage extends TargetLanguage implements LanguageConfig { + readonly displayName = "C#" as const; + readonly names = ["cs", "csharp"] as const; + readonly extension = "cs" as const; protected getOptions(): Option[] { return [ diff --git a/packages/quicktype-core/src/language/Crystal.ts b/packages/quicktype-core/src/language/Crystal.ts index ae08ac743..347618905 100644 --- a/packages/quicktype-core/src/language/Crystal.ts +++ b/packages/quicktype-core/src/language/Crystal.ts @@ -1,4 +1,4 @@ -import { TargetLanguage } from "../TargetLanguage"; +import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; import { legalizeCharacters, @@ -22,10 +22,10 @@ import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; import { Option } from "../RendererOptions"; import { RenderContext } from "../Renderer"; -export class CrystalTargetLanguage extends TargetLanguage { - constructor() { - super("Crystal", ["crystal", "cr", "crystallang"], "cr"); - } +export class CrystalTargetLanguage extends TargetLanguage implements LanguageConfig { + readonly displayName = "Crystal" as const; + readonly names = ["crystal", "cr", "crystallang"] as const; + readonly extension = "cr" as const; protected makeRenderer(renderContext: RenderContext): CrystalRenderer { return new CrystalRenderer(this, renderContext); diff --git a/packages/quicktype-core/src/language/Dart.ts b/packages/quicktype-core/src/language/Dart.ts index 6dc40ead6..6c842c531 100644 --- a/packages/quicktype-core/src/language/Dart.ts +++ b/packages/quicktype-core/src/language/Dart.ts @@ -31,7 +31,7 @@ import { StringTypeMapping } from "../TypeBuilder"; import { DependencyName, funPrefixNamer, Name, Namer } from "../Naming"; import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { TargetLanguage } from "../TargetLanguage"; +import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; import { BooleanOption, getOptionValues, Option, OptionValues, StringOption } from "../RendererOptions"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; import { defined } from "../support/Support"; @@ -61,10 +61,10 @@ export const dartOptions = { partName: new StringOption("part-name", "Use this name in `part` directive", "NAME", "", "secondary") }; -export class DartTargetLanguage extends TargetLanguage { - constructor() { - super("Dart", ["dart"], "dart"); - } +export class DartTargetLanguage extends TargetLanguage implements LanguageConfig { + readonly displayName = "Dart" as const; + readonly names = ["dart"] as const; + readonly extension = "dart" as const; protected getOptions(): Option[] { return [ @@ -200,8 +200,8 @@ function dartNameStyle(startWithUpper: boolean, upperUnderscore: boolean, origin const firstWordStyle = upperUnderscore ? allUpperWordStyle : startWithUpper - ? firstUpperWordStyle - : allLowerWordStyle; + ? firstUpperWordStyle + : allLowerWordStyle; const restWordStyle = upperUnderscore ? allUpperWordStyle : firstUpperWordStyle; return combineWords( words, diff --git a/packages/quicktype-core/src/language/Elm.ts b/packages/quicktype-core/src/language/Elm.ts index bab36c541..9f27107b3 100644 --- a/packages/quicktype-core/src/language/Elm.ts +++ b/packages/quicktype-core/src/language/Elm.ts @@ -1,6 +1,6 @@ import { mapContains, arrayIntercalate } from "collection-utils"; -import { TargetLanguage } from "../TargetLanguage"; +import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; import { EnumOption, StringOption, BooleanOption, Option, getOptionValues, OptionValues } from "../RendererOptions"; import { Type, ClassType, UnionType, EnumType, ClassProperty } from "../Type"; import { matchType, nullableFromUnion } from "../TypeUtils"; @@ -34,10 +34,10 @@ export const elmOptions = { moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType") }; -export class ElmTargetLanguage extends TargetLanguage { - constructor() { - super("Elm", ["elm"], "elm"); - } +export class ElmTargetLanguage extends TargetLanguage implements LanguageConfig { + readonly displayName = "Elm" as const; + readonly names = ["elm"] as const; + readonly extension = "elm" as const; protected getOptions(): Option[] { return [elmOptions.justTypes, elmOptions.moduleName, elmOptions.useList]; diff --git a/packages/quicktype-core/src/language/Golang.ts b/packages/quicktype-core/src/language/Golang.ts index fb3c7b8f7..373f61098 100644 --- a/packages/quicktype-core/src/language/Golang.ts +++ b/packages/quicktype-core/src/language/Golang.ts @@ -16,7 +16,7 @@ import { assert, defined } from "../support/Support"; import { StringOption, BooleanOption, Option, OptionValues, getOptionValues } from "../RendererOptions"; import { Sourcelike, maybeAnnotated, modifySource } from "../Source"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { TargetLanguage } from "../TargetLanguage"; +import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; import { RenderContext } from "../Renderer"; import { StringTypeMapping, TransformedStringTypeKind, PrimitiveStringTypeKind } from ".."; @@ -34,10 +34,10 @@ export const goOptions = { ) }; -export class GoTargetLanguage extends TargetLanguage { - constructor() { - super("Go", ["go", "golang"], "go"); - } +export class GoTargetLanguage extends TargetLanguage implements LanguageConfig { + readonly displayName = "Go" as const; + readonly names = ["go", "golang"] as const; + readonly extension = "go" as const; protected getOptions(): Option[] { return [ diff --git a/packages/quicktype-core/src/language/Haskell.ts b/packages/quicktype-core/src/language/Haskell.ts index 2bac412e9..e568d3575 100644 --- a/packages/quicktype-core/src/language/Haskell.ts +++ b/packages/quicktype-core/src/language/Haskell.ts @@ -1,5 +1,5 @@ import { mapContains } from "collection-utils"; -import { TargetLanguage } from "../TargetLanguage"; +import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; import { EnumOption, StringOption, BooleanOption, Option, getOptionValues, OptionValues } from "../RendererOptions"; import { Type, ClassType, UnionType, EnumType, ClassProperty } from "../Type"; import { matchType, nullableFromUnion } from "../TypeUtils"; @@ -29,10 +29,10 @@ export const haskellOptions = { moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType") }; -export class HaskellTargetLanguage extends TargetLanguage { - constructor() { - super("Haskell", ["haskell"], "haskell"); - } +export class HaskellTargetLanguage extends TargetLanguage implements LanguageConfig { + readonly displayName = "Haskell" as const; + readonly names = ["haskell"] as const; + readonly extension = "haskell" as const; protected getOptions(): Option[] { return [haskellOptions.justTypes, haskellOptions.moduleName, haskellOptions.useList]; diff --git a/packages/quicktype-core/src/language/JSONSchema.ts b/packages/quicktype-core/src/language/JSONSchema.ts index 2b8a447ba..b276e8149 100644 --- a/packages/quicktype-core/src/language/JSONSchema.ts +++ b/packages/quicktype-core/src/language/JSONSchema.ts @@ -1,6 +1,6 @@ import { mapFirst, iterableFirst } from "collection-utils"; -import { TargetLanguage } from "../TargetLanguage"; +import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; import { Type, UnionType, EnumType, ObjectType, transformedStringTypeTargetTypeKindsMap } from "../Type"; import { matchTypeExhaustive } from "../TypeUtils"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; @@ -18,10 +18,10 @@ import { addDescriptionToSchema } from "../attributes/Description"; import { Option } from "../RendererOptions"; import { RenderContext } from "../Renderer"; -export class JSONSchemaTargetLanguage extends TargetLanguage { - constructor() { - super("JSON Schema", ["schema", "json-schema"], "schema"); - } +export class JSONSchemaTargetLanguage extends TargetLanguage implements LanguageConfig { + readonly displayName = "JSON Schema" as const; + readonly names = ["schema", "json-schema"] as const; + readonly extension = "schema" as const; protected getOptions(): Option[] { return []; diff --git a/packages/quicktype-core/src/language/Java.ts b/packages/quicktype-core/src/language/Java.ts index 05ad4b535..a661bb640 100644 --- a/packages/quicktype-core/src/language/Java.ts +++ b/packages/quicktype-core/src/language/Java.ts @@ -21,7 +21,7 @@ import { utf16LegalizeCharacters } from "../support/Strings"; import { assert, assertNever, defined, panic } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; +import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; import { ArrayType, ClassProperty, ClassType, EnumType, MapType, Type, TypeKind, UnionType } from "../Type"; import { directlyReachableSingleNamedType, matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; import { StringTypeMapping, TransformedStringTypeKind, PrimitiveStringTypeKind } from ".."; @@ -53,10 +53,10 @@ export const javaOptions = { lombokCopyAnnotations: new BooleanOption("lombok-copy-annotations", "Copy accessor annotations", true, "secondary") }; -export class JavaTargetLanguage extends TargetLanguage { - constructor() { - super("Java", ["java"], "java"); - } +export class JavaTargetLanguage extends TargetLanguage implements LanguageConfig { + readonly displayName = "Java" as const; + readonly names = ["java"] as const; + readonly extension = "java" as const; protected getOptions(): Option[] { return [ diff --git a/packages/quicktype-core/src/language/JavaScript.ts b/packages/quicktype-core/src/language/JavaScript.ts index e8e3db9a2..1e255b70f 100644 --- a/packages/quicktype-core/src/language/JavaScript.ts +++ b/packages/quicktype-core/src/language/JavaScript.ts @@ -27,7 +27,7 @@ import { panic } from "../support/Support"; import { Sourcelike, modifySource } from "../Source"; import { Namer, Name, funPrefixNamer } from "../Naming"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { TargetLanguage } from "../TargetLanguage"; +import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; import { StringTypeMapping } from "../TypeBuilder"; import { BooleanOption, Option, OptionValues, getOptionValues, EnumOption } from "../RendererOptions"; import { RenderContext } from "../Renderer"; @@ -65,10 +65,10 @@ export type JavaScriptTypeAnnotations = { never: string; }; -export class JavaScriptTargetLanguage extends TargetLanguage { - constructor(displayName = "JavaScript", names: string[] = ["javascript", "js", "jsx"], extension = "js") { - super(displayName, names, extension); - } +export class JavaScriptTargetLanguage extends TargetLanguage implements LanguageConfig { + readonly displayName = "JavaScript" as const; + readonly names = ["javascript", "js", "jsx"] as const; + readonly extension = "js" as const; protected getOptions(): Option[] { return [ diff --git a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts index 7d35dca10..7a666ec56 100644 --- a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts +++ b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts @@ -1,4 +1,4 @@ -import { TargetLanguage } from "../TargetLanguage"; +import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; import { getOptionValues, Option, OptionValues, EnumOption } from "../RendererOptions"; import { RenderContext } from "../Renderer"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; @@ -39,10 +39,10 @@ export const javaScriptPropTypesOptions = { ) }; -export class JavaScriptPropTypesTargetLanguage extends TargetLanguage { - constructor(displayName = "JavaScript PropTypes", names: string[] = ["javascript-prop-types"], extension = "js") { - super(displayName, names, extension); - } +export class JavaScriptPropTypesTargetLanguage extends TargetLanguage implements LanguageConfig { + readonly displayName = "JavaScript PropTypes" as const; + readonly names = ["javascript-prop-types"] as const; + readonly extension = "js" as const; protected getOptions(): Option[] { return [javaScriptPropTypesOptions.acronymStyle, javaScriptPropTypesOptions.converters]; diff --git a/packages/quicktype-core/src/language/Kotlin.ts b/packages/quicktype-core/src/language/Kotlin.ts index 407b82300..815cc96e4 100644 --- a/packages/quicktype-core/src/language/Kotlin.ts +++ b/packages/quicktype-core/src/language/Kotlin.ts @@ -22,7 +22,7 @@ import { utf32ConcatMap } from "../support/Strings"; import { assertNever, mustNotHappen } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; +import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; import { ArrayType, ClassProperty, @@ -61,10 +61,10 @@ export const kotlinOptions = { packageName: new StringOption("package", "Package", "PACKAGE", "quicktype") }; -export class KotlinTargetLanguage extends TargetLanguage { - constructor() { - super("Kotlin", ["kotlin"], "kt"); - } +export class KotlinTargetLanguage extends TargetLanguage implements LanguageConfig { + readonly displayName = "Kotlin" as const; + readonly names = ["kotlin"] as const; + readonly extension = "kt" as const; protected getOptions(): Option[] { return [kotlinOptions.framework, kotlinOptions.acronymStyle, kotlinOptions.packageName]; diff --git a/packages/quicktype-core/src/language/Objective-C.ts b/packages/quicktype-core/src/language/Objective-C.ts index b1a44e899..b37d3b206 100644 --- a/packages/quicktype-core/src/language/Objective-C.ts +++ b/packages/quicktype-core/src/language/Objective-C.ts @@ -1,6 +1,6 @@ import { iterableSome, iterableFirst, mapContains, mapFirst, mapSome } from "collection-utils"; -import { TargetLanguage } from "../TargetLanguage"; +import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; import { Type, ClassType, EnumType, ArrayType, MapType, UnionType, ClassProperty } from "../Type"; import { matchType, nullableFromUnion, isAnyOrNull } from "../TypeUtils"; import { Name, Namer, funPrefixNamer } from "../Naming"; @@ -43,10 +43,10 @@ export const objcOptions = { extraComments: new BooleanOption("extra-comments", "Extra comments", false) }; -export class ObjectiveCTargetLanguage extends TargetLanguage { - constructor() { - super("Objective-C", ["objc", "objective-c", "objectivec"], "m"); - } +export class ObjectiveCTargetLanguage extends TargetLanguage implements LanguageConfig { + readonly displayName = "Objective-C" as const; + readonly names = ["objc", "objective-c", "objectivec"] as const; + readonly extension = "m" as const; protected getOptions(): Option[] { return [ diff --git a/packages/quicktype-core/src/language/Php.ts b/packages/quicktype-core/src/language/Php.ts index 670b09cc1..8effe83c6 100644 --- a/packages/quicktype-core/src/language/Php.ts +++ b/packages/quicktype-core/src/language/Php.ts @@ -20,7 +20,7 @@ import { utf16LegalizeCharacters } from "../support/Strings"; import { defined } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; +import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; import { ClassProperty, ClassType, EnumType, Type, UnionType } from "../Type"; import { directlyReachableSingleNamedType, matchType, nullableFromUnion } from "../TypeUtils"; import { StringTypeMapping, TransformedStringTypeKind, PrimitiveStringTypeKind } from ".."; @@ -34,10 +34,10 @@ export const phpOptions = { acronymStyle: acronymOption(AcronymStyleOptions.Pascal) }; -export class PhpTargetLanguage extends TargetLanguage { - constructor() { - super("PHP", ["php"], "php"); - } +export class PhpTargetLanguage extends TargetLanguage implements LanguageConfig { + readonly displayName = "PHP" as const; + readonly names = ["php"] as const; + readonly extension = "php" as const; protected getOptions(): Option[] { return _.values(phpOptions); diff --git a/packages/quicktype-core/src/language/Pike.ts b/packages/quicktype-core/src/language/Pike.ts index d2d9541b7..9436f40cf 100644 --- a/packages/quicktype-core/src/language/Pike.ts +++ b/packages/quicktype-core/src/language/Pike.ts @@ -3,7 +3,7 @@ import { Name, Namer, funPrefixNamer } from "../Naming"; import { Option } from "../RendererOptions"; import { RenderContext } from "../Renderer"; import { MultiWord, Sourcelike, multiWord, parenIfNeeded, singleWord } from "../Source"; -import { TargetLanguage } from "../TargetLanguage"; +import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; import { Type, ClassType, EnumType, UnionType, ArrayType, MapType, PrimitiveType } from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; import { legalizeCharacters, isLetterOrUnderscoreOrDigit, stringEscape, makeNameStyle } from "../support/Strings"; @@ -70,10 +70,10 @@ const enumNamingFunction = funPrefixNamer("enumNamer", makeNameStyle("upper-unde const namingFunction = funPrefixNamer("genericNamer", makeNameStyle("underscore", legalizeName)); const namedTypeNamingFunction = funPrefixNamer("typeNamer", makeNameStyle("pascal", legalizeName)); -export class PikeTargetLanguage extends TargetLanguage { - constructor() { - super("Pike", ["pike", "pikelang"], "pmod"); - } +export class PikeTargetLanguage extends TargetLanguage implements LanguageConfig { + readonly displayName = "Pike" as const; + readonly names = ["pike", "pikelang"] as const; + readonly extension = "pmod" as const; protected getOptions(): Option[] { return []; } diff --git a/packages/quicktype-core/src/language/Python.ts b/packages/quicktype-core/src/language/Python.ts index 56182a0a9..252643919 100644 --- a/packages/quicktype-core/src/language/Python.ts +++ b/packages/quicktype-core/src/language/Python.ts @@ -1,4 +1,4 @@ -import { TargetLanguage } from "../TargetLanguage"; +import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; import { StringTypeMapping } from "../TypeBuilder"; import { TransformedStringTypeKind, @@ -129,10 +129,10 @@ export const pythonOptions = { nicePropertyNames: new BooleanOption("nice-property-names", "Transform property names to be Pythonic", true) }; -export class PythonTargetLanguage extends TargetLanguage { - constructor() { - super("Python", ["python", "py"], "py"); - } +export class PythonTargetLanguage extends TargetLanguage implements LanguageConfig { + readonly displayName = "Python" as const; + readonly names = ["python", "py"] as const; + readonly extension = "py" as const; protected getOptions(): Option[] { return [pythonOptions.features, pythonOptions.justTypes, pythonOptions.nicePropertyNames]; diff --git a/packages/quicktype-core/src/language/Rust.ts b/packages/quicktype-core/src/language/Rust.ts index f938483d5..d87aa7157 100644 --- a/packages/quicktype-core/src/language/Rust.ts +++ b/packages/quicktype-core/src/language/Rust.ts @@ -1,6 +1,6 @@ import { mapFirst } from "collection-utils"; -import { TargetLanguage } from "../TargetLanguage"; +import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; import { legalizeCharacters, @@ -111,10 +111,10 @@ const namingStyles: Record = { } }; -export class RustTargetLanguage extends TargetLanguage { - constructor() { - super("Rust", ["rust", "rs", "rustlang"], "rs"); - } +export class RustTargetLanguage extends TargetLanguage implements LanguageConfig { + readonly displayName = "Rust" as const; + readonly names = ["rust", "rs", "rustlang"] as const; + readonly extension = "rs" as const; protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): RustRenderer { return new RustRenderer(this, renderContext, getOptionValues(rustOptions, untypedOptionValues)); diff --git a/packages/quicktype-core/src/language/Scala3.ts b/packages/quicktype-core/src/language/Scala3.ts index 56437c02b..baa36ba5d 100644 --- a/packages/quicktype-core/src/language/Scala3.ts +++ b/packages/quicktype-core/src/language/Scala3.ts @@ -15,7 +15,7 @@ import { splitIntoWords } from "../support/Strings"; import { assertNever } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; +import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; import { ArrayType, ClassProperty, ClassType, EnumType, MapType, ObjectType, Type, UnionType } from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; import { RenderContext } from "../Renderer"; @@ -245,10 +245,10 @@ export class Scala3Renderer extends ConvenienceRenderer { delimiter === "curly" ? ["{", "}"] : delimiter === "paren" - ? ["(", ")"] - : delimiter === "none" - ? ["", ""] - : ["{", "})"]; + ? ["(", ")"] + : delimiter === "none" + ? ["", ""] + : ["{", "})"]; this.emitLine(line, " ", open); this.indent(f); this.emitLine(close); @@ -724,10 +724,10 @@ export class CirceRenderer extends Scala3Renderer { } } -export class Scala3TargetLanguage extends TargetLanguage { - constructor() { - super("Scala3", ["scala3"], "scala"); - } +export class Scala3TargetLanguage extends TargetLanguage implements LanguageConfig { + readonly displayName = "Scala3" as const; + readonly names = ["scala3"] as const; + readonly extension = "scala" as const; protected getOptions(): Option[] { return [scala3Options.framework, scala3Options.packageName]; diff --git a/packages/quicktype-core/src/language/Smithy4s.ts b/packages/quicktype-core/src/language/Smithy4s.ts index 3a875be64..9cc8ea1ed 100644 --- a/packages/quicktype-core/src/language/Smithy4s.ts +++ b/packages/quicktype-core/src/language/Smithy4s.ts @@ -15,7 +15,7 @@ import { splitIntoWords } from "../support/Strings"; import { assertNever } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; +import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; import { ArrayType, ClassProperty, ClassType, EnumType, MapType, ObjectType, Type, UnionType } from "../Type"; import { matchCompoundType, matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; import { RenderContext } from "../Renderer"; @@ -205,10 +205,10 @@ export class Smithy4sRenderer extends ConvenienceRenderer { delimiter === "curly" ? ["{", "}"] : delimiter === "paren" - ? ["(", ")"] - : delimiter === "none" - ? ["", ""] - : ["{", "})"]; + ? ["(", ")"] + : delimiter === "none" + ? ["", ""] + : ["{", "})"]; this.emitLine(line, " ", open); this.indent(f); this.emitLine(close); @@ -510,10 +510,10 @@ export class Smithy4sRenderer extends ConvenienceRenderer { } } -export class SmithyTargetLanguage extends TargetLanguage { - constructor() { - super("Smithy", ["Smithy"], "smithy"); - } +export class SmithyTargetLanguage extends TargetLanguage implements LanguageConfig { + readonly displayName = "Smithy" as const; + readonly names = ["Smithy"] as const; + readonly extension = "smithy" as const; protected getOptions(): Option[] { return [SmithyOptions.framework, SmithyOptions.packageName]; diff --git a/packages/quicktype-core/src/language/Swift.ts b/packages/quicktype-core/src/language/Swift.ts index 04fc431a1..8ec666ad1 100644 --- a/packages/quicktype-core/src/language/Swift.ts +++ b/packages/quicktype-core/src/language/Swift.ts @@ -1,7 +1,7 @@ import { arrayIntercalate } from "collection-utils"; import { assert, defined } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; +import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; import { Type, ClassType, @@ -130,10 +130,10 @@ export interface SwiftProperty { position: ForEachPosition; } -export class SwiftTargetLanguage extends TargetLanguage { - constructor() { - super("Swift", ["swift", "swift4"], "swift"); - } +export class SwiftTargetLanguage extends TargetLanguage implements LanguageConfig { + readonly displayName = "Swift" as const; + readonly names = ["swift", "swift4"] as const; + readonly extension = "swift" as const; protected getOptions(): Option[] { return [ diff --git a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts index 4e46b65e3..5c025108a 100644 --- a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts +++ b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts @@ -15,7 +15,7 @@ import { stringEscape, utf16StringEscape } from "../support/Strings"; -import { TargetLanguage } from "../TargetLanguage"; +import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; import { legalizeName } from "./JavaScript"; import { Sourcelike } from "../Source"; import { panic } from "../support/Support"; @@ -25,14 +25,10 @@ export const typeScriptEffectSchemaOptions = { justSchema: new BooleanOption("just-schema", "Schema only", false) }; -export class TypeScriptEffectSchemaTargetLanguage extends TargetLanguage { - constructor( - displayName: string = "TypeScript Effect Schema", - names: string[] = ["typescript-effect-schema"], - extension: string = "ts" - ) { - super(displayName, names, extension); - } +export class TypeScriptEffectSchemaTargetLanguage extends TargetLanguage implements LanguageConfig { + readonly displayName = "TypeScript Effect Schema" as const; + readonly names = ["typescript-effect-schema"] as const; + readonly extension = "ts" as const; protected getOptions(): Option[] { return []; diff --git a/packages/quicktype-core/src/language/TypeScriptFlow.ts b/packages/quicktype-core/src/language/TypeScriptFlow.ts index 0c5750006..e9bbda153 100644 --- a/packages/quicktype-core/src/language/TypeScriptFlow.ts +++ b/packages/quicktype-core/src/language/TypeScriptFlow.ts @@ -13,7 +13,7 @@ import { legalizeName } from "./JavaScript"; import { defined, panic } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; +import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; import { RenderContext } from "../Renderer"; import { isES3IdentifierStart } from "./JavaScriptUnicodeMaps"; @@ -66,10 +66,13 @@ export abstract class TypeScriptFlowBaseTargetLanguage extends JavaScriptTargetL ): JavaScriptRenderer; } -export class TypeScriptTargetLanguage extends TypeScriptFlowBaseTargetLanguage { - constructor() { - super("TypeScript", ["typescript", "ts", "tsx"], "ts"); - } +export class TypeScriptTargetLanguage extends TypeScriptFlowBaseTargetLanguage implements LanguageConfig { + // @ts-expect-error + readonly displayName = "TypeScript" as const; + // @ts-expect-error + readonly names = ["typescript", "ts", "tsx"] as const; + // @ts-expect-error + readonly extension = "ts" as const; protected makeRenderer( renderContext: RenderContext, @@ -330,9 +333,11 @@ export class TypeScriptRenderer extends TypeScriptFlowBaseRenderer { } export class FlowTargetLanguage extends TypeScriptFlowBaseTargetLanguage { - constructor() { - super("Flow", ["flow"], "js"); - } + // @ts-expect-error + readonly displayName = "Flow" as const; + // @ts-expect-error + readonly names = ["flow"] as const; + readonly extension = "js" as const; protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): FlowRenderer { return new FlowRenderer(this, renderContext, getOptionValues(tsFlowOptions, untypedOptionValues)); diff --git a/packages/quicktype-core/src/language/TypeScriptZod.ts b/packages/quicktype-core/src/language/TypeScriptZod.ts index 00f67ecdb..482e1f4e1 100644 --- a/packages/quicktype-core/src/language/TypeScriptZod.ts +++ b/packages/quicktype-core/src/language/TypeScriptZod.ts @@ -5,7 +5,7 @@ import { Name, Namer, funPrefixNamer } from "../Naming"; import { RenderContext } from "../Renderer"; import { BooleanOption, Option, OptionValues, getOptionValues } from "../RendererOptions"; import { Sourcelike } from "../Source"; -import { TargetLanguage } from "../TargetLanguage"; +import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; import { ArrayType, ClassProperty, @@ -36,14 +36,10 @@ export const typeScriptZodOptions = { justSchema: new BooleanOption("just-schema", "Schema only", false) }; -export class TypeScriptZodTargetLanguage extends TargetLanguage { - constructor( - displayName: string = "TypeScript Zod", - names: string[] = ["typescript-zod"], - extension: string = "ts" - ) { - super(displayName, names, extension); - } +export class TypeScriptZodTargetLanguage extends TargetLanguage implements LanguageConfig { + readonly displayName = "TypeScript Zod" as const; + readonly names = ["typescript-zod"] as const; + readonly extension = "ts" as const; protected getOptions(): Option[] { return []; diff --git a/packages/quicktype-core/src/language/ruby/index.ts b/packages/quicktype-core/src/language/ruby/index.ts index 383bdd5ae..bd65e25be 100644 --- a/packages/quicktype-core/src/language/ruby/index.ts +++ b/packages/quicktype-core/src/language/ruby/index.ts @@ -3,13 +3,9 @@ import unicode from "unicode-properties"; import { Sourcelike, modifySource } from "../../Source"; import { Namer, Name } from "../../Naming"; import { ConvenienceRenderer, ForbiddenWordsInfo } from "../../ConvenienceRenderer"; -import { TargetLanguage } from "../../TargetLanguage"; +import { type LanguageConfig, TargetLanguage } from "../../TargetLanguage"; import { Option, BooleanOption, EnumOption, OptionValues, getOptionValues, StringOption } from "../../RendererOptions"; -import * as keywords from "./keywords"; - -const forbiddenForObjectProperties = Array.from(new Set([...keywords.keywords, ...keywords.reservedProperties])); - import { Type, EnumType, ClassType, UnionType, ArrayType, MapType, ClassProperty } from "../../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../../TypeUtils"; @@ -29,6 +25,10 @@ import { } from "../../support/Strings"; import { RenderContext } from "../../Renderer"; +import * as keywords from "./keywords"; + +const forbiddenForObjectProperties = Array.from(new Set([...keywords.keywords, ...keywords.reservedProperties])); + function unicodeEscape(codePoint: number): string { return "\\u{" + intToHex(codePoint, 0) + "}"; } @@ -51,10 +51,10 @@ export const rubyOptions = { namespace: new StringOption("namespace", "Specify a wrapping Namespace", "NAME", "", "secondary") }; -export class RubyTargetLanguage extends TargetLanguage { - constructor() { - super("Ruby", ["ruby"], "rb"); - } +export class RubyTargetLanguage extends TargetLanguage implements LanguageConfig { + readonly displayName = "Ruby" as const; + readonly names = ["ruby"] as const; + readonly extension = "rb" as const; protected getOptions(): Option[] { return [rubyOptions.justTypes, rubyOptions.strictness, rubyOptions.namespace]; From 0822babca840e10cf2c3cecd63343f9f784ecaa2 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 6 Apr 2024 07:26:34 -0700 Subject: [PATCH 11/94] add strict typing for language name --- packages/quicktype-core/src/Run.ts | 5 +- packages/quicktype-core/src/language/All.ts | 58 ++++++++++----------- packages/quicktype-core/src/types.ts | 14 +++++ 3 files changed, 46 insertions(+), 31 deletions(-) create mode 100644 packages/quicktype-core/src/types.ts diff --git a/packages/quicktype-core/src/Run.ts b/packages/quicktype-core/src/Run.ts index 195417cb9..aa85f783e 100644 --- a/packages/quicktype-core/src/Run.ts +++ b/packages/quicktype-core/src/Run.ts @@ -20,8 +20,9 @@ import { flattenStrings } from "./rewrites/FlattenStrings"; import { makeTransformations } from "./MakeTransformations"; import { TransformedStringTypeKind } from "./Type"; import { type Comment } from "./support/Comments"; +import type { LanguageName } from "./types"; -export function getTargetLanguage(nameOrInstance: string | TargetLanguage): TargetLanguage { +export function getTargetLanguage(nameOrInstance: LanguageName | TargetLanguage): TargetLanguage { if (typeof nameOrInstance === "object") { return nameOrInstance; } @@ -123,7 +124,7 @@ export type NonInferenceOptions = { * or a string specifying one of the names for quicktype's built-in target languages. For example, * both `cs` and `csharp` will generate C#. */ - lang: string | TargetLanguage; + lang: LanguageName | TargetLanguage; /** The input data from which to produce types */ inputData: InputData; /** Put class properties in alphabetical order, instead of in the order found in the JSON */ diff --git a/packages/quicktype-core/src/language/All.ts b/packages/quicktype-core/src/language/All.ts index f286bb183..0a3a422f6 100644 --- a/packages/quicktype-core/src/language/All.ts +++ b/packages/quicktype-core/src/language/All.ts @@ -1,5 +1,3 @@ -import { iterableFind } from "collection-utils"; - import { TargetLanguage } from "../TargetLanguage"; import { CSharpTargetLanguage } from "./CSharp"; @@ -28,45 +26,47 @@ import { TypeScriptZodTargetLanguage } from "./TypeScriptZod"; import { PhpTargetLanguage } from "./Php"; import { TypeScriptEffectSchemaTargetLanguage } from "./TypeScriptEffectSchema"; +import type { LanguageName, LanguageNameMap } from "../types"; + export const all = [ - new CSharpTargetLanguage(), - new GoTargetLanguage(), - new RustTargetLanguage(), - new CrystalTargetLanguage(), new CJSONTargetLanguage(), new CPlusPlusTargetLanguage(), - new ObjectiveCTargetLanguage(), + new CrystalTargetLanguage(), + new CSharpTargetLanguage(), + new ElmTargetLanguage(), + new DartTargetLanguage(), + new FlowTargetLanguage(), + new GoTargetLanguage(), + new HaskellTargetLanguage(), new JavaTargetLanguage(), - new TypeScriptTargetLanguage(), new JavaScriptTargetLanguage(), new JavaScriptPropTypesTargetLanguage(), - new FlowTargetLanguage(), - new SwiftTargetLanguage(), - new Scala3TargetLanguage(), - new SmithyTargetLanguage(), - new KotlinTargetLanguage(), - new ElmTargetLanguage(), new JSONSchemaTargetLanguage(), - new RubyTargetLanguage(), - new DartTargetLanguage(), - new PythonTargetLanguage(), + new KotlinTargetLanguage(), + new ObjectiveCTargetLanguage(), + new PhpTargetLanguage(), new PikeTargetLanguage(), - new HaskellTargetLanguage(), - new TypeScriptZodTargetLanguage(), + new PythonTargetLanguage(), + new RubyTargetLanguage(), + new RustTargetLanguage(), + new Scala3TargetLanguage(), + new SmithyTargetLanguage(), + new SwiftTargetLanguage(), + new TypeScriptTargetLanguage(), new TypeScriptEffectSchemaTargetLanguage(), - new PhpTargetLanguage() + new TypeScriptZodTargetLanguage() ] as const; all satisfies readonly TargetLanguage[]; -export function languageNamed( - name: string, +export function languageNamed( + name: Name, targetLanguages: readonly TargetLanguage[] = all -): TargetLanguage | undefined { - const maybeTargetLanguage = iterableFind( - targetLanguages, - l => l.names.indexOf(name) >= 0 || l.displayName === name - ); - if (maybeTargetLanguage !== undefined) return maybeTargetLanguage; - return iterableFind(targetLanguages, l => l.extension === name); +): LanguageNameMap[Name] { + const foundLanguage = targetLanguages.find(language => language.names.includes(name)); + if (!foundLanguage) { + throw new Error(`Unknown language name: ${name}`); + } + + return foundLanguage as LanguageNameMap[Name]; } diff --git a/packages/quicktype-core/src/types.ts b/packages/quicktype-core/src/types.ts new file mode 100644 index 000000000..d53fa3b40 --- /dev/null +++ b/packages/quicktype-core/src/types.ts @@ -0,0 +1,14 @@ +import { type TargetLanguage } from "TargetLanguage"; +import type { all } from "./language/All"; + +type AllLanguages = (typeof all)[number]; + +export type LanguageDisplayName = Language["displayName"]; +export type LanguageName = Language["names"][number]; + +export type LanguageDisplayNameMap = { + [Language in AllLanguages as LanguageDisplayName]: Language; +}; +export type LanguageNameMap = { + [Language in AllLanguages as LanguageName]: Language; +}; From 36e8514e868d04fb93bebcb5d181683c5374c379 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 6 Apr 2024 07:54:01 -0700 Subject: [PATCH 12/94] :recycle: --- packages/quicktype-core/src/input/Inputs.ts | 3 ++- packages/quicktype-core/src/language/TypeScriptZod.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/quicktype-core/src/input/Inputs.ts b/packages/quicktype-core/src/input/Inputs.ts index 3baefd9c5..1f6438ff4 100644 --- a/packages/quicktype-core/src/input/Inputs.ts +++ b/packages/quicktype-core/src/input/Inputs.ts @@ -10,6 +10,7 @@ import { TypeInference } from "./Inference"; import { TargetLanguage } from "../TargetLanguage"; import { RunContext } from "../Run"; import { languageNamed } from "../language/All"; +import type { LanguageName } from "../types"; export interface Input { readonly kind: string; @@ -144,7 +145,7 @@ export class JSONInput implements Input> { } export function jsonInputForTargetLanguage( - targetLanguage: string | TargetLanguage, + targetLanguage: LanguageName | TargetLanguage, languages?: TargetLanguage[], handleJSONRefs = false ): JSONInput { diff --git a/packages/quicktype-core/src/language/TypeScriptZod.ts b/packages/quicktype-core/src/language/TypeScriptZod.ts index 482e1f4e1..30d22c4d9 100644 --- a/packages/quicktype-core/src/language/TypeScriptZod.ts +++ b/packages/quicktype-core/src/language/TypeScriptZod.ts @@ -1,5 +1,6 @@ -import { StringTypeMapping } from "TypeBuilder"; import { arrayIntercalate } from "collection-utils"; + +import { StringTypeMapping } from "../TypeBuilder"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; import { Name, Namer, funPrefixNamer } from "../Naming"; import { RenderContext } from "../Renderer"; From 3e5f3453a328bfad229cda03c13ffb2aa3b8afff Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 6 Apr 2024 07:54:38 -0700 Subject: [PATCH 13/94] Revert "move language displayName, names, extension to class static members" This reverts commit 5ca879cbeb74ffb2139d9281943578c8393680ae. --- packages/quicktype-core/src/TargetLanguage.ts | 18 +++++++--------- packages/quicktype-core/src/language/CJSON.ts | 18 ++++++++++------ .../quicktype-core/src/language/CPlusPlus.ts | 10 ++++----- .../quicktype-core/src/language/CSharp.ts | 10 ++++----- .../quicktype-core/src/language/Crystal.ts | 10 ++++----- packages/quicktype-core/src/language/Dart.ts | 14 ++++++------- packages/quicktype-core/src/language/Elm.ts | 10 ++++----- .../quicktype-core/src/language/Golang.ts | 10 ++++----- .../quicktype-core/src/language/Haskell.ts | 10 ++++----- .../quicktype-core/src/language/JSONSchema.ts | 10 ++++----- packages/quicktype-core/src/language/Java.ts | 10 ++++----- .../quicktype-core/src/language/JavaScript.ts | 10 ++++----- .../src/language/JavaScriptPropTypes.ts | 10 ++++----- .../quicktype-core/src/language/Kotlin.ts | 10 ++++----- .../src/language/Objective-C.ts | 10 ++++----- packages/quicktype-core/src/language/Php.ts | 10 ++++----- packages/quicktype-core/src/language/Pike.ts | 10 ++++----- .../quicktype-core/src/language/Python.ts | 10 ++++----- packages/quicktype-core/src/language/Rust.ts | 10 ++++----- .../quicktype-core/src/language/Scala3.ts | 18 ++++++++-------- .../quicktype-core/src/language/Smithy4s.ts | 18 ++++++++-------- packages/quicktype-core/src/language/Swift.ts | 10 ++++----- .../src/language/TypeScriptEffectSchema.ts | 14 ++++++++----- .../src/language/TypeScriptFlow.ts | 21 +++++++------------ .../src/language/TypeScriptZod.ts | 14 ++++++++----- .../quicktype-core/src/language/ruby/index.ts | 18 ++++++++-------- 26 files changed, 164 insertions(+), 159 deletions(-) diff --git a/packages/quicktype-core/src/TargetLanguage.ts b/packages/quicktype-core/src/TargetLanguage.ts index d371594a3..f1c3a90bf 100644 --- a/packages/quicktype-core/src/TargetLanguage.ts +++ b/packages/quicktype-core/src/TargetLanguage.ts @@ -13,16 +13,12 @@ import { type Comment } from "./support/Comments"; export type MultiFileRenderResult = ReadonlyMap; -export interface LanguageConfig { - readonly displayName: string; - readonly names: readonly string[]; - readonly extension: string; -} - -export abstract class TargetLanguage implements LanguageConfig { - abstract readonly displayName: string; - abstract readonly names: readonly string[]; - abstract readonly extension: string; +export abstract class TargetLanguage { + constructor( + readonly displayName: string, + readonly names: string[], + readonly extension: string + ) {} protected abstract getOptions(): Option[]; @@ -40,7 +36,7 @@ export abstract class TargetLanguage implements LanguageConfig { return { actual, display }; } - get name() { + get name(): string { return defined(this.names[0]); } diff --git a/packages/quicktype-core/src/language/CJSON.ts b/packages/quicktype-core/src/language/CJSON.ts index 9a1d880b9..8dd1990b2 100644 --- a/packages/quicktype-core/src/language/CJSON.ts +++ b/packages/quicktype-core/src/language/CJSON.ts @@ -13,7 +13,7 @@ * To print json string from json data use the following: char * string = cJSON_Print(); * To delete json data use the following: cJSON_Delete(); * - * TODO list for future enhancements: + * TODO list for futur enhancements: * - Management of Class, Union and TopLevel should be mutualized to reduce code size and to permit Union and TopLevel having recursive Array/Map * - Types check should be added to verify unwanted inputs (for example a Number passed while a String is expected, etc) * - Constraints should be implemented (verification of Enum values, min/max values for Numbers and min/max length for Strings, regex) @@ -22,7 +22,7 @@ */ /* Imports */ -import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; +import { TargetLanguage } from "../TargetLanguage"; import { Type, TypeKind, ClassType, ArrayType, MapType, EnumType, UnionType } from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; import { NameStyle, Name, Namer, funPrefixNamer } from "../Naming"; @@ -128,10 +128,16 @@ export const cJSONOptions = { }; /* cJSON generator target language */ -export class CJSONTargetLanguage extends TargetLanguage implements LanguageConfig { - readonly displayName = "C (cJSON)" as const; - readonly names = ["cjson", "cJSON"] as const; - readonly extension = "h" as const; +export class CJSONTargetLanguage extends TargetLanguage { + /** + * Constructor + * @param displayName: display name + * @params names: names + * @param extension: extension of files + */ + constructor(displayName = "C (cJSON)", names: string[] = ["cjson", "cJSON"], extension = "h") { + super(displayName, names, extension); + } /** * Return cJSON generator options diff --git a/packages/quicktype-core/src/language/CPlusPlus.ts b/packages/quicktype-core/src/language/CPlusPlus.ts index 702de1bd8..5adff56d2 100644 --- a/packages/quicktype-core/src/language/CPlusPlus.ts +++ b/packages/quicktype-core/src/language/CPlusPlus.ts @@ -8,7 +8,7 @@ import { withDefault } from "collection-utils"; -import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; +import { TargetLanguage } from "../TargetLanguage"; import { Type, TypeKind, ClassType, ClassProperty, ArrayType, MapType, EnumType, UnionType } from "../Type"; import { nullableFromUnion, matchType, removeNullFromUnion, isNamedType, directlyReachableTypes } from "../TypeUtils"; import { NameStyle, Name, Namer, funPrefixNamer, DependencyName } from "../Naming"; @@ -118,10 +118,10 @@ export const cPlusPlusOptions = { hideNullOptional: new BooleanOption("hide-null-optional", "Hide null value for optional field", false) }; -export class CPlusPlusTargetLanguage extends TargetLanguage implements LanguageConfig { - readonly displayName = "C++" as const; - readonly names = ["c++", "cpp", "cplusplus"] as const; - readonly extension = "cpp" as const; +export class CPlusPlusTargetLanguage extends TargetLanguage { + constructor(displayName = "C++", names: string[] = ["c++", "cpp", "cplusplus"], extension = "cpp") { + super(displayName, names, extension); + } protected getOptions(): Option[] { return [ diff --git a/packages/quicktype-core/src/language/CSharp.ts b/packages/quicktype-core/src/language/CSharp.ts index b0c1cea49..627e387be 100644 --- a/packages/quicktype-core/src/language/CSharp.ts +++ b/packages/quicktype-core/src/language/CSharp.ts @@ -25,7 +25,7 @@ import { import { defined, assert, panic, assertNever } from "../support/Support"; import { Name, DependencyName, Namer, funPrefixNamer, SimpleName } from "../Naming"; import { ConvenienceRenderer, ForbiddenWordsInfo, inferredNameOrder } from "../ConvenienceRenderer"; -import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; +import { TargetLanguage } from "../TargetLanguage"; import { StringOption, EnumOption, Option, BooleanOption, OptionValues, getOptionValues } from "../RendererOptions"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; import { StringTypeMapping } from "../TypeBuilder"; @@ -194,10 +194,10 @@ export const cSharpOptions = { keepPropertyName: new BooleanOption("keep-property-name", "Keep original field name generate", false) }; -export class CSharpTargetLanguage extends TargetLanguage implements LanguageConfig { - readonly displayName = "C#" as const; - readonly names = ["cs", "csharp"] as const; - readonly extension = "cs" as const; +export class CSharpTargetLanguage extends TargetLanguage { + constructor() { + super("C#", ["cs", "csharp"], "cs"); + } protected getOptions(): Option[] { return [ diff --git a/packages/quicktype-core/src/language/Crystal.ts b/packages/quicktype-core/src/language/Crystal.ts index 347618905..ae08ac743 100644 --- a/packages/quicktype-core/src/language/Crystal.ts +++ b/packages/quicktype-core/src/language/Crystal.ts @@ -1,4 +1,4 @@ -import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; +import { TargetLanguage } from "../TargetLanguage"; import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; import { legalizeCharacters, @@ -22,10 +22,10 @@ import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; import { Option } from "../RendererOptions"; import { RenderContext } from "../Renderer"; -export class CrystalTargetLanguage extends TargetLanguage implements LanguageConfig { - readonly displayName = "Crystal" as const; - readonly names = ["crystal", "cr", "crystallang"] as const; - readonly extension = "cr" as const; +export class CrystalTargetLanguage extends TargetLanguage { + constructor() { + super("Crystal", ["crystal", "cr", "crystallang"], "cr"); + } protected makeRenderer(renderContext: RenderContext): CrystalRenderer { return new CrystalRenderer(this, renderContext); diff --git a/packages/quicktype-core/src/language/Dart.ts b/packages/quicktype-core/src/language/Dart.ts index 6c842c531..6dc40ead6 100644 --- a/packages/quicktype-core/src/language/Dart.ts +++ b/packages/quicktype-core/src/language/Dart.ts @@ -31,7 +31,7 @@ import { StringTypeMapping } from "../TypeBuilder"; import { DependencyName, funPrefixNamer, Name, Namer } from "../Naming"; import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; +import { TargetLanguage } from "../TargetLanguage"; import { BooleanOption, getOptionValues, Option, OptionValues, StringOption } from "../RendererOptions"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; import { defined } from "../support/Support"; @@ -61,10 +61,10 @@ export const dartOptions = { partName: new StringOption("part-name", "Use this name in `part` directive", "NAME", "", "secondary") }; -export class DartTargetLanguage extends TargetLanguage implements LanguageConfig { - readonly displayName = "Dart" as const; - readonly names = ["dart"] as const; - readonly extension = "dart" as const; +export class DartTargetLanguage extends TargetLanguage { + constructor() { + super("Dart", ["dart"], "dart"); + } protected getOptions(): Option[] { return [ @@ -200,8 +200,8 @@ function dartNameStyle(startWithUpper: boolean, upperUnderscore: boolean, origin const firstWordStyle = upperUnderscore ? allUpperWordStyle : startWithUpper - ? firstUpperWordStyle - : allLowerWordStyle; + ? firstUpperWordStyle + : allLowerWordStyle; const restWordStyle = upperUnderscore ? allUpperWordStyle : firstUpperWordStyle; return combineWords( words, diff --git a/packages/quicktype-core/src/language/Elm.ts b/packages/quicktype-core/src/language/Elm.ts index 9f27107b3..bab36c541 100644 --- a/packages/quicktype-core/src/language/Elm.ts +++ b/packages/quicktype-core/src/language/Elm.ts @@ -1,6 +1,6 @@ import { mapContains, arrayIntercalate } from "collection-utils"; -import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; +import { TargetLanguage } from "../TargetLanguage"; import { EnumOption, StringOption, BooleanOption, Option, getOptionValues, OptionValues } from "../RendererOptions"; import { Type, ClassType, UnionType, EnumType, ClassProperty } from "../Type"; import { matchType, nullableFromUnion } from "../TypeUtils"; @@ -34,10 +34,10 @@ export const elmOptions = { moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType") }; -export class ElmTargetLanguage extends TargetLanguage implements LanguageConfig { - readonly displayName = "Elm" as const; - readonly names = ["elm"] as const; - readonly extension = "elm" as const; +export class ElmTargetLanguage extends TargetLanguage { + constructor() { + super("Elm", ["elm"], "elm"); + } protected getOptions(): Option[] { return [elmOptions.justTypes, elmOptions.moduleName, elmOptions.useList]; diff --git a/packages/quicktype-core/src/language/Golang.ts b/packages/quicktype-core/src/language/Golang.ts index 16ed2d8b6..847bb075d 100644 --- a/packages/quicktype-core/src/language/Golang.ts +++ b/packages/quicktype-core/src/language/Golang.ts @@ -16,7 +16,7 @@ import { assert, defined } from "../support/Support"; import { StringOption, BooleanOption, Option, OptionValues, getOptionValues } from "../RendererOptions"; import { Sourcelike, maybeAnnotated, modifySource } from "../Source"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; +import { TargetLanguage } from "../TargetLanguage"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; import { RenderContext } from "../Renderer"; import { StringTypeMapping, TransformedStringTypeKind, PrimitiveStringTypeKind } from ".."; @@ -34,10 +34,10 @@ export const goOptions = { ) }; -export class GoTargetLanguage extends TargetLanguage implements LanguageConfig { - readonly displayName = "Go" as const; - readonly names = ["go", "golang"] as const; - readonly extension = "go" as const; +export class GoTargetLanguage extends TargetLanguage { + constructor() { + super("Go", ["go", "golang"], "go"); + } protected getOptions(): Option[] { return [ diff --git a/packages/quicktype-core/src/language/Haskell.ts b/packages/quicktype-core/src/language/Haskell.ts index e568d3575..2bac412e9 100644 --- a/packages/quicktype-core/src/language/Haskell.ts +++ b/packages/quicktype-core/src/language/Haskell.ts @@ -1,5 +1,5 @@ import { mapContains } from "collection-utils"; -import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; +import { TargetLanguage } from "../TargetLanguage"; import { EnumOption, StringOption, BooleanOption, Option, getOptionValues, OptionValues } from "../RendererOptions"; import { Type, ClassType, UnionType, EnumType, ClassProperty } from "../Type"; import { matchType, nullableFromUnion } from "../TypeUtils"; @@ -29,10 +29,10 @@ export const haskellOptions = { moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType") }; -export class HaskellTargetLanguage extends TargetLanguage implements LanguageConfig { - readonly displayName = "Haskell" as const; - readonly names = ["haskell"] as const; - readonly extension = "haskell" as const; +export class HaskellTargetLanguage extends TargetLanguage { + constructor() { + super("Haskell", ["haskell"], "haskell"); + } protected getOptions(): Option[] { return [haskellOptions.justTypes, haskellOptions.moduleName, haskellOptions.useList]; diff --git a/packages/quicktype-core/src/language/JSONSchema.ts b/packages/quicktype-core/src/language/JSONSchema.ts index b276e8149..2b8a447ba 100644 --- a/packages/quicktype-core/src/language/JSONSchema.ts +++ b/packages/quicktype-core/src/language/JSONSchema.ts @@ -1,6 +1,6 @@ import { mapFirst, iterableFirst } from "collection-utils"; -import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; +import { TargetLanguage } from "../TargetLanguage"; import { Type, UnionType, EnumType, ObjectType, transformedStringTypeTargetTypeKindsMap } from "../Type"; import { matchTypeExhaustive } from "../TypeUtils"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; @@ -18,10 +18,10 @@ import { addDescriptionToSchema } from "../attributes/Description"; import { Option } from "../RendererOptions"; import { RenderContext } from "../Renderer"; -export class JSONSchemaTargetLanguage extends TargetLanguage implements LanguageConfig { - readonly displayName = "JSON Schema" as const; - readonly names = ["schema", "json-schema"] as const; - readonly extension = "schema" as const; +export class JSONSchemaTargetLanguage extends TargetLanguage { + constructor() { + super("JSON Schema", ["schema", "json-schema"], "schema"); + } protected getOptions(): Option[] { return []; diff --git a/packages/quicktype-core/src/language/Java.ts b/packages/quicktype-core/src/language/Java.ts index a661bb640..05ad4b535 100644 --- a/packages/quicktype-core/src/language/Java.ts +++ b/packages/quicktype-core/src/language/Java.ts @@ -21,7 +21,7 @@ import { utf16LegalizeCharacters } from "../support/Strings"; import { assert, assertNever, defined, panic } from "../support/Support"; -import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; +import { TargetLanguage } from "../TargetLanguage"; import { ArrayType, ClassProperty, ClassType, EnumType, MapType, Type, TypeKind, UnionType } from "../Type"; import { directlyReachableSingleNamedType, matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; import { StringTypeMapping, TransformedStringTypeKind, PrimitiveStringTypeKind } from ".."; @@ -53,10 +53,10 @@ export const javaOptions = { lombokCopyAnnotations: new BooleanOption("lombok-copy-annotations", "Copy accessor annotations", true, "secondary") }; -export class JavaTargetLanguage extends TargetLanguage implements LanguageConfig { - readonly displayName = "Java" as const; - readonly names = ["java"] as const; - readonly extension = "java" as const; +export class JavaTargetLanguage extends TargetLanguage { + constructor() { + super("Java", ["java"], "java"); + } protected getOptions(): Option[] { return [ diff --git a/packages/quicktype-core/src/language/JavaScript.ts b/packages/quicktype-core/src/language/JavaScript.ts index 1e255b70f..e8e3db9a2 100644 --- a/packages/quicktype-core/src/language/JavaScript.ts +++ b/packages/quicktype-core/src/language/JavaScript.ts @@ -27,7 +27,7 @@ import { panic } from "../support/Support"; import { Sourcelike, modifySource } from "../Source"; import { Namer, Name, funPrefixNamer } from "../Naming"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; +import { TargetLanguage } from "../TargetLanguage"; import { StringTypeMapping } from "../TypeBuilder"; import { BooleanOption, Option, OptionValues, getOptionValues, EnumOption } from "../RendererOptions"; import { RenderContext } from "../Renderer"; @@ -65,10 +65,10 @@ export type JavaScriptTypeAnnotations = { never: string; }; -export class JavaScriptTargetLanguage extends TargetLanguage implements LanguageConfig { - readonly displayName = "JavaScript" as const; - readonly names = ["javascript", "js", "jsx"] as const; - readonly extension = "js" as const; +export class JavaScriptTargetLanguage extends TargetLanguage { + constructor(displayName = "JavaScript", names: string[] = ["javascript", "js", "jsx"], extension = "js") { + super(displayName, names, extension); + } protected getOptions(): Option[] { return [ diff --git a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts index 7a666ec56..7d35dca10 100644 --- a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts +++ b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts @@ -1,4 +1,4 @@ -import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; +import { TargetLanguage } from "../TargetLanguage"; import { getOptionValues, Option, OptionValues, EnumOption } from "../RendererOptions"; import { RenderContext } from "../Renderer"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; @@ -39,10 +39,10 @@ export const javaScriptPropTypesOptions = { ) }; -export class JavaScriptPropTypesTargetLanguage extends TargetLanguage implements LanguageConfig { - readonly displayName = "JavaScript PropTypes" as const; - readonly names = ["javascript-prop-types"] as const; - readonly extension = "js" as const; +export class JavaScriptPropTypesTargetLanguage extends TargetLanguage { + constructor(displayName = "JavaScript PropTypes", names: string[] = ["javascript-prop-types"], extension = "js") { + super(displayName, names, extension); + } protected getOptions(): Option[] { return [javaScriptPropTypesOptions.acronymStyle, javaScriptPropTypesOptions.converters]; diff --git a/packages/quicktype-core/src/language/Kotlin.ts b/packages/quicktype-core/src/language/Kotlin.ts index 815cc96e4..407b82300 100644 --- a/packages/quicktype-core/src/language/Kotlin.ts +++ b/packages/quicktype-core/src/language/Kotlin.ts @@ -22,7 +22,7 @@ import { utf32ConcatMap } from "../support/Strings"; import { assertNever, mustNotHappen } from "../support/Support"; -import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; +import { TargetLanguage } from "../TargetLanguage"; import { ArrayType, ClassProperty, @@ -61,10 +61,10 @@ export const kotlinOptions = { packageName: new StringOption("package", "Package", "PACKAGE", "quicktype") }; -export class KotlinTargetLanguage extends TargetLanguage implements LanguageConfig { - readonly displayName = "Kotlin" as const; - readonly names = ["kotlin"] as const; - readonly extension = "kt" as const; +export class KotlinTargetLanguage extends TargetLanguage { + constructor() { + super("Kotlin", ["kotlin"], "kt"); + } protected getOptions(): Option[] { return [kotlinOptions.framework, kotlinOptions.acronymStyle, kotlinOptions.packageName]; diff --git a/packages/quicktype-core/src/language/Objective-C.ts b/packages/quicktype-core/src/language/Objective-C.ts index b37d3b206..b1a44e899 100644 --- a/packages/quicktype-core/src/language/Objective-C.ts +++ b/packages/quicktype-core/src/language/Objective-C.ts @@ -1,6 +1,6 @@ import { iterableSome, iterableFirst, mapContains, mapFirst, mapSome } from "collection-utils"; -import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; +import { TargetLanguage } from "../TargetLanguage"; import { Type, ClassType, EnumType, ArrayType, MapType, UnionType, ClassProperty } from "../Type"; import { matchType, nullableFromUnion, isAnyOrNull } from "../TypeUtils"; import { Name, Namer, funPrefixNamer } from "../Naming"; @@ -43,10 +43,10 @@ export const objcOptions = { extraComments: new BooleanOption("extra-comments", "Extra comments", false) }; -export class ObjectiveCTargetLanguage extends TargetLanguage implements LanguageConfig { - readonly displayName = "Objective-C" as const; - readonly names = ["objc", "objective-c", "objectivec"] as const; - readonly extension = "m" as const; +export class ObjectiveCTargetLanguage extends TargetLanguage { + constructor() { + super("Objective-C", ["objc", "objective-c", "objectivec"], "m"); + } protected getOptions(): Option[] { return [ diff --git a/packages/quicktype-core/src/language/Php.ts b/packages/quicktype-core/src/language/Php.ts index 8effe83c6..670b09cc1 100644 --- a/packages/quicktype-core/src/language/Php.ts +++ b/packages/quicktype-core/src/language/Php.ts @@ -20,7 +20,7 @@ import { utf16LegalizeCharacters } from "../support/Strings"; import { defined } from "../support/Support"; -import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; +import { TargetLanguage } from "../TargetLanguage"; import { ClassProperty, ClassType, EnumType, Type, UnionType } from "../Type"; import { directlyReachableSingleNamedType, matchType, nullableFromUnion } from "../TypeUtils"; import { StringTypeMapping, TransformedStringTypeKind, PrimitiveStringTypeKind } from ".."; @@ -34,10 +34,10 @@ export const phpOptions = { acronymStyle: acronymOption(AcronymStyleOptions.Pascal) }; -export class PhpTargetLanguage extends TargetLanguage implements LanguageConfig { - readonly displayName = "PHP" as const; - readonly names = ["php"] as const; - readonly extension = "php" as const; +export class PhpTargetLanguage extends TargetLanguage { + constructor() { + super("PHP", ["php"], "php"); + } protected getOptions(): Option[] { return _.values(phpOptions); diff --git a/packages/quicktype-core/src/language/Pike.ts b/packages/quicktype-core/src/language/Pike.ts index 9436f40cf..d2d9541b7 100644 --- a/packages/quicktype-core/src/language/Pike.ts +++ b/packages/quicktype-core/src/language/Pike.ts @@ -3,7 +3,7 @@ import { Name, Namer, funPrefixNamer } from "../Naming"; import { Option } from "../RendererOptions"; import { RenderContext } from "../Renderer"; import { MultiWord, Sourcelike, multiWord, parenIfNeeded, singleWord } from "../Source"; -import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; +import { TargetLanguage } from "../TargetLanguage"; import { Type, ClassType, EnumType, UnionType, ArrayType, MapType, PrimitiveType } from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; import { legalizeCharacters, isLetterOrUnderscoreOrDigit, stringEscape, makeNameStyle } from "../support/Strings"; @@ -70,10 +70,10 @@ const enumNamingFunction = funPrefixNamer("enumNamer", makeNameStyle("upper-unde const namingFunction = funPrefixNamer("genericNamer", makeNameStyle("underscore", legalizeName)); const namedTypeNamingFunction = funPrefixNamer("typeNamer", makeNameStyle("pascal", legalizeName)); -export class PikeTargetLanguage extends TargetLanguage implements LanguageConfig { - readonly displayName = "Pike" as const; - readonly names = ["pike", "pikelang"] as const; - readonly extension = "pmod" as const; +export class PikeTargetLanguage extends TargetLanguage { + constructor() { + super("Pike", ["pike", "pikelang"], "pmod"); + } protected getOptions(): Option[] { return []; } diff --git a/packages/quicktype-core/src/language/Python.ts b/packages/quicktype-core/src/language/Python.ts index 252643919..56182a0a9 100644 --- a/packages/quicktype-core/src/language/Python.ts +++ b/packages/quicktype-core/src/language/Python.ts @@ -1,4 +1,4 @@ -import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; +import { TargetLanguage } from "../TargetLanguage"; import { StringTypeMapping } from "../TypeBuilder"; import { TransformedStringTypeKind, @@ -129,10 +129,10 @@ export const pythonOptions = { nicePropertyNames: new BooleanOption("nice-property-names", "Transform property names to be Pythonic", true) }; -export class PythonTargetLanguage extends TargetLanguage implements LanguageConfig { - readonly displayName = "Python" as const; - readonly names = ["python", "py"] as const; - readonly extension = "py" as const; +export class PythonTargetLanguage extends TargetLanguage { + constructor() { + super("Python", ["python", "py"], "py"); + } protected getOptions(): Option[] { return [pythonOptions.features, pythonOptions.justTypes, pythonOptions.nicePropertyNames]; diff --git a/packages/quicktype-core/src/language/Rust.ts b/packages/quicktype-core/src/language/Rust.ts index d87aa7157..f938483d5 100644 --- a/packages/quicktype-core/src/language/Rust.ts +++ b/packages/quicktype-core/src/language/Rust.ts @@ -1,6 +1,6 @@ import { mapFirst } from "collection-utils"; -import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; +import { TargetLanguage } from "../TargetLanguage"; import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; import { legalizeCharacters, @@ -111,10 +111,10 @@ const namingStyles: Record = { } }; -export class RustTargetLanguage extends TargetLanguage implements LanguageConfig { - readonly displayName = "Rust" as const; - readonly names = ["rust", "rs", "rustlang"] as const; - readonly extension = "rs" as const; +export class RustTargetLanguage extends TargetLanguage { + constructor() { + super("Rust", ["rust", "rs", "rustlang"], "rs"); + } protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): RustRenderer { return new RustRenderer(this, renderContext, getOptionValues(rustOptions, untypedOptionValues)); diff --git a/packages/quicktype-core/src/language/Scala3.ts b/packages/quicktype-core/src/language/Scala3.ts index baa36ba5d..56437c02b 100644 --- a/packages/quicktype-core/src/language/Scala3.ts +++ b/packages/quicktype-core/src/language/Scala3.ts @@ -15,7 +15,7 @@ import { splitIntoWords } from "../support/Strings"; import { assertNever } from "../support/Support"; -import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; +import { TargetLanguage } from "../TargetLanguage"; import { ArrayType, ClassProperty, ClassType, EnumType, MapType, ObjectType, Type, UnionType } from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; import { RenderContext } from "../Renderer"; @@ -245,10 +245,10 @@ export class Scala3Renderer extends ConvenienceRenderer { delimiter === "curly" ? ["{", "}"] : delimiter === "paren" - ? ["(", ")"] - : delimiter === "none" - ? ["", ""] - : ["{", "})"]; + ? ["(", ")"] + : delimiter === "none" + ? ["", ""] + : ["{", "})"]; this.emitLine(line, " ", open); this.indent(f); this.emitLine(close); @@ -724,10 +724,10 @@ export class CirceRenderer extends Scala3Renderer { } } -export class Scala3TargetLanguage extends TargetLanguage implements LanguageConfig { - readonly displayName = "Scala3" as const; - readonly names = ["scala3"] as const; - readonly extension = "scala" as const; +export class Scala3TargetLanguage extends TargetLanguage { + constructor() { + super("Scala3", ["scala3"], "scala"); + } protected getOptions(): Option[] { return [scala3Options.framework, scala3Options.packageName]; diff --git a/packages/quicktype-core/src/language/Smithy4s.ts b/packages/quicktype-core/src/language/Smithy4s.ts index 9cc8ea1ed..3a875be64 100644 --- a/packages/quicktype-core/src/language/Smithy4s.ts +++ b/packages/quicktype-core/src/language/Smithy4s.ts @@ -15,7 +15,7 @@ import { splitIntoWords } from "../support/Strings"; import { assertNever } from "../support/Support"; -import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; +import { TargetLanguage } from "../TargetLanguage"; import { ArrayType, ClassProperty, ClassType, EnumType, MapType, ObjectType, Type, UnionType } from "../Type"; import { matchCompoundType, matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; import { RenderContext } from "../Renderer"; @@ -205,10 +205,10 @@ export class Smithy4sRenderer extends ConvenienceRenderer { delimiter === "curly" ? ["{", "}"] : delimiter === "paren" - ? ["(", ")"] - : delimiter === "none" - ? ["", ""] - : ["{", "})"]; + ? ["(", ")"] + : delimiter === "none" + ? ["", ""] + : ["{", "})"]; this.emitLine(line, " ", open); this.indent(f); this.emitLine(close); @@ -510,10 +510,10 @@ export class Smithy4sRenderer extends ConvenienceRenderer { } } -export class SmithyTargetLanguage extends TargetLanguage implements LanguageConfig { - readonly displayName = "Smithy" as const; - readonly names = ["Smithy"] as const; - readonly extension = "smithy" as const; +export class SmithyTargetLanguage extends TargetLanguage { + constructor() { + super("Smithy", ["Smithy"], "smithy"); + } protected getOptions(): Option[] { return [SmithyOptions.framework, SmithyOptions.packageName]; diff --git a/packages/quicktype-core/src/language/Swift.ts b/packages/quicktype-core/src/language/Swift.ts index 8ec666ad1..04fc431a1 100644 --- a/packages/quicktype-core/src/language/Swift.ts +++ b/packages/quicktype-core/src/language/Swift.ts @@ -1,7 +1,7 @@ import { arrayIntercalate } from "collection-utils"; import { assert, defined } from "../support/Support"; -import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; +import { TargetLanguage } from "../TargetLanguage"; import { Type, ClassType, @@ -130,10 +130,10 @@ export interface SwiftProperty { position: ForEachPosition; } -export class SwiftTargetLanguage extends TargetLanguage implements LanguageConfig { - readonly displayName = "Swift" as const; - readonly names = ["swift", "swift4"] as const; - readonly extension = "swift" as const; +export class SwiftTargetLanguage extends TargetLanguage { + constructor() { + super("Swift", ["swift", "swift4"], "swift"); + } protected getOptions(): Option[] { return [ diff --git a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts index 80d0d6856..3616cd9dd 100644 --- a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts +++ b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts @@ -15,7 +15,7 @@ import { stringEscape, utf16StringEscape } from "../support/Strings"; -import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; +import { TargetLanguage } from "../TargetLanguage"; import { legalizeName } from "./JavaScript"; import { Sourcelike } from "../Source"; import { panic } from "../support/Support"; @@ -25,10 +25,14 @@ export const typeScriptEffectSchemaOptions = { justSchema: new BooleanOption("just-schema", "Schema only", false) }; -export class TypeScriptEffectSchemaTargetLanguage extends TargetLanguage implements LanguageConfig { - readonly displayName = "TypeScript Effect Schema" as const; - readonly names = ["typescript-effect-schema"] as const; - readonly extension = "ts" as const; +export class TypeScriptEffectSchemaTargetLanguage extends TargetLanguage { + constructor( + displayName: string = "TypeScript Effect Schema", + names: string[] = ["typescript-effect-schema"], + extension: string = "ts" + ) { + super(displayName, names, extension); + } protected getOptions(): Option[] { return []; diff --git a/packages/quicktype-core/src/language/TypeScriptFlow.ts b/packages/quicktype-core/src/language/TypeScriptFlow.ts index ae7f5f064..f21202056 100644 --- a/packages/quicktype-core/src/language/TypeScriptFlow.ts +++ b/packages/quicktype-core/src/language/TypeScriptFlow.ts @@ -13,7 +13,7 @@ import { legalizeName } from "./JavaScript"; import { defined, panic } from "../support/Support"; -import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; +import { TargetLanguage } from "../TargetLanguage"; import { RenderContext } from "../Renderer"; import { isES3IdentifierStart } from "./JavaScriptUnicodeMaps"; @@ -68,13 +68,10 @@ export abstract class TypeScriptFlowBaseTargetLanguage extends JavaScriptTargetL ): JavaScriptRenderer; } -export class TypeScriptTargetLanguage extends TypeScriptFlowBaseTargetLanguage implements LanguageConfig { - // @ts-expect-error - readonly displayName = "TypeScript" as const; - // @ts-expect-error - readonly names = ["typescript", "ts", "tsx"] as const; - // @ts-expect-error - readonly extension = "ts" as const; +export class TypeScriptTargetLanguage extends TypeScriptFlowBaseTargetLanguage { + constructor() { + super("TypeScript", ["typescript", "ts", "tsx"], "ts"); + } protected makeRenderer( renderContext: RenderContext, @@ -343,11 +340,9 @@ export class TypeScriptRenderer extends TypeScriptFlowBaseRenderer { } export class FlowTargetLanguage extends TypeScriptFlowBaseTargetLanguage { - // @ts-expect-error - readonly displayName = "Flow" as const; - // @ts-expect-error - readonly names = ["flow"] as const; - readonly extension = "js" as const; + constructor() { + super("Flow", ["flow"], "js"); + } protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): FlowRenderer { return new FlowRenderer(this, renderContext, getOptionValues(tsFlowOptions, untypedOptionValues)); diff --git a/packages/quicktype-core/src/language/TypeScriptZod.ts b/packages/quicktype-core/src/language/TypeScriptZod.ts index 30d22c4d9..a90273c89 100644 --- a/packages/quicktype-core/src/language/TypeScriptZod.ts +++ b/packages/quicktype-core/src/language/TypeScriptZod.ts @@ -6,7 +6,7 @@ import { Name, Namer, funPrefixNamer } from "../Naming"; import { RenderContext } from "../Renderer"; import { BooleanOption, Option, OptionValues, getOptionValues } from "../RendererOptions"; import { Sourcelike } from "../Source"; -import { type LanguageConfig, TargetLanguage } from "../TargetLanguage"; +import { TargetLanguage } from "../TargetLanguage"; import { ArrayType, ClassProperty, @@ -37,10 +37,14 @@ export const typeScriptZodOptions = { justSchema: new BooleanOption("just-schema", "Schema only", false) }; -export class TypeScriptZodTargetLanguage extends TargetLanguage implements LanguageConfig { - readonly displayName = "TypeScript Zod" as const; - readonly names = ["typescript-zod"] as const; - readonly extension = "ts" as const; +export class TypeScriptZodTargetLanguage extends TargetLanguage { + constructor( + displayName: string = "TypeScript Zod", + names: string[] = ["typescript-zod"], + extension: string = "ts" + ) { + super(displayName, names, extension); + } protected getOptions(): Option[] { return []; diff --git a/packages/quicktype-core/src/language/ruby/index.ts b/packages/quicktype-core/src/language/ruby/index.ts index bd65e25be..383bdd5ae 100644 --- a/packages/quicktype-core/src/language/ruby/index.ts +++ b/packages/quicktype-core/src/language/ruby/index.ts @@ -3,9 +3,13 @@ import unicode from "unicode-properties"; import { Sourcelike, modifySource } from "../../Source"; import { Namer, Name } from "../../Naming"; import { ConvenienceRenderer, ForbiddenWordsInfo } from "../../ConvenienceRenderer"; -import { type LanguageConfig, TargetLanguage } from "../../TargetLanguage"; +import { TargetLanguage } from "../../TargetLanguage"; import { Option, BooleanOption, EnumOption, OptionValues, getOptionValues, StringOption } from "../../RendererOptions"; +import * as keywords from "./keywords"; + +const forbiddenForObjectProperties = Array.from(new Set([...keywords.keywords, ...keywords.reservedProperties])); + import { Type, EnumType, ClassType, UnionType, ArrayType, MapType, ClassProperty } from "../../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../../TypeUtils"; @@ -25,10 +29,6 @@ import { } from "../../support/Strings"; import { RenderContext } from "../../Renderer"; -import * as keywords from "./keywords"; - -const forbiddenForObjectProperties = Array.from(new Set([...keywords.keywords, ...keywords.reservedProperties])); - function unicodeEscape(codePoint: number): string { return "\\u{" + intToHex(codePoint, 0) + "}"; } @@ -51,10 +51,10 @@ export const rubyOptions = { namespace: new StringOption("namespace", "Specify a wrapping Namespace", "NAME", "", "secondary") }; -export class RubyTargetLanguage extends TargetLanguage implements LanguageConfig { - readonly displayName = "Ruby" as const; - readonly names = ["ruby"] as const; - readonly extension = "rb" as const; +export class RubyTargetLanguage extends TargetLanguage { + constructor() { + super("Ruby", ["ruby"], "rb"); + } protected getOptions(): Option[] { return [rubyOptions.justTypes, rubyOptions.strictness, rubyOptions.namespace]; From 8d7c622933820cc0cacf7f6b465ec32d76a6b6de Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 30 Mar 2024 10:24:43 -0700 Subject: [PATCH 14/94] add generics to TargetLanguage for names and extension --- packages/quicktype-core/src/TargetLanguage.ts | 14 +++++++++----- packages/quicktype-core/src/language/CJSON.ts | 12 +++--------- packages/quicktype-core/src/language/CPlusPlus.ts | 6 +++--- packages/quicktype-core/src/language/CSharp.ts | 2 +- packages/quicktype-core/src/language/Crystal.ts | 2 +- packages/quicktype-core/src/language/Dart.ts | 6 +++--- packages/quicktype-core/src/language/Elm.ts | 2 +- packages/quicktype-core/src/language/Golang.ts | 2 +- packages/quicktype-core/src/language/Haskell.ts | 2 +- packages/quicktype-core/src/language/JSONSchema.ts | 2 +- packages/quicktype-core/src/language/Java.ts | 2 +- packages/quicktype-core/src/language/JavaScript.ts | 6 +++--- .../src/language/JavaScriptPropTypes.ts | 10 +++++++--- packages/quicktype-core/src/language/Kotlin.ts | 2 +- .../quicktype-core/src/language/Objective-C.ts | 6 +++++- packages/quicktype-core/src/language/Php.ts | 2 +- packages/quicktype-core/src/language/Pike.ts | 2 +- packages/quicktype-core/src/language/Python.ts | 2 +- packages/quicktype-core/src/language/Rust.ts | 2 +- packages/quicktype-core/src/language/Scala3.ts | 10 +++++----- packages/quicktype-core/src/language/Smithy4s.ts | 10 +++++----- packages/quicktype-core/src/language/Swift.ts | 2 +- .../src/language/TypeScriptEffectSchema.ts | 14 +++++++------- .../quicktype-core/src/language/TypeScriptZod.ts | 10 +++------- packages/quicktype-core/src/language/ruby/index.ts | 2 +- 25 files changed, 67 insertions(+), 65 deletions(-) diff --git a/packages/quicktype-core/src/TargetLanguage.ts b/packages/quicktype-core/src/TargetLanguage.ts index f1c3a90bf..229fa09bb 100644 --- a/packages/quicktype-core/src/TargetLanguage.ts +++ b/packages/quicktype-core/src/TargetLanguage.ts @@ -13,11 +13,15 @@ import { type Comment } from "./support/Comments"; export type MultiFileRenderResult = ReadonlyMap; -export abstract class TargetLanguage { +export abstract class TargetLanguage< + DisplayName extends string = string, + Names extends readonly string[] = readonly string[], + Extension extends string = string +> { constructor( - readonly displayName: string, - readonly names: string[], - readonly extension: string + readonly displayName: DisplayName, + readonly names: Names, + readonly extension: Extension ) {} protected abstract getOptions(): Option[]; @@ -36,7 +40,7 @@ export abstract class TargetLanguage { return { actual, display }; } - get name(): string { + get name(): Names[0] { return defined(this.names[0]); } diff --git a/packages/quicktype-core/src/language/CJSON.ts b/packages/quicktype-core/src/language/CJSON.ts index 8dd1990b2..53cf67fdb 100644 --- a/packages/quicktype-core/src/language/CJSON.ts +++ b/packages/quicktype-core/src/language/CJSON.ts @@ -128,15 +128,9 @@ export const cJSONOptions = { }; /* cJSON generator target language */ -export class CJSONTargetLanguage extends TargetLanguage { - /** - * Constructor - * @param displayName: display name - * @params names: names - * @param extension: extension of files - */ - constructor(displayName = "C (cJSON)", names: string[] = ["cjson", "cJSON"], extension = "h") { - super(displayName, names, extension); +export class CJSONTargetLanguage extends TargetLanguage<"C (cJSON)", ["cjson", "cJSON"], "h"> { + constructor() { + super("C (cJSON)", ["cjson", "cJSON"], "h"); } /** diff --git a/packages/quicktype-core/src/language/CPlusPlus.ts b/packages/quicktype-core/src/language/CPlusPlus.ts index 5adff56d2..c6b68b93b 100644 --- a/packages/quicktype-core/src/language/CPlusPlus.ts +++ b/packages/quicktype-core/src/language/CPlusPlus.ts @@ -118,9 +118,9 @@ export const cPlusPlusOptions = { hideNullOptional: new BooleanOption("hide-null-optional", "Hide null value for optional field", false) }; -export class CPlusPlusTargetLanguage extends TargetLanguage { - constructor(displayName = "C++", names: string[] = ["c++", "cpp", "cplusplus"], extension = "cpp") { - super(displayName, names, extension); +export class CPlusPlusTargetLanguage extends TargetLanguage<"C++", ["c++", "cpp", "cplusplus"], "cpp"> { + constructor() { + super("C++", ["c++", "cpp", "cplusplus"], "cpp"); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/CSharp.ts b/packages/quicktype-core/src/language/CSharp.ts index 627e387be..e3a8d49c3 100644 --- a/packages/quicktype-core/src/language/CSharp.ts +++ b/packages/quicktype-core/src/language/CSharp.ts @@ -194,7 +194,7 @@ export const cSharpOptions = { keepPropertyName: new BooleanOption("keep-property-name", "Keep original field name generate", false) }; -export class CSharpTargetLanguage extends TargetLanguage { +export class CSharpTargetLanguage extends TargetLanguage<"C#", ["cs", "csharp"], "cs"> { constructor() { super("C#", ["cs", "csharp"], "cs"); } diff --git a/packages/quicktype-core/src/language/Crystal.ts b/packages/quicktype-core/src/language/Crystal.ts index ae08ac743..a6d0e5ef1 100644 --- a/packages/quicktype-core/src/language/Crystal.ts +++ b/packages/quicktype-core/src/language/Crystal.ts @@ -22,7 +22,7 @@ import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; import { Option } from "../RendererOptions"; import { RenderContext } from "../Renderer"; -export class CrystalTargetLanguage extends TargetLanguage { +export class CrystalTargetLanguage extends TargetLanguage<"Crystal", ["crystal", "cr", "crystallang"], "cr"> { constructor() { super("Crystal", ["crystal", "cr", "crystallang"], "cr"); } diff --git a/packages/quicktype-core/src/language/Dart.ts b/packages/quicktype-core/src/language/Dart.ts index 6dc40ead6..9fbd5807f 100644 --- a/packages/quicktype-core/src/language/Dart.ts +++ b/packages/quicktype-core/src/language/Dart.ts @@ -61,7 +61,7 @@ export const dartOptions = { partName: new StringOption("part-name", "Use this name in `part` directive", "NAME", "", "secondary") }; -export class DartTargetLanguage extends TargetLanguage { +export class DartTargetLanguage extends TargetLanguage<"Dart", ["dart"], "dart"> { constructor() { super("Dart", ["dart"], "dart"); } @@ -200,8 +200,8 @@ function dartNameStyle(startWithUpper: boolean, upperUnderscore: boolean, origin const firstWordStyle = upperUnderscore ? allUpperWordStyle : startWithUpper - ? firstUpperWordStyle - : allLowerWordStyle; + ? firstUpperWordStyle + : allLowerWordStyle; const restWordStyle = upperUnderscore ? allUpperWordStyle : firstUpperWordStyle; return combineWords( words, diff --git a/packages/quicktype-core/src/language/Elm.ts b/packages/quicktype-core/src/language/Elm.ts index bab36c541..0a7c77f9d 100644 --- a/packages/quicktype-core/src/language/Elm.ts +++ b/packages/quicktype-core/src/language/Elm.ts @@ -34,7 +34,7 @@ export const elmOptions = { moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType") }; -export class ElmTargetLanguage extends TargetLanguage { +export class ElmTargetLanguage extends TargetLanguage<"Elm", ["elm"], "elm"> { constructor() { super("Elm", ["elm"], "elm"); } diff --git a/packages/quicktype-core/src/language/Golang.ts b/packages/quicktype-core/src/language/Golang.ts index 847bb075d..b0f375de9 100644 --- a/packages/quicktype-core/src/language/Golang.ts +++ b/packages/quicktype-core/src/language/Golang.ts @@ -34,7 +34,7 @@ export const goOptions = { ) }; -export class GoTargetLanguage extends TargetLanguage { +export class GoTargetLanguage extends TargetLanguage<"Go", ["go", "golang"], "go"> { constructor() { super("Go", ["go", "golang"], "go"); } diff --git a/packages/quicktype-core/src/language/Haskell.ts b/packages/quicktype-core/src/language/Haskell.ts index 2bac412e9..5856f32cb 100644 --- a/packages/quicktype-core/src/language/Haskell.ts +++ b/packages/quicktype-core/src/language/Haskell.ts @@ -29,7 +29,7 @@ export const haskellOptions = { moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType") }; -export class HaskellTargetLanguage extends TargetLanguage { +export class HaskellTargetLanguage extends TargetLanguage<"Haskell", ["haskell"], "haskell"> { constructor() { super("Haskell", ["haskell"], "haskell"); } diff --git a/packages/quicktype-core/src/language/JSONSchema.ts b/packages/quicktype-core/src/language/JSONSchema.ts index 2b8a447ba..7249b212f 100644 --- a/packages/quicktype-core/src/language/JSONSchema.ts +++ b/packages/quicktype-core/src/language/JSONSchema.ts @@ -18,7 +18,7 @@ import { addDescriptionToSchema } from "../attributes/Description"; import { Option } from "../RendererOptions"; import { RenderContext } from "../Renderer"; -export class JSONSchemaTargetLanguage extends TargetLanguage { +export class JSONSchemaTargetLanguage extends TargetLanguage<"JSON Schema", ["schema", "json-schema"], "schema"> { constructor() { super("JSON Schema", ["schema", "json-schema"], "schema"); } diff --git a/packages/quicktype-core/src/language/Java.ts b/packages/quicktype-core/src/language/Java.ts index 05ad4b535..64b3c6c2f 100644 --- a/packages/quicktype-core/src/language/Java.ts +++ b/packages/quicktype-core/src/language/Java.ts @@ -53,7 +53,7 @@ export const javaOptions = { lombokCopyAnnotations: new BooleanOption("lombok-copy-annotations", "Copy accessor annotations", true, "secondary") }; -export class JavaTargetLanguage extends TargetLanguage { +export class JavaTargetLanguage extends TargetLanguage<"Java", ["java"], "java"> { constructor() { super("Java", ["java"], "java"); } diff --git a/packages/quicktype-core/src/language/JavaScript.ts b/packages/quicktype-core/src/language/JavaScript.ts index e8e3db9a2..12a18e320 100644 --- a/packages/quicktype-core/src/language/JavaScript.ts +++ b/packages/quicktype-core/src/language/JavaScript.ts @@ -65,9 +65,9 @@ export type JavaScriptTypeAnnotations = { never: string; }; -export class JavaScriptTargetLanguage extends TargetLanguage { - constructor(displayName = "JavaScript", names: string[] = ["javascript", "js", "jsx"], extension = "js") { - super(displayName, names, extension); +export class JavaScriptTargetLanguage extends TargetLanguage<"JavaScript", ["javascript", "js", "jsx"], "js"> { + constructor() { + super("JavaScript", ["javascript", "js", "jsx"], "js"); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts index 7d35dca10..4e8369db2 100644 --- a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts +++ b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts @@ -39,9 +39,13 @@ export const javaScriptPropTypesOptions = { ) }; -export class JavaScriptPropTypesTargetLanguage extends TargetLanguage { - constructor(displayName = "JavaScript PropTypes", names: string[] = ["javascript-prop-types"], extension = "js") { - super(displayName, names, extension); +export class JavaScriptPropTypesTargetLanguage extends TargetLanguage< + "JavaScript PropTypes", + ["javascript-prop-types"], + "js" +> { + constructor() { + super("JavaScript PropTypes", ["javascript-prop-types"], "js"); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/Kotlin.ts b/packages/quicktype-core/src/language/Kotlin.ts index 407b82300..e3e09469d 100644 --- a/packages/quicktype-core/src/language/Kotlin.ts +++ b/packages/quicktype-core/src/language/Kotlin.ts @@ -61,7 +61,7 @@ export const kotlinOptions = { packageName: new StringOption("package", "Package", "PACKAGE", "quicktype") }; -export class KotlinTargetLanguage extends TargetLanguage { +export class KotlinTargetLanguage extends TargetLanguage<"Kotlin", ["kotlin"], "kt"> { constructor() { super("Kotlin", ["kotlin"], "kt"); } diff --git a/packages/quicktype-core/src/language/Objective-C.ts b/packages/quicktype-core/src/language/Objective-C.ts index b1a44e899..facb6174a 100644 --- a/packages/quicktype-core/src/language/Objective-C.ts +++ b/packages/quicktype-core/src/language/Objective-C.ts @@ -43,7 +43,11 @@ export const objcOptions = { extraComments: new BooleanOption("extra-comments", "Extra comments", false) }; -export class ObjectiveCTargetLanguage extends TargetLanguage { +export class ObjectiveCTargetLanguage extends TargetLanguage< + "Objective-C", + ["objc", "objective-c", "objectivec"], + "m" +> { constructor() { super("Objective-C", ["objc", "objective-c", "objectivec"], "m"); } diff --git a/packages/quicktype-core/src/language/Php.ts b/packages/quicktype-core/src/language/Php.ts index 670b09cc1..4933d86d0 100644 --- a/packages/quicktype-core/src/language/Php.ts +++ b/packages/quicktype-core/src/language/Php.ts @@ -34,7 +34,7 @@ export const phpOptions = { acronymStyle: acronymOption(AcronymStyleOptions.Pascal) }; -export class PhpTargetLanguage extends TargetLanguage { +export class PhpTargetLanguage extends TargetLanguage<"PHP", ["php"], "php"> { constructor() { super("PHP", ["php"], "php"); } diff --git a/packages/quicktype-core/src/language/Pike.ts b/packages/quicktype-core/src/language/Pike.ts index d2d9541b7..2e87f5d5a 100644 --- a/packages/quicktype-core/src/language/Pike.ts +++ b/packages/quicktype-core/src/language/Pike.ts @@ -70,7 +70,7 @@ const enumNamingFunction = funPrefixNamer("enumNamer", makeNameStyle("upper-unde const namingFunction = funPrefixNamer("genericNamer", makeNameStyle("underscore", legalizeName)); const namedTypeNamingFunction = funPrefixNamer("typeNamer", makeNameStyle("pascal", legalizeName)); -export class PikeTargetLanguage extends TargetLanguage { +export class PikeTargetLanguage extends TargetLanguage<"Pike", ["pike", "pikelang"], "pmod"> { constructor() { super("Pike", ["pike", "pikelang"], "pmod"); } diff --git a/packages/quicktype-core/src/language/Python.ts b/packages/quicktype-core/src/language/Python.ts index 56182a0a9..f2309db46 100644 --- a/packages/quicktype-core/src/language/Python.ts +++ b/packages/quicktype-core/src/language/Python.ts @@ -129,7 +129,7 @@ export const pythonOptions = { nicePropertyNames: new BooleanOption("nice-property-names", "Transform property names to be Pythonic", true) }; -export class PythonTargetLanguage extends TargetLanguage { +export class PythonTargetLanguage extends TargetLanguage<"Python", ["python", "py"], "py"> { constructor() { super("Python", ["python", "py"], "py"); } diff --git a/packages/quicktype-core/src/language/Rust.ts b/packages/quicktype-core/src/language/Rust.ts index f938483d5..82feb3032 100644 --- a/packages/quicktype-core/src/language/Rust.ts +++ b/packages/quicktype-core/src/language/Rust.ts @@ -111,7 +111,7 @@ const namingStyles: Record = { } }; -export class RustTargetLanguage extends TargetLanguage { +export class RustTargetLanguage extends TargetLanguage<"Rust", ["rust", "rs", "rustlang"], "rs"> { constructor() { super("Rust", ["rust", "rs", "rustlang"], "rs"); } diff --git a/packages/quicktype-core/src/language/Scala3.ts b/packages/quicktype-core/src/language/Scala3.ts index 56437c02b..44ddedc64 100644 --- a/packages/quicktype-core/src/language/Scala3.ts +++ b/packages/quicktype-core/src/language/Scala3.ts @@ -245,10 +245,10 @@ export class Scala3Renderer extends ConvenienceRenderer { delimiter === "curly" ? ["{", "}"] : delimiter === "paren" - ? ["(", ")"] - : delimiter === "none" - ? ["", ""] - : ["{", "})"]; + ? ["(", ")"] + : delimiter === "none" + ? ["", ""] + : ["{", "})"]; this.emitLine(line, " ", open); this.indent(f); this.emitLine(close); @@ -724,7 +724,7 @@ export class CirceRenderer extends Scala3Renderer { } } -export class Scala3TargetLanguage extends TargetLanguage { +export class Scala3TargetLanguage extends TargetLanguage<"Scala3", ["scala3"], "scala"> { constructor() { super("Scala3", ["scala3"], "scala"); } diff --git a/packages/quicktype-core/src/language/Smithy4s.ts b/packages/quicktype-core/src/language/Smithy4s.ts index 3a875be64..203c3b277 100644 --- a/packages/quicktype-core/src/language/Smithy4s.ts +++ b/packages/quicktype-core/src/language/Smithy4s.ts @@ -205,10 +205,10 @@ export class Smithy4sRenderer extends ConvenienceRenderer { delimiter === "curly" ? ["{", "}"] : delimiter === "paren" - ? ["(", ")"] - : delimiter === "none" - ? ["", ""] - : ["{", "})"]; + ? ["(", ")"] + : delimiter === "none" + ? ["", ""] + : ["{", "})"]; this.emitLine(line, " ", open); this.indent(f); this.emitLine(close); @@ -510,7 +510,7 @@ export class Smithy4sRenderer extends ConvenienceRenderer { } } -export class SmithyTargetLanguage extends TargetLanguage { +export class SmithyTargetLanguage extends TargetLanguage<"Smithy", ["Smithy"], "smithy"> { constructor() { super("Smithy", ["Smithy"], "smithy"); } diff --git a/packages/quicktype-core/src/language/Swift.ts b/packages/quicktype-core/src/language/Swift.ts index 04fc431a1..1401079da 100644 --- a/packages/quicktype-core/src/language/Swift.ts +++ b/packages/quicktype-core/src/language/Swift.ts @@ -130,7 +130,7 @@ export interface SwiftProperty { position: ForEachPosition; } -export class SwiftTargetLanguage extends TargetLanguage { +export class SwiftTargetLanguage extends TargetLanguage<"Swift", ["swift", "swift4"], "swift"> { constructor() { super("Swift", ["swift", "swift4"], "swift"); } diff --git a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts index 3616cd9dd..a3f766cd7 100644 --- a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts +++ b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts @@ -25,13 +25,13 @@ export const typeScriptEffectSchemaOptions = { justSchema: new BooleanOption("just-schema", "Schema only", false) }; -export class TypeScriptEffectSchemaTargetLanguage extends TargetLanguage { - constructor( - displayName: string = "TypeScript Effect Schema", - names: string[] = ["typescript-effect-schema"], - extension: string = "ts" - ) { - super(displayName, names, extension); +export class TypeScriptEffectSchemaTargetLanguage extends TargetLanguage< + "TypeScript Effect Schema", + ["typescript-effect-schema"], + "ts" +> { + constructor() { + super("TypeScript Effect Schema", ["typescript-effect-schema"], "ts"); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/TypeScriptZod.ts b/packages/quicktype-core/src/language/TypeScriptZod.ts index a90273c89..77d0ea9c1 100644 --- a/packages/quicktype-core/src/language/TypeScriptZod.ts +++ b/packages/quicktype-core/src/language/TypeScriptZod.ts @@ -37,13 +37,9 @@ export const typeScriptZodOptions = { justSchema: new BooleanOption("just-schema", "Schema only", false) }; -export class TypeScriptZodTargetLanguage extends TargetLanguage { - constructor( - displayName: string = "TypeScript Zod", - names: string[] = ["typescript-zod"], - extension: string = "ts" - ) { - super(displayName, names, extension); +export class TypeScriptZodTargetLanguage extends TargetLanguage<"TypeScript Zod", ["typescript-zod"], "ts"> { + constructor() { + super("TypeScript Zod", ["typescript-zod"], "ts"); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/ruby/index.ts b/packages/quicktype-core/src/language/ruby/index.ts index 383bdd5ae..178e199c7 100644 --- a/packages/quicktype-core/src/language/ruby/index.ts +++ b/packages/quicktype-core/src/language/ruby/index.ts @@ -51,7 +51,7 @@ export const rubyOptions = { namespace: new StringOption("namespace", "Specify a wrapping Namespace", "NAME", "", "secondary") }; -export class RubyTargetLanguage extends TargetLanguage { +export class RubyTargetLanguage extends TargetLanguage<"Ruby", ["ruby"], "rb"> { constructor() { super("Ruby", ["ruby"], "rb"); } From 4acad79b18e9040419bc515baedf6b8fdf1d1849 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 30 Mar 2024 11:05:53 -0700 Subject: [PATCH 15/94] fix generics for JavaScript + subclassing --- .../quicktype-core/src/language/JavaScript.ts | 14 +++++++++++--- .../src/language/TypeScriptFlow.ts | 18 +++++++++++++++--- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/packages/quicktype-core/src/language/JavaScript.ts b/packages/quicktype-core/src/language/JavaScript.ts index 12a18e320..304a6c775 100644 --- a/packages/quicktype-core/src/language/JavaScript.ts +++ b/packages/quicktype-core/src/language/JavaScript.ts @@ -65,9 +65,17 @@ export type JavaScriptTypeAnnotations = { never: string; }; -export class JavaScriptTargetLanguage extends TargetLanguage<"JavaScript", ["javascript", "js", "jsx"], "js"> { - constructor() { - super("JavaScript", ["javascript", "js", "jsx"], "js"); +export class JavaScriptTargetLanguage< + DisplayName extends string = "JavaScript", + Names extends readonly string[] = readonly ["javascript", "js", "jsx"], + Extension extends string = "js" +> extends TargetLanguage { + constructor( + displayName = "JavaScript" as DisplayName, + names = ["javascript", "js", "jsx"] as unknown as Names, + extension = "js" as Extension + ) { + super(displayName, names, extension); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/TypeScriptFlow.ts b/packages/quicktype-core/src/language/TypeScriptFlow.ts index f21202056..664ff92d2 100644 --- a/packages/quicktype-core/src/language/TypeScriptFlow.ts +++ b/packages/quicktype-core/src/language/TypeScriptFlow.ts @@ -40,7 +40,15 @@ const tsFlowTypeAnnotations = { boolean: ": boolean" }; -export abstract class TypeScriptFlowBaseTargetLanguage extends JavaScriptTargetLanguage { +export abstract class TypeScriptFlowBaseTargetLanguage< + DisplayName extends string, + Names extends readonly string[], + Extension extends string +> extends JavaScriptTargetLanguage { + protected constructor(displayName: DisplayName, names: Names, extension: Extension) { + super(displayName, names, extension); + } + protected getOptions(): Option[] { return [ tsFlowOptions.justTypes, @@ -68,7 +76,11 @@ export abstract class TypeScriptFlowBaseTargetLanguage extends JavaScriptTargetL ): JavaScriptRenderer; } -export class TypeScriptTargetLanguage extends TypeScriptFlowBaseTargetLanguage { +export class TypeScriptTargetLanguage extends TypeScriptFlowBaseTargetLanguage< + "TypeScript", + ["typescript", "ts", "tsx"], + "ts" +> { constructor() { super("TypeScript", ["typescript", "ts", "tsx"], "ts"); } @@ -339,7 +351,7 @@ export class TypeScriptRenderer extends TypeScriptFlowBaseRenderer { } } -export class FlowTargetLanguage extends TypeScriptFlowBaseTargetLanguage { +export class FlowTargetLanguage extends TypeScriptFlowBaseTargetLanguage<"Flow", ["flow"], "js"> { constructor() { super("Flow", ["flow"], "js"); } From c4ce60f69df152b18d6d15664dbe0045712e30e0 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 6 Apr 2024 07:57:33 -0700 Subject: [PATCH 16/94] :recycle: --- packages/quicktype-core/src/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/quicktype-core/src/types.ts b/packages/quicktype-core/src/types.ts index d53fa3b40..bfab4f05a 100644 --- a/packages/quicktype-core/src/types.ts +++ b/packages/quicktype-core/src/types.ts @@ -1,4 +1,4 @@ -import { type TargetLanguage } from "TargetLanguage"; +import { type TargetLanguage } from "./TargetLanguage"; import type { all } from "./language/All"; type AllLanguages = (typeof all)[number]; From b2a79041e6bbca0c08152f329f790fa6f2b08230 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sun, 7 Apr 2024 08:50:57 -0700 Subject: [PATCH 17/94] install eslint packages --- package-lock.json | 15983 +++++++++++++++++++++++++++++++++++++------- package.json | 13 +- 2 files changed, 13688 insertions(+), 2308 deletions(-) diff --git a/package-lock.json b/package-lock.json index 06154c3d6..a0ff1b196 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,6 @@ ], "dependencies": { "@glideapps/ts-necessities": "^2.1.3", - "@types/readable-stream": "^4.0.10", "chalk": "^4.1.2", "collection-utils": "^1.0.1", "command-line-args": "^5.2.1", @@ -45,8 +44,18 @@ "@types/shelljs": "^0.8.12", "@types/stream-json": "^1.7.3", "@types/urijs": "^1.19.25", + "@typescript-eslint/eslint-plugin": "^6.3.0", + "@typescript-eslint/parser": "^6.3.0", "ajv": "^5.5.2", "deep-equal": "^2.2.2", + "eslint": "^8.57.0", + "eslint-config-canonical": "^41.1.7", + "eslint-config-prettier": "^6.10.0", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-canonical": "^3.4.0", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-json": "^3.1.0", + "eslint-plugin-prettier": "^4.2.1", "exit": "^0.1.2", "prettier": "^3.0.1", "promise-timeout": "^1.3.0", @@ -80,865 +89,931 @@ "node": ">=12.17" } }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, "engines": { - "node": ">=12" + "node": ">=0.10.0" } }, - "node_modules/@glideapps/ts-necessities": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@glideapps/ts-necessities/-/ts-necessities-2.1.3.tgz", - "integrity": "sha512-q9U8v/n9qbkd2zDYjuX3qtlbl+OIyI9zF+zQhZjfYOE9VMDH7tfcUSJ9p0lXoY3lxmGFne09yi4iiNeQUwV7AA==" - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, "engines": { "node": ">=6.0.0" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "node_modules/@ampproject/remapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@mark.probst/typescript-json-schema": { - "version": "0.55.0", - "resolved": "https://registry.npmjs.org/@mark.probst/typescript-json-schema/-/typescript-json-schema-0.55.0.tgz", - "integrity": "sha512-jI48mSnRgFQxXiE/UTUCVCpX8lK3wCFKLF1Ss2aEreboKNuLQGt3e0/YFqWVHe/WENxOaqiJvwOz+L/SrN2+qQ==", + "node_modules/@ardatan/sync-fetch": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@ardatan/sync-fetch/-/sync-fetch-0.0.1.tgz", + "integrity": "sha512-xhlTqH0m31mnsG0tIP4ETgfSB6gXDaYYsUWTrlUV93fFQPI9dd8hE0Ot6MHLCtqgB32hwJAC3YZMWlXZw7AleA==", + "dev": true, "dependencies": { - "@types/json-schema": "^7.0.9", - "@types/node": "^16.9.2", - "glob": "^7.1.7", - "path-equal": "^1.1.2", - "safe-stable-stringify": "^2.2.0", - "ts-node": "^10.9.1", - "typescript": "4.9.4", - "yargs": "^17.1.1" + "node-fetch": "^2.6.1" }, - "bin": { - "typescript-json-schema": "bin/typescript-json-schema" + "engines": { + "node": ">=14" } }, - "node_modules/@mark.probst/typescript-json-schema/node_modules/@types/node": { - "version": "16.18.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", - "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==" - }, - "node_modules/@mark.probst/typescript-json-schema/node_modules/typescript": { - "version": "4.9.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", - "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "node_modules/@babel/code-frame": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" }, "engines": { - "node": ">=4.2.0" + "node": ">=6.9.0" } }, - "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==" - }, - "node_modules/@tsconfig/node18": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@tsconfig/node18/-/node18-1.0.1.tgz", - "integrity": "sha512-sNFeK6X2ATlhlvzyH4kKYQlfHXE2f2/wxtB9ClvYXevWpmwkUT7VaSrjIN9E76Qebz8qP5JOJJ9jD3QoD/Z9TA==", - "dev": true - }, - "node_modules/@types/browser-or-node": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/browser-or-node/-/browser-or-node-1.3.2.tgz", - "integrity": "sha512-CkvJrvVMI4ZHbiL+Df22Owzq1IYnHnoSrM8s6Dmy4MRdqvdFi9bHsIvyFrSGJPOxvFI9Y3MqY2gFCqIafJBcfw==", - "dev": true - }, - "node_modules/@types/command-line-args": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@types/command-line-args/-/command-line-args-5.2.0.tgz", - "integrity": "sha512-UuKzKpJJ/Ief6ufIaIzr3A/0XnluX7RvFgwkV89Yzvm77wCh1kFaFmqN8XEnGcN62EuHdedQjEMb8mYxFLGPyA==", - "dev": true - }, - "node_modules/@types/command-line-usage": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@types/command-line-usage/-/command-line-usage-5.0.2.tgz", - "integrity": "sha512-n7RlEEJ+4x4TS7ZQddTmNSxP+zziEG0TNsMfiRIxcIVXt71ENJ9ojeXmGO3wPoTdn7pJcU2xc3CJYMktNT6DPg==", - "dev": true + "node_modules/@babel/compat-data": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.1.tgz", + "integrity": "sha512-Pc65opHDliVpRHuKfzI+gSA4zcgr65O4cl64fFJIWEEh8JoHIHh0Oez1Eo8Arz8zq/JhgKodQaxEwUPRtZylVA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/@types/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "node_modules/@babel/core": { + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.3.tgz", + "integrity": "sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ==", "dev": true, "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.1", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.24.1", + "@babel/parser": "^7.24.1", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/@types/graphql": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@types/graphql/-/graphql-0.11.8.tgz", - "integrity": "sha512-xGWx4kx9JKlqxDrZA12gw5qi2lvxPNLxnQQcoTXVX83MuGcXcpb7TADatGyGW51GaaXQOQTbjw3x4HuL3ULBaA==", - "dev": true + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } }, - "node_modules/@types/js-base64": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@types/js-base64/-/js-base64-3.3.1.tgz", - "integrity": "sha512-Zw33oQNAvDdAN9b0IE5stH0y2MylYvtU7VVTKEJPxhyM2q57CVaNJhtJW258ah24NRtaiA23tptUmVn3dmTKpw==", - "deprecated": "This is a stub types definition. js-base64 provides its own type definitions, so you do not need this installed.", + "node_modules/@babel/eslint-parser": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.24.1.tgz", + "integrity": "sha512-d5guuzMlPeDfZIbpQ8+g1NaCNuAGBBGNECh0HVqz1sjOeVLh2CEaifuOysCH18URW6R7pqXINvf5PaR/dC6jLQ==", "dev": true, "dependencies": { - "js-base64": "*" + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0", + "eslint": "^7.5.0 || ^8.0.0" } }, - "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" - }, - "node_modules/@types/lodash": { - "version": "4.14.197", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.197.tgz", - "integrity": "sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g==", - "dev": true - }, - "node_modules/@types/minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", - "dev": true - }, - "node_modules/@types/node": { - "version": "18.14.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.0.tgz", - "integrity": "sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A==" + "node_modules/@babel/eslint-parser/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } }, - "node_modules/@types/pako": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/pako/-/pako-1.0.0.tgz", - "integrity": "sha1-6q6DZNG391LiY7w/1o3+yY5hNsU=", - "dev": true + "node_modules/@babel/eslint-parser/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } }, - "node_modules/@types/pluralize": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/@types/pluralize/-/pluralize-0.0.30.tgz", - "integrity": "sha512-kVww6xZrW/db5BR9OqiT71J9huRdQ+z/r+LbDuT7/EK50mCmj5FoaIARnVv0rvjUS/YpDox0cDU9lpQT011VBA==", - "dev": true + "node_modules/@babel/eslint-plugin": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/eslint-plugin/-/eslint-plugin-7.23.5.tgz", + "integrity": "sha512-03+E/58Hoo/ui69gR+beFdGpplpoVK0BSIdke2iw4/Bz7eGN0ssRenNlnU4nmbkowNQOPCStKSwFr8H6DiY49g==", + "dev": true, + "dependencies": { + "eslint-rule-composer": "^0.3.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/eslint-parser": "^7.11.0", + "eslint": "^7.5.0 || ^8.0.0" + } }, - "node_modules/@types/readable-stream": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.10.tgz", - "integrity": "sha512-AbUKBjcC8SHmImNi4yK2bbjogQlkFSg7shZCcicxPQapniOlajG8GCc39lvXzCWX4lLRRs7DM3VAeSlqmEVZUA==", + "node_modules/@babel/generator": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.1.tgz", + "integrity": "sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A==", + "dev": true, "dependencies": { - "@types/node": "*", - "safe-buffer": "~5.1.1" + "@babel/types": "^7.24.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", - "dev": true + "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } }, - "node_modules/@types/shelljs": { - "version": "0.8.12", - "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.8.12.tgz", - "integrity": "sha512-ZA8U81/gldY+rR5zl/7HSHrG2KDfEb3lzG6uCUDhW1DTQE9yC/VBQ45fXnXq8f3CgInfhZmjtdu/WOUlrXRQUg==", + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", "dev": true, + "peer": true, "dependencies": { - "@types/glob": "~7.2.0", - "@types/node": "*" + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@types/stream-chain": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stream-chain/-/stream-chain-2.0.1.tgz", - "integrity": "sha512-D+Id9XpcBpampptkegH7WMsEk6fUdf9LlCIX7UhLydILsqDin4L0QT7ryJR0oycwC7OqohIzdfcMHVZ34ezNGg==", + "node_modules/@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", "dev": true, "dependencies": { - "@types/node": "*" + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@types/stream-json": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@types/stream-json/-/stream-json-1.7.3.tgz", - "integrity": "sha512-Jqsyq5VPOTWorvEmzWhEWH5tJnHA+bB8vt/Zzb11vSDj8esfSHDMj2rbVjP0mfJQzl3YBJSXBBq08iiyaBK3KA==", + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, "dependencies": { - "@types/node": "*", - "@types/stream-chain": "*" + "yallist": "^3.0.2" } }, - "node_modules/@types/unicode-properties": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@types/unicode-properties/-/unicode-properties-1.3.0.tgz", - "integrity": "sha512-kDVlxpdkCfgvzfXcglkr7j4OSMjCEEo/Jloj4tFuldYZpQ9Uypy7FGXPhNstoj4eGvhddwuu5n0EfI+XdWVoVA==", + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, - "node_modules/@types/urijs": { - "version": "1.19.25", - "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.25.tgz", - "integrity": "sha512-XOfUup9r3Y06nFAZh3WvO0rBU4OtlfPB/vgxpjg+NRdGU6CN6djdc6OEiH+PcqHCY6eFLo9Ista73uarf4gnBg==" + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/@types/yaml": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@types/yaml/-/yaml-1.9.7.tgz", - "integrity": "sha512-8WMXRDD1D+wCohjfslHDgICd2JtMATZU8CkhH8LVJqcJs6dyYj5TGptzP8wApbmEullGBSsCEzzap73DQ1HJaA==", - "deprecated": "This is a stub types definition. yaml provides its own type definitions, so you do not need this installed.", + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "dependencies": { - "yaml": "*" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, "dependencies": { - "event-target-shim": "^5.0.0" + "@babel/types": "^7.22.5" }, "engines": { - "node": ">=6.5" + "node": ">=6.9.0" } }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "node_modules/@babel/helper-module-imports": { + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.0" + }, "engines": { - "node": ">=0.4.0" + "node": ">=6.9.0" } }, - "node_modules/ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", "dev": true, "dependencies": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", + "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", + "dev": true, "engines": { - "node": ">=8" + "node": ">=6.9.0" } }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", "dev": true, "dependencies": { - "color-convert": "^1.9.0" + "@babel/types": "^7.22.5" }, "engines": { - "node": ">=4" + "node": ">=6.9.0" } }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, "dependencies": { - "sprintf-js": "~1.0.2" + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/array-back": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "node_modules/@babel/helper-string-parser": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", + "dev": true, "engines": { - "node": ">=6" + "node": ">=6.9.0" } }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "node_modules/@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "dev": true, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=6.9.0" } }, - "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@babel/helpers": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.1.tgz", + "integrity": "sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg==", + "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/browser-or-node": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-1.2.1.tgz", - "integrity": "sha512-sVIA0cysIED0nbmNOm7sZzKfgN1rpFmrqvLZaFWspaBAftfQcezlC81G6j6U2RJf4Lh66zFxrCeOsvkUXIcPWg==" + "node_modules/@babel/highlight": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "node_modules/@babel/parser": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz", + "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==", "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6.0.0" } }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.1.tgz", + "integrity": "sha512-sxi2kLTI5DeW5vDtMUsk4mTPwvlUDbjOnoWayhynCwrw4QXRld4QEYwqzY8JmQXaJUtgUuCIurtSRH5sn4c7mA==", "dev": true, + "peer": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "@babel/helper-plugin-utils": "^7.24.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.1.tgz", + "integrity": "sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ==", + "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { - "node": ">=10" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/chalk-template": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz", - "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==", + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", + "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", + "dev": true, + "peer": true, "dependencies": { - "chalk": "^4.1.2" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { - "node": ">=12" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/chalk/chalk-template?sponsor=1" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/chalk/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.23.4.tgz", + "integrity": "sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA==", + "dev": true, + "peer": true, "dependencies": { - "color-convert": "^2.0.1" + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.23.3", + "@babel/types": "^7.23.4" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/chalk/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@babel/runtime": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.1.tgz", + "integrity": "sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ==", + "dev": true, "dependencies": { - "color-name": "~1.1.4" + "regenerator-runtime": "^0.14.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=6.9.0" } }, - "node_modules/chalk/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@babel/runtime-corejs3": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.24.1.tgz", + "integrity": "sha512-T9ko/35G+Bkl+win48GduaPlhSlOjjE5s1TeiEcD+QpxlLQnoEfb/nO/T+TQqkm+ipFwORn+rB8w14iJ/uD0bg==", + "dev": true, + "dependencies": { + "core-js-pure": "^3.30.2", + "regenerator-runtime": "^0.14.0" + }, "engines": { - "node": ">=8" + "node": ">=6.9.0" } }, - "node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@babel/template": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", + "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" } }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "node_modules/@babel/traverse": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", + "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", + "dev": true, "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "@babel/code-frame": "^7.24.1", + "@babel/generator": "^7.24.1", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.24.1", + "@babel/types": "^7.24.0", + "debug": "^4.3.1", + "globals": "^11.1.0" }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" + "node": ">=4" } }, - "node_modules/collection-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collection-utils/-/collection-utils-1.0.1.tgz", - "integrity": "sha512-LA2YTIlR7biSpXkKYwwuzGjwL5rjWEZVOSnvdUc7gObvWe4WkjxOpfrdhoP7Hs09YWDVfg0Mal9BpAqLfVEzQg==" - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/@babel/types": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", "dev": true, "dependencies": { - "color-name": "1.1.3" + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/color-convert/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/command-line-args": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", - "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dependencies": { - "array-back": "^3.1.0", - "find-replace": "^3.0.0", - "lodash.camelcase": "^4.3.0", - "typical": "^4.0.0" + "@jridgewell/trace-mapping": "0.3.9" }, "engines": { - "node": ">=4.0.0" + "node": ">=12" } }, - "node_modules/command-line-usage": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-7.0.1.tgz", - "integrity": "sha512-NCyznE//MuTjwi3y84QVUGEOT+P5oto1e1Pk/jFPVdPPfsG03qpTIl3yw6etR+v73d0lXsoojRpvbru2sqePxQ==", + "node_modules/@es-joy/jsdoccomment": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.41.0.tgz", + "integrity": "sha512-aKUhyn1QI5Ksbqcr3fFJj16p99QdjUxXAEuFst1Z47DRyoiMwivIH9MV/ARcJOCXVjPfjITciej8ZD2O/6qUmw==", + "dev": true, "dependencies": { - "array-back": "^6.2.2", - "chalk-template": "^0.4.0", - "table-layout": "^3.0.0", - "typical": "^7.1.1" + "comment-parser": "1.4.1", + "esquery": "^1.5.0", + "jsdoc-type-pratt-parser": "~4.0.0" }, "engines": { - "node": ">=12.20.0" + "node": ">=16" } }, - "node_modules/command-line-usage/node_modules/array-back": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", - "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, "engines": { - "node": ">=12.17" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/command-line-usage/node_modules/typical": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-7.1.1.tgz", - "integrity": "sha512-T+tKVNs6Wu7IWiAce5BgMd7OZfNYUndHwc5MknN+UHOudi7sGZzuHdCadllRuqJ3fPtgFtIH9+lt9qRv6lmpfA==", + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, "engines": { - "node": ">=12.17" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" - }, - "node_modules/cross-fetch": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", - "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, "dependencies": { - "node-fetch": "^2.6.12" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/deep-equal": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz", - "integrity": "sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==", + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.1", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.2", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.0", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/deep-equal/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "node_modules/@eslint/eslintrc/node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" + "argparse": "^2.0.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true, "engines": { - "node": ">=0.3.1" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "node_modules/@glideapps/ts-necessities": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@glideapps/ts-necessities/-/ts-necessities-2.1.3.tgz", + "integrity": "sha512-q9U8v/n9qbkd2zDYjuX3qtlbl+OIyI9zF+zQhZjfYOE9VMDH7tfcUSJ9p0lXoY3lxmGFne09yi4iiNeQUwV7AA==" }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "node_modules/@graphql-eslint/eslint-plugin": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@graphql-eslint/eslint-plugin/-/eslint-plugin-3.20.1.tgz", + "integrity": "sha512-RbwVlz1gcYG62sECR1u0XqMh8w5e5XMCCZoMvPQ3nJzEBCTfXLGX727GBoRmSvY1x4gJmqNZ1lsOX7lZY14RIw==", + "dev": true, "dependencies": { - "iconv-lite": "^0.6.2" + "@babel/code-frame": "^7.18.6", + "@graphql-tools/code-file-loader": "^7.3.6", + "@graphql-tools/graphql-tag-pluck": "^7.3.6", + "@graphql-tools/utils": "^9.0.0", + "chalk": "^4.1.2", + "debug": "^4.3.4", + "fast-glob": "^3.2.12", + "graphql-config": "^4.4.0", + "graphql-depth-limit": "^1.1.0", + "lodash.lowercase": "^4.3.0", + "tslib": "^2.4.1" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "node_modules/@graphql-eslint/eslint-plugin/node_modules/@graphql-tools/code-file-loader": { + "version": "7.3.23", + "resolved": "https://registry.npmjs.org/@graphql-tools/code-file-loader/-/code-file-loader-7.3.23.tgz", + "integrity": "sha512-8Wt1rTtyTEs0p47uzsPJ1vAtfAx0jmxPifiNdmo9EOCuUPyQGEbMaik/YkqZ7QUFIEYEQu+Vgfo8tElwOPtx5Q==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" + "@graphql-tools/graphql-tag-pluck": "7.5.2", + "@graphql-tools/utils": "^9.2.1", + "globby": "^11.0.3", + "tslib": "^2.4.0", + "unixify": "^1.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-get-iterator/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "engines": { - "node": ">=6" + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/@graphql-eslint/eslint-plugin/node_modules/@graphql-tools/graphql-tag-pluck": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/graphql-tag-pluck/-/graphql-tag-pluck-7.5.2.tgz", + "integrity": "sha512-RW+H8FqOOLQw0BPXaahYepVSRjuOHw+7IL8Opaa5G5uYGOBxoXR7DceyQ7BcpMgktAOOmpDNQ2WtcboChOJSRA==", "dev": true, - "engines": { - "node": ">=0.8.0" + "dependencies": { + "@babel/parser": "^7.16.8", + "@babel/plugin-syntax-import-assertions": "^7.20.0", + "@babel/traverse": "^7.16.8", + "@babel/types": "^7.16.8", + "@graphql-tools/utils": "^9.2.1", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, - "node_modules/esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "node_modules/@graphql-eslint/eslint-plugin/node_modules/@graphql-tools/utils": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-9.2.1.tgz", + "integrity": "sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A==", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "@graphql-typed-document-node/core": "^3.1.1", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "engines": { - "node": ">=6" - } + "node_modules/@graphql-eslint/eslint-plugin/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "engines": { - "node": ">=0.8.x" + "node_modules/@graphql-typed-document-node/core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "dev": true, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, - "node_modules/exec-sh": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.1.tgz", - "integrity": "sha512-aLt95pexaugVtQerpmE51+4QfWrNc304uez7jvj6fWnN8GeEHpttB8F36n8N7uVhUMbH/1enbxQ9HImZ4w/9qg==", + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, "dependencies": { - "merge": "^1.1.3" + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" } }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, "engines": { - "node": ">= 0.8.0" + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, - "node_modules/find-replace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", - "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, "dependencies": { - "array-back": "^3.0.1" + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { - "node": ">=4.0.0" + "node": ">=6.0.0" } }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "dependencies": { - "is-callable": "^1.1.3" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "engines": { + "node": ">=6.0.0" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": ">=6.0.0" } }, - "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", - "dev": true, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@mark.probst/typescript-json-schema": { + "version": "0.55.0", + "resolved": "https://registry.npmjs.org/@mark.probst/typescript-json-schema/-/typescript-json-schema-0.55.0.tgz", + "integrity": "sha512-jI48mSnRgFQxXiE/UTUCVCpX8lK3wCFKLF1Ss2aEreboKNuLQGt3e0/YFqWVHe/WENxOaqiJvwOz+L/SrN2+qQ==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "@types/node": "^16.9.2", + "glob": "^7.1.7", + "path-equal": "^1.1.2", + "safe-stable-stringify": "^2.2.0", + "ts-node": "^10.9.1", + "typescript": "4.9.4", + "yargs": "^17.1.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bin": { + "typescript-json-schema": "bin/typescript-json-schema" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/@mark.probst/typescript-json-schema/node_modules/@types/node": { + "version": "16.18.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", + "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==" + }, + "node_modules/@mark.probst/typescript-json-schema/node_modules/typescript": { + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/@next/eslint-plugin-next": { + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.5.6.tgz", + "integrity": "sha512-ng7pU/DDsxPgT6ZPvuprxrkeew3XaRf4LAT4FabaEO/hAbvVx4P7wqnqdbTdDn1kgTvsI4tpIgT4Awn/m0bGbg==", + "dev": true, + "dependencies": { + "glob": "7.1.7" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.1.1", + "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, @@ -949,754 +1024,877 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graphql": { - "version": "0.11.7", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-0.11.7.tgz", - "integrity": "sha512-x7uDjyz8Jx+QPbpCFCMQ8lltnQa4p4vSYHx6ADe8rVYRTdsyhCJbvSty5DAsLVmU6cGakl+r8HQYolKHxk/tiw==", - "dependencies": { - "iterall": "1.1.3" + "eslint-scope": "5.1.1" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, "dependencies": { - "function-bind": "^1.1.1" + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" }, "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8.0.0" } }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, "engines": { - "node": ">=4" + "node": ">=4.0" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.1" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 8" } }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 8" } }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 8" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "node_modules/@peculiar/asn1-schema": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.8.tgz", + "integrity": "sha512-ULB1XqHKx1WBU/tTFIA+uARuRoBVZ4pNdOA878RDrRbBfBGcSzi5HBkdScC6ZbHn8z7L8gmKCgPC1LHRrP46tA==", + "dev": true, "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "asn1js": "^3.0.5", + "pvtsutils": "^1.3.5", + "tslib": "^2.6.2" } }, - "node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "node_modules/@peculiar/asn1-schema/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true }, - "node_modules/internal-slot": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.4.tgz", - "integrity": "sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ==", + "node_modules/@peculiar/json-schema": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", + "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "side-channel": "^1.0.4" + "tslib": "^2.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=8.0.0" } }, - "node_modules/interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "node_modules/@peculiar/json-schema/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "dev": true }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "node_modules/@peculiar/webcrypto": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.4.5.tgz", + "integrity": "sha512-oDk93QCDGdxFRM8382Zdminzs44dg3M2+E5Np+JWkpqLDyJC9DviMh8F8mEJkYuUcUOGA5jHO5AJJ10MFWdbZw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "@peculiar/asn1-schema": "^2.3.8", + "@peculiar/json-schema": "^1.1.12", + "pvtsutils": "^1.3.5", + "tslib": "^2.6.2", + "webcrypto-core": "^1.7.8" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10.12.0" } }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "node_modules/@peculiar/webcrypto/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, "engines": { - "node": ">= 0.4" + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/unts" } }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "node_modules/@repeaterjs/repeater": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.4.tgz", + "integrity": "sha512-AW8PKd6iX3vAZ0vA43nOUOnbq/X5ihgU+mSXXqunMkeQADGiqw/PY0JNeYtD5sr0PAy51YPgAPbDoeapv9r8WA==", + "dev": true }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "node_modules/@rushstack/eslint-patch": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.8.0.tgz", + "integrity": "sha512-0HejFckBN2W+ucM6cUOlwsByTKt9/+0tWhqUffNIcHqCXkthY/mZ7AuYPK/2IIaGWhdl0h+tICDO0ssLMd6XMQ==", + "dev": true }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==" + }, + "node_modules/@tsconfig/node18": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node18/-/node18-1.0.1.tgz", + "integrity": "sha512-sNFeK6X2ATlhlvzyH4kKYQlfHXE2f2/wxtB9ClvYXevWpmwkUT7VaSrjIN9E76Qebz8qP5JOJJ9jD3QoD/Z9TA==", + "dev": true + }, + "node_modules/@types/browser-or-node": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/browser-or-node/-/browser-or-node-1.3.2.tgz", + "integrity": "sha512-CkvJrvVMI4ZHbiL+Df22Owzq1IYnHnoSrM8s6Dmy4MRdqvdFi9bHsIvyFrSGJPOxvFI9Y3MqY2gFCqIafJBcfw==", + "dev": true + }, + "node_modules/@types/command-line-args": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@types/command-line-args/-/command-line-args-5.2.0.tgz", + "integrity": "sha512-UuKzKpJJ/Ief6ufIaIzr3A/0XnluX7RvFgwkV89Yzvm77wCh1kFaFmqN8XEnGcN62EuHdedQjEMb8mYxFLGPyA==", + "dev": true + }, + "node_modules/@types/command-line-usage": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@types/command-line-usage/-/command-line-usage-5.0.2.tgz", + "integrity": "sha512-n7RlEEJ+4x4TS7ZQddTmNSxP+zziEG0TNsMfiRIxcIVXt71ENJ9ojeXmGO3wPoTdn7pJcU2xc3CJYMktNT6DPg==", + "dev": true + }, + "node_modules/@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" } }, - "node_modules/is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "node_modules/@types/graphql": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@types/graphql/-/graphql-0.11.8.tgz", + "integrity": "sha512-xGWx4kx9JKlqxDrZA12gw5qi2lvxPNLxnQQcoTXVX83MuGcXcpb7TADatGyGW51GaaXQOQTbjw3x4HuL3ULBaA==", + "dev": true + }, + "node_modules/@types/js-base64": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/js-base64/-/js-base64-3.3.1.tgz", + "integrity": "sha512-Zw33oQNAvDdAN9b0IE5stH0y2MylYvtU7VVTKEJPxhyM2q57CVaNJhtJW258ah24NRtaiA23tptUmVn3dmTKpw==", + "deprecated": "This is a stub types definition. js-base64 provides its own type definitions, so you do not need this installed.", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "dependencies": { + "js-base64": "*" } }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/lodash": { + "version": "4.14.197", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.197.tgz", + "integrity": "sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g==", + "dev": true + }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.14.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.0.tgz", + "integrity": "sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A==" + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true + }, + "node_modules/@types/pako": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/pako/-/pako-1.0.0.tgz", + "integrity": "sha1-6q6DZNG391LiY7w/1o3+yY5hNsU=", + "dev": true + }, + "node_modules/@types/pluralize": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/pluralize/-/pluralize-0.0.30.tgz", + "integrity": "sha512-kVww6xZrW/db5BR9OqiT71J9huRdQ+z/r+LbDuT7/EK50mCmj5FoaIARnVv0rvjUS/YpDox0cDU9lpQT011VBA==", + "dev": true + }, + "node_modules/@types/readable-stream": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.10.tgz", + "integrity": "sha512-AbUKBjcC8SHmImNi4yK2bbjogQlkFSg7shZCcicxPQapniOlajG8GCc39lvXzCWX4lLRRs7DM3VAeSlqmEVZUA==", "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@types/node": "*", + "safe-buffer": "~5.1.1" } }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "node_modules/@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "dev": true + }, + "node_modules/@types/shelljs": { + "version": "0.8.12", + "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.8.12.tgz", + "integrity": "sha512-ZA8U81/gldY+rR5zl/7HSHrG2KDfEb3lzG6uCUDhW1DTQE9yC/VBQ45fXnXq8f3CgInfhZmjtdu/WOUlrXRQUg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@types/glob": "~7.2.0", + "@types/node": "*" } }, - "node_modules/is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "node_modules/@types/stream-chain": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stream-chain/-/stream-chain-2.0.1.tgz", + "integrity": "sha512-D+Id9XpcBpampptkegH7WMsEk6fUdf9LlCIX7UhLydILsqDin4L0QT7ryJR0oycwC7OqohIzdfcMHVZ34ezNGg==", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "dependencies": { + "@types/node": "*" } }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "node_modules/@types/stream-json": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@types/stream-json/-/stream-json-1.7.3.tgz", + "integrity": "sha512-Jqsyq5VPOTWorvEmzWhEWH5tJnHA+bB8vt/Zzb11vSDj8esfSHDMj2rbVjP0mfJQzl3YBJSXBBq08iiyaBK3KA==", "dev": true, "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@types/node": "*", + "@types/stream-chain": "*" } }, - "node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "engines": { - "node": ">=0.10.0" + "node_modules/@types/unicode-properties": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@types/unicode-properties/-/unicode-properties-1.3.0.tgz", + "integrity": "sha512-kDVlxpdkCfgvzfXcglkr7j4OSMjCEEo/Jloj4tFuldYZpQ9Uypy7FGXPhNstoj4eGvhddwuu5n0EfI+XdWVoVA==", + "dev": true + }, + "node_modules/@types/urijs": { + "version": "1.19.25", + "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.25.tgz", + "integrity": "sha512-XOfUup9r3Y06nFAZh3WvO0rBU4OtlfPB/vgxpjg+NRdGU6CN6djdc6OEiH+PcqHCY6eFLo9Ista73uarf4gnBg==" + }, + "node_modules/@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "dev": true, + "dependencies": { + "@types/node": "*" } }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "node_modules/@types/yaml": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@types/yaml/-/yaml-1.9.7.tgz", + "integrity": "sha512-8WMXRDD1D+wCohjfslHDgICd2JtMATZU8CkhH8LVJqcJs6dyYj5TGptzP8wApbmEullGBSsCEzzap73DQ1HJaA==", + "deprecated": "This is a stub types definition. yaml provides its own type definitions, so you do not need this installed.", "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" + "yaml": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": ">= 0.4" + "node": "^16.0.0 || >=18.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "node_modules/@typescript-eslint/experimental-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.62.0.tgz", + "integrity": "sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==", "dev": true, "dependencies": { - "has-symbols": "^1.0.2" + "@typescript-eslint/utils": "5.62.0" }, "engines": { - "node": ">= 0.4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" }, "engines": { - "node": ">= 0.4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/is-url": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" - }, - "node_modules/is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/iterall": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.1.3.tgz", - "integrity": "sha512-Cu/kb+4HiNSejAPhSaN1VukdNTTi/r4/e+yykqjlG/IW+1gZH5b4+Bq3whDX4tvbYugta3r8KTMUiqT3fIGxuQ==" - }, - "node_modules/js-base64": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.3.tgz", - "integrity": "sha512-H7ErYLM34CvDMto3GbD6xD0JLUGYXR3QTcH6B/tr4Hi/QpSThnCsIp+Sy5FRTw3B0d6py4HcNkW7nO/wdtGWEw==" - }, - "node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", "dev": true, "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/js-yaml/node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" }, "engines": { - "node": ">=4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.assignwith": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assignwith/-/lodash.assignwith-4.2.0.tgz", - "integrity": "sha512-ZznplvbvtjK2gMvnQ1BR/zqPFZmS6jbK4p+6Up4xcRYA7yMIwxHCfbTcrYxXKzzqLsQ05eJPVznEW3tuwV7k1g==" - }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" }, "engines": { - "node": ">=10" + "node": ">=8.0.0" } }, - "node_modules/make-error": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz", - "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==" - }, - "node_modules/merge": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz", - "integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==", - "dev": true + "node_modules/@typescript-eslint/experimental-utils/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@typescript-eslint/experimental-utils/node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "tslib": "^1.8.1" }, "engines": { - "node": "*" + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, - "node_modules/minimist": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", + "node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "dependencies": { - "minimist": "^1.2.6" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", "engines": { - "node": "*" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", + "node_modules/@typescript-eslint/type-utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "dev": true, "dependencies": { - "whatwg-url": "^5.0.0" + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": "4.x || >=6.0.0" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "encoding": "^0.1.0" + "eslint": "^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { - "encoding": { + "typescript": { "optional": true } } }, - "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": ">= 0.4" + "node": "^16.0.0 || >=18.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": ">= 0.4" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" }, "engines": { - "node": ">= 0.4" + "node": "^16.0.0 || >=18.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dev": true, "dependencies": { - "wrappy": "1" + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/pako": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", - "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==" + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true }, - "node_modules/path-equal": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/path-equal/-/path-equal-1.2.5.tgz", - "integrity": "sha512-i73IctDr3F2W+bsOWDyyVm/lqsXO47aY9nsFZUjTT/aljSbkxHxxCoyZ9UUrM8jK0JVod+An+rl48RCsvWM+9g==" + "node_modules/@whatwg-node/events": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@whatwg-node/events/-/events-0.0.3.tgz", + "integrity": "sha512-IqnKIDWfXBJkvy/k6tzskWTc2NK3LcqHlb+KHGCrjOCH4jfQckRX0NAiIcC/vIqQkzLYw2r2CTSwAxcrtcD6lA==", + "dev": true }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "engines": { - "node": ">=0.10.0" + "node_modules/@whatwg-node/fetch": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.8.8.tgz", + "integrity": "sha512-CdcjGC2vdKhc13KKxgsc6/616BQ7ooDIgPeTuAiE8qfCnS0mGzcfCOoZXypQSz73nxI+GWc7ZReIAVhxoE1KCg==", + "dev": true, + "dependencies": { + "@peculiar/webcrypto": "^1.4.0", + "@whatwg-node/node-fetch": "^0.3.6", + "busboy": "^1.6.0", + "urlpattern-polyfill": "^8.0.0", + "web-streams-polyfill": "^3.2.1" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "node_modules/@whatwg-node/node-fetch": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.3.6.tgz", + "integrity": "sha512-w9wKgDO4C95qnXZRwZTfCmLWqyRnooGjcIwG0wADWjw9/HN0p7dtvtgSvItZtUyNteEvgTrd8QojNEqV6DAGTA==", + "dev": true, + "dependencies": { + "@whatwg-node/events": "^0.0.3", + "busboy": "^1.6.0", + "fast-querystring": "^1.1.1", + "fast-url-parser": "^1.1.3", + "tslib": "^2.3.1" + } + }, + "node_modules/@whatwg-node/node-fetch/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "dev": true }, - "node_modules/pluralize": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, "engines": { - "node": ">=4" + "node": ">=6.5" } }, - "node_modules/prettier": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.1.tgz", - "integrity": "sha512-fcOWSnnpCrovBsmFZIGIy9UqK2FaI7Hqax+DIO0A9UxeVoY4iweyaFjS5TavZN97Hfehph0nhsZnjlVKzEQSrQ==", - "dev": true, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "bin": { - "prettier": "bin/prettier.cjs" + "acorn": "bin/acorn" }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "node": ">=0.4.0" } }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/promise-timeout": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/promise-timeout/-/promise-timeout-1.3.0.tgz", - "integrity": "sha512-5yANTE0tmi5++POym6OgtFmwfDvOXABD9oj/jLQr5GPEyuNEb7jH4wbbANJceJid49jwhi1RddxnhnEAb/doqg==", - "dev": true + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } }, - "node_modules/quicktype-core": { - "resolved": "packages/quicktype-core", - "link": true + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "engines": { + "node": ">=0.4.0" + } }, - "node_modules/quicktype-graphql-input": { - "resolved": "packages/quicktype-graphql-input", - "link": true + "node_modules/ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "dependencies": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } }, - "node_modules/quicktype-typescript-input": { - "resolved": "packages/quicktype-typescript-input", - "link": true + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } }, - "node_modules/readable-stream": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", - "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" + "color-convert": "^1.9.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=4" } }, - "node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "node_modules/are-docs-informative": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", + "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", + "dev": true, + "engines": { + "node": ">=14" + } }, - "node_modules/readable-stream/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, "dependencies": { - "safe-buffer": "~5.2.0" + "sprintf-js": "~1.0.2" } }, - "node_modules/rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", "dev": true, "dependencies": { - "resolve": "^1.1.6" - }, + "dequal": "^2.0.3" + } + }, + "node_modules/array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", "engines": { - "node": ">= 0.10" + "node": ">=6" } }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" }, "engines": { "node": ">= 0.4" @@ -1705,562 +1903,454 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", - "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, "dependencies": { - "path-parse": "^1.0.5" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/safe-stable-stringify": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.2.tgz", - "integrity": "sha512-gMxvPJYhP0O9n2pvcfYfIuYgbledAOJFcqRThtPRmjscaipiwcwPPKLytpVzMkG2HAN87Qmo2d4PtGiri1dSLA==", + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" }, "engines": { - "node": ">=10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/shelljs": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", - "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", "dev": true, "dependencies": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - }, - "bin": { - "shjs": "bin/shjs" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" }, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", "dev": true, "dependencies": { - "internal-slot": "^1.0.4" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/stream-chain": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz", - "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==" - }, - "node_modules/stream-json": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.8.0.tgz", - "integrity": "sha512-HZfXngYHUAr1exT4fxlbc1IOce1RYxp2ldeaf97LYCOPSoOqY/1Psp7iGvpb+6JIOgkra9zDYnPX01hGAHzEPw==", + "node_modules/array.prototype.toreversed": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", + "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", + "dev": true, "dependencies": { - "stream-chain": "^2.2.5" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" } }, - "node_modules/stream-read-all": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/stream-read-all/-/stream-read-all-3.0.1.tgz", - "integrity": "sha512-EWZT9XOceBPlVJRrYcykW8jyRSZYbkb/0ZK36uLEmoWVO5gxBOnntNTseNzfREsqxqdfEGQrD8SXQ3QWbBmq8A==", - "engines": { - "node": ">=10" + "node_modules/array.prototype.tosorted": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz", + "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.1.0", + "es-shim-unscopables": "^1.0.2" } }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, "dependencies": { - "safe-buffer": "~5.1.0" + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string-to-stream": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/string-to-stream/-/string-to-stream-3.0.1.tgz", - "integrity": "sha512-Hl092MV3USJuUCC6mfl9sPzGloA3K5VwdIeJjYIkXY/8K+mUvaeEabWJgArp+xXrsWxCajeT2pc4axbVhIZJyg==", - "dependencies": { - "readable-stream": "^3.4.0" + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/string-to-stream/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "node_modules/asn1js": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", + "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", + "dev": true, "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "pvtsutils": "^1.3.2", + "pvutils": "^1.1.3", + "tslib": "^2.4.0" }, "engines": { - "node": ">= 6" + "node": ">=12.0.0" } }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/asn1js/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, + "node_modules/ast-types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "dev": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "tslib": "^2.0.1" }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true + }, + "node_modules/ast-types/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, "dependencies": { - "ansi-regex": "^5.0.1" + "possible-typed-array-names": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/axe-core": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz", + "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==", "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, "engines": { "node": ">=4" } }, - "node_modules/table-layout": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-3.0.2.tgz", - "integrity": "sha512-rpyNZYRw+/C+dYkcQ3Pr+rLxW4CfHpXjPDnG7lYhdRoUcZTUt+KEsX+94RGp/aVp/MQU35JCITv2T/beY4m+hw==", + "node_modules/axobject-query": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", + "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", + "dev": true, "dependencies": { - "@75lb/deep-merge": "^1.1.1", - "array-back": "^6.2.2", - "command-line-args": "^5.2.1", - "command-line-usage": "^7.0.0", - "stream-read-all": "^3.0.1", - "typical": "^7.1.1", - "wordwrapjs": "^5.1.0" - }, - "bin": { - "table-layout": "bin/cli.js" - }, - "engines": { - "node": ">=12.17" - } - }, - "node_modules/table-layout/node_modules/array-back": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", - "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", - "engines": { - "node": ">=12.17" + "dequal": "^2.0.3" } }, - "node_modules/table-layout/node_modules/typical": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-7.1.1.tgz", - "integrity": "sha512-T+tKVNs6Wu7IWiAce5BgMd7OZfNYUndHwc5MknN+UHOudi7sGZzuHdCadllRuqJ3fPtgFtIH9+lt9qRv6lmpfA==", - "engines": { - "node": ">=12.17" - } + "node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, - "node_modules/tiny-inflate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.2.tgz", - "integrity": "sha1-k9nez/yIBb1X6uQxDwt0Xptvs6c=" + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "dev": true }, - "node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/ts-node/node_modules/acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", - "bin": { - "acorn": "bin/acorn" + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" }, "engines": { - "node": ">=0.4.0" + "node": ">=8" } }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "node_modules/browser-or-node": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-1.2.1.tgz", + "integrity": "sha512-sVIA0cysIED0nbmNOm7sZzKfgN1rpFmrqvLZaFWspaBAftfQcezlC81G6j6U2RJf4Lh66zFxrCeOsvkUXIcPWg==" }, - "node_modules/tslint": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", - "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", - "deprecated": "TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.", + "node_modules/browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.3", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.13.0", - "tsutils": "^2.29.0" + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" }, "bin": { - "tslint": "bin/tslint" + "browserslist": "cli.js" }, "engines": { - "node": ">=4.8.0" - }, - "peerDependencies": { - "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/tslint/node_modules/@babel/code-frame": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", - "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", - "dev": true, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { - "@babel/highlight": "^7.0.0" + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, - "node_modules/tslint/node_modules/@babel/highlight": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", - "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "node_modules/builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", "dev": true, - "dependencies": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/tslint/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "streamsearch": "^1.1.0" }, "engines": { - "node": ">=4" + "node": ">=10.16.0" } }, - "node_modules/tslint/node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/tslint/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "peerDependencies": { - "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" - } - }, - "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/typical": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", - "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/unicode-properties": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", - "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==", - "dependencies": { - "base64-js": "^1.3.0", - "unicode-trie": "^2.0.0" - } - }, - "node_modules/unicode-properties/node_modules/pako": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", - "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" - }, - "node_modules/unicode-properties/node_modules/unicode-trie": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", - "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", - "dependencies": { - "pako": "^0.2.5", - "tiny-inflate": "^1.0.0" - } - }, - "node_modules/urijs": { - "version": "1.19.11", - "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.11.tgz", - "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==" - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" - }, - "node_modules/watch": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/watch/-/watch-1.0.2.tgz", - "integrity": "sha1-NApxe952Vyb6CqB9ch4BR6VR3ww=", + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, "dependencies": { - "exec-sh": "^0.2.0", - "minimist": "^1.2.0" - }, - "bin": { - "watch": "cli.js" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" }, "engines": { - "node": ">=0.1.95" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/whatwg-fetch": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", - "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, - "dependencies": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=6" } }, - "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "node_modules/caniuse-lite": { + "version": "1.0.30001600", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001600.tgz", + "integrity": "sha512-+2S9/2JFhYmYaDpZvo0lKkfvuKIglrx68MwOBqMGHhQsNkLjB5xtc/TGoEPs+MxjSyN/72qer2g97nzR641mOQ==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" - }, - "node_modules/wordwrapjs": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-5.1.0.tgz", - "integrity": "sha512-JNjcULU2e4KJwUNv6CHgI46UvDGitb6dGryHajXTDiLgg1/RiGoPSDw4kZfYnwGtEXf2ZMeIewDQgFGzkCB2Sg==", - "engines": { - "node": ">=12.17" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "node_modules/chalk-template": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz", + "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "chalk": "^4.1.2" }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "url": "https://github.com/chalk/chalk-template?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { + "node_modules/chalk/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", @@ -2274,7 +2364,7 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/color-convert": { + "node_modules/chalk/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -2285,829 +2375,10022 @@ "node": ">=7.0.0" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "node_modules/chalk/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "node_modules/chance": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/chance/-/chance-1.1.11.tgz", + "integrity": "sha512-kqTg3WWywappJPqtgrdvbA380VoXO2eu9VCV895JgbyHsaErXdyHK9LOZ911OvAk6L0obK7kDk9CGs8+oBawVA==", "dev": true }, - "node_modules/yaml": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", - "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "engines": { - "node": ">= 14" + "node": ">=8" } }, - "node_modules/yargs": { - "version": "17.6.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", - "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", + "node_modules/clean-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", + "integrity": "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==", + "dev": true, "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "escape-string-regexp": "^1.0.5" }, "engines": { - "node": ">=12" + "node": ">=4" } }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, "engines": { "node": ">=12" } }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true, "engines": { - "node": ">=6" + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" } }, - "packages/quicktype-core": { - "version": "18.0.15", - "license": "Apache-2.0", + "node_modules/collection-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/collection-utils/-/collection-utils-1.0.1.tgz", + "integrity": "sha512-LA2YTIlR7biSpXkKYwwuzGjwL5rjWEZVOSnvdUc7gObvWe4WkjxOpfrdhoP7Hs09YWDVfg0Mal9BpAqLfVEzQg==" + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, "dependencies": { - "@glideapps/ts-necessities": "2.1.3", - "@types/urijs": "^1.19.25", - "browser-or-node": "^2.1.1", - "collection-utils": "^1.0.1", - "cross-fetch": "^4.0.0", - "is-url": "^1.2.4", - "js-base64": "^3.7.5", - "lodash": "^4.17.21", - "pako": "^1.0.6", - "pluralize": "^8.0.0", - "readable-stream": "4.5.2", - "unicode-properties": "^1.4.1", - "urijs": "^1.19.1", - "wordwrap": "^1.0.0", - "yaml": "^2.3.1" - }, - "devDependencies": { - "@types/browser-or-node": "^1.3.2", - "@types/js-base64": "^3.3.1", - "@types/node": "18.14.0", - "@types/pako": "^1.0.0", - "@types/pluralize": "0.0.30", - "@types/readable-stream": "4.0.10", - "@types/unicode-properties": "^1.3.0", - "@types/yaml": "^1.9.7", - "tslint": "^6.1.3", - "typescript": "4.9.5" + "color-name": "1.1.3" } }, - "packages/quicktype-core/node_modules/browser-or-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-2.1.1.tgz", - "integrity": "sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg==" + "node_modules/color-convert/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true }, - "packages/quicktype-core/node_modules/js-base64": { - "version": "3.7.5", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.5.tgz", - "integrity": "sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA==" + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "packages/quicktype-core/node_modules/pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "node_modules/command-line-args": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", + "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", + "dependencies": { + "array-back": "^3.1.0", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" + }, "engines": { - "node": ">=4" + "node": ">=4.0.0" } }, - "packages/quicktype-graphql-input": { - "version": "18.0.15", - "license": "Apache-2.0", + "node_modules/command-line-usage": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-7.0.1.tgz", + "integrity": "sha512-NCyznE//MuTjwi3y84QVUGEOT+P5oto1e1Pk/jFPVdPPfsG03qpTIl3yw6etR+v73d0lXsoojRpvbru2sqePxQ==", "dependencies": { - "collection-utils": "^1.0.1", - "graphql": "^0.11.7", - "quicktype-core": "file:../quicktype-core" + "array-back": "^6.2.2", + "chalk-template": "^0.4.0", + "table-layout": "^3.0.0", + "typical": "^7.1.1" }, - "devDependencies": { - "@types/graphql": "^0.11.7", - "@types/node": "18.14.0", - "tslint": "^6.1.3", - "typescript": "4.9.5" + "engines": { + "node": ">=12.20.0" } }, - "packages/quicktype-typescript-input": { - "version": "18.0.15", - "license": "Apache-2.0", + "node_modules/command-line-usage/node_modules/array-back": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", + "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", + "engines": { + "node": ">=12.17" + } + }, + "node_modules/command-line-usage/node_modules/typical": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-7.1.1.tgz", + "integrity": "sha512-T+tKVNs6Wu7IWiAce5BgMd7OZfNYUndHwc5MknN+UHOudi7sGZzuHdCadllRuqJ3fPtgFtIH9+lt9qRv6lmpfA==", + "engines": { + "node": ">=12.17" + } + }, + "node_modules/commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, + "node_modules/comment-parser": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", + "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", + "dev": true, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/core-js-pure": { + "version": "3.36.1", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.36.1.tgz", + "integrity": "sha512-NXCvHvSVYSrewP0L5OhltzXeWFJLo2AL2TYnj6iLV3Bw8mM62wAQMNgUCRI6EBu6hVVpbCxmOPlxh1Ikw2PfUA==", + "dev": true, + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cosmiconfig": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.0.0.tgz", + "integrity": "sha512-da1EafcpH6b/TD8vDRaWV7xFINlHlF6zKsGwS1TsuVJTZRkquaS5HTMq7uq6h31619QjbsYl21gVDOm32KM1vQ==", + "dev": true, "dependencies": { - "@mark.probst/typescript-json-schema": "0.55.0", - "quicktype-core": "file:../quicktype-core", - "typescript": "4.9.5" + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0" }, - "devDependencies": { - "@types/node": "18.14.0", - "tslint": "^6.1.3" + "engines": { + "node": ">=14" } }, - "packages/quicktype-typescript-input/node_modules/@glideapps/ts-necessities": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@glideapps/ts-necessities/-/ts-necessities-2.1.2.tgz", - "integrity": "sha512-tLjfhinr6doUBcWi7BWnkT2zT6G5UhiZftsiIH6xVvykeXE+FU7Wr0MyqwmqideWlDD5rG+VjVLptLviGo04CA==" + "node_modules/cosmiconfig/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, - "packages/quicktype-typescript-input/node_modules/isomorphic-fetch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", - "integrity": "sha512-9c4TNAKYXM5PRyVcwUZrF3W09nQ+sO7+jydgs4ZGW9dhsLG2VOlISJABombdQqQRXCwuYG3sYV/puGf5rp0qmA==", + "node_modules/cosmiconfig/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, "dependencies": { - "node-fetch": "^1.0.1", - "whatwg-fetch": ">=0.10.0" + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "packages/quicktype-typescript-input/node_modules/node-fetch": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", - "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "node_modules/create-eslint-index": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/create-eslint-index/-/create-eslint-index-1.0.0.tgz", + "integrity": "sha512-nXvJjnfDytOOaPOonX0h0a1ggMoqrhdekGeZkD6hkcWYvlCWhU719tKFVh8eU04CnMwu3uwe1JjwuUF2C3k2qg==", + "dev": true, "dependencies": { - "encoding": "^0.1.11", - "is-stream": "^1.0.1" + "lodash.get": "^4.3.0" + }, + "engines": { + "node": ">=4.0.0" } }, - "packages/quicktype-typescript-input/node_modules/quicktype-core": { - "version": "20.0.0", - "resolved": "https://registry.npmjs.org/quicktype-core/-/quicktype-core-20.0.0.tgz", - "integrity": "sha512-zuvQAk/i4STnhLC4t3nNWPr6u5ArHBW+TME3jA7YQQMp1UdDsFD+4lzqt49b73aYhhmrk9BlO/fX7PcRR5l6YQ==", + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + }, + "node_modules/cross-fetch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", + "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", "dependencies": { - "@glideapps/ts-necessities": "2.1.2", - "@types/urijs": "^1.19.8", - "browser-or-node": "^1.2.1", - "collection-utils": "^1.0.1", - "is-url": "^1.2.4", - "isomorphic-fetch": "^2.2.1", - "js-base64": "^2.4.3", - "lodash": "^4.17.21", - "pako": "^1.0.6", - "pluralize": "^7.0.0", - "readable-stream": "2.3.7", - "unicode-properties": "^1.4.1", - "urijs": "^1.19.1", - "wordwrap": "^1.0.0", - "yaml": "^1.5.0" + "node-fetch": "^2.6.12" } }, - "packages/quicktype-typescript-input/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" } }, - "packages/quicktype-typescript-input/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, "engines": { - "node": ">= 6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } - } - }, - "dependencies": { - "@75lb/deep-merge": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@75lb/deep-merge/-/deep-merge-1.1.1.tgz", - "integrity": "sha512-xvgv6pkMGBA6GwdyJbNAnDmfAIR/DfWhrj9jgWh3TY7gRm3KO46x/GPjRg6wJ0nOepwqrNxFfojebh0Df4h4Tw==", + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dataloader": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.2.2.tgz", + "integrity": "sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-equal": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz", + "integrity": "sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.1", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.0", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-equal/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dset": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.3.tgz", + "integrity": "sha512-20TuZZHCEZ2O71q9/+8BwKwZ0QtD9D8ObhrihJPr+vLLYlSuAU3/zL4cSlgbfeoGHTjCSJBa7NGcrF9/Bx/WJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.717", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.717.tgz", + "integrity": "sha512-6Fmg8QkkumNOwuZ/5mIbMU9WI3H2fmn5ajcVya64I5Yr5CcNmO7vcLt0Y7c96DCiMO5/9G+4sI2r6eEvdg1F7A==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/enhance-visitors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/enhance-visitors/-/enhance-visitors-1.0.0.tgz", + "integrity": "sha512-+29eJLiUixTEDRaZ35Vu8jP3gPLNcQQkQkOQjLp2X+6cZGGPDD/uasbFzvLsJKnGZnvmyZ0srxudwOtskHeIDA==", + "dev": true, + "dependencies": { + "lodash": "^4.13.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz", + "integrity": "sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.23.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.2.tgz", + "integrity": "sha512-60s3Xv2T2p1ICykc7c+DNDPLDMm9t4QxCOUU0K9JxiLjM3C1zB9YVdN7tjxrFd4+AkZ8CdX1ovUga4P2+1e+/w==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.5", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-get-iterator/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/es-iterator-helpers": { + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.18.tgz", + "integrity": "sha512-scxAJaewsahbqTYrGKJihhViaM6DDZDDoucfvzNbK0pOren1g/daDQ3IAhzn+1G14rBG7w+i5N+qul60++zlKA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-ast-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-ast-utils/-/eslint-ast-utils-1.1.0.tgz", + "integrity": "sha512-otzzTim2/1+lVrlH19EfQQJEhVJSu0zOb9ygb3iapN6UlyaDtyRq4b5U1FuW0v1lRa9Fp/GJyHkSwm6NqABgCA==", + "dev": true, + "dependencies": { + "lodash.get": "^4.4.2", + "lodash.zip": "^4.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-compat-utils": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.0.tgz", + "integrity": "sha512-dc6Y8tzEcSYZMHa+CMPLi/hyo1FzNeonbhJL7Ol0ccuKQkwopJcJBA9YL/xmMTLU1eKigXo9vj9nALElWYSowg==", + "dev": true, + "dependencies": { + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/eslint-config-canonical": { + "version": "41.4.2", + "resolved": "https://registry.npmjs.org/eslint-config-canonical/-/eslint-config-canonical-41.4.2.tgz", + "integrity": "sha512-ayP7OPe7Mh0Vf1K8PXQshekyeM3dNcEVwoJAu5ozrZXftaY36NPaH57Oj1FcmMzr2gpc3WbjQ5frVqxnqjnKMg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.0", + "@babel/eslint-parser": "^7.22.15", + "@babel/eslint-plugin": "^7.22.10", + "@babel/plugin-syntax-import-assertions": "^7.22.5", + "@graphql-eslint/eslint-plugin": "^3.20.1", + "@next/eslint-plugin-next": "^13.5.4", + "@rushstack/eslint-patch": "^1.5.1", + "@typescript-eslint/eslint-plugin": "^6.7.5", + "@typescript-eslint/parser": "^6.7.5", + "eslint-config-prettier": "^9.0.0", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-ava": "^14.0.0", + "eslint-plugin-canonical": "^4.14.0", + "eslint-plugin-cypress": "^2.15.1", + "eslint-plugin-eslint-comments": "^3.2.0", + "eslint-plugin-flowtype": "^8.0.3", + "eslint-plugin-fp": "^2.3.0", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jest": "^27.4.2", + "eslint-plugin-jsdoc": "^46.8.2", + "eslint-plugin-jsonc": "^2.10.0", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-lodash": "^7.4.0", + "eslint-plugin-mocha": "^10.2.0", + "eslint-plugin-modules-newline": "0.0.6", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^5.0.1", + "eslint-plugin-promise": "^6.1.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-regexp": "^1.15.0", + "eslint-plugin-simple-import-sort": "^10.0.0", + "eslint-plugin-typescript-sort-keys": "^3.0.0", + "eslint-plugin-unicorn": "^48.0.1", + "eslint-plugin-vitest": "^0.3.2", + "eslint-plugin-yml": "^1.10.0", + "eslint-plugin-zod": "^1.4.0", + "prettier": "^3.0.3", + "ramda": "^0.29.1", + "yaml-eslint-parser": "^1.2.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "eslint": "^8.30.0" + } + }, + "node_modules/eslint-config-canonical/node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-config-canonical/node_modules/eslint-plugin-canonical": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-canonical/-/eslint-plugin-canonical-4.18.0.tgz", + "integrity": "sha512-0Egc0FKOnCRdu3bFEJhfHkdkusIgW0UxdemukkowZQnQsnf12FHSJ7K26b+tZ5pKB7cTyECSaqvEpoIJfplX4g==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "^6.1.0", + "chance": "^1.1.11", + "debug": "^4.3.4", + "eslint-import-resolver-typescript": "^3.5.3", + "eslint-module-utils": "^2.7.4", + "is-get-set-prop": "^1.0.0", + "is-js-type": "^2.0.0", + "is-obj-prop": "^1.0.0", + "is-proto-prop": "^2.0.0", + "lodash": "^4.17.21", + "natural-compare": "^1.4.0", + "recast": "^0.23.2", + "roarr": "^7.14.2", + "ts-unused-exports": "^9.0.3", + "xregexp": "^5.1.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/eslint-config-canonical/node_modules/eslint-plugin-prettier": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", + "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.6" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-config-canonical/node_modules/synckit": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "dev": true, + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/eslint-config-canonical/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, + "node_modules/eslint-config-prettier": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz", + "integrity": "sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw==", + "dev": true, + "dependencies": { + "get-stdin": "^6.0.0" + }, + "bin": { + "eslint-config-prettier-check": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=3.14.1" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", + "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "fast-glob": "^3.3.1", + "get-tsconfig": "^4.5.0", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-ava": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-ava/-/eslint-plugin-ava-14.0.0.tgz", + "integrity": "sha512-XmKT6hppaipwwnLVwwvQliSU6AF1QMHiNoLD5JQfzhUhf0jY7CO0O624fQrE+Y/fTb9vbW8r77nKf7M/oHulxw==", + "dev": true, + "dependencies": { + "enhance-visitors": "^1.0.0", + "eslint-utils": "^3.0.0", + "espree": "^9.0.0", + "espurify": "^2.1.1", + "import-modules": "^2.1.0", + "micro-spelling-correcter": "^1.1.1", + "pkg-dir": "^5.0.0", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=14.17 <15 || >=16.4" + }, + "peerDependencies": { + "eslint": ">=8.26.0" + } + }, + "node_modules/eslint-plugin-ava/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint-plugin-canonical": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-canonical/-/eslint-plugin-canonical-3.4.0.tgz", + "integrity": "sha512-akY2RpJD3VC2XXsU/02VsbzkHfybsZTsruOKPI7pJzQ+lZaS3UGM1H0vUKf0itXsbMHHJbIT78hUXU2d2HemZQ==", + "dev": true, + "dependencies": { + "is-get-set-prop": "^1.0.0", + "is-js-type": "^2.0.0", + "is-obj-prop": "^1.0.0", + "is-proto-prop": "^2.0.0", + "lodash": "^4.17.21", + "natural-compare": "^1.4.0", + "ts-unused-exports": "^9.0.3", + "xregexp": "^5.1.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/eslint-plugin-cypress": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-cypress/-/eslint-plugin-cypress-2.15.1.tgz", + "integrity": "sha512-eLHLWP5Q+I4j2AWepYq0PgFEei9/s5LvjuSqWrxurkg1YZ8ltxdvMNmdSf0drnsNo57CTgYY/NIHHLRSWejR7w==", + "dev": true, + "dependencies": { + "globals": "^13.20.0" + }, + "peerDependencies": { + "eslint": ">= 3.2.1" + } + }, + "node_modules/eslint-plugin-es": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", + "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", + "dev": true, + "dependencies": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=4.19.1" + } + }, + "node_modules/eslint-plugin-es/node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/eslint-plugin-es/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-plugin-eslint-comments": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.2.0.tgz", + "integrity": "sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5", + "ignore": "^5.0.5" + }, + "engines": { + "node": ">=6.5.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=4.19.1" + } + }, + "node_modules/eslint-plugin-flowtype": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz", + "integrity": "sha512-dX8l6qUL6O+fYPtpNRideCFSpmWOUVx5QcaGLVqe/vlDiBSe4vYljDWDETwnyFzpl7By/WVIu6rcrniCgH9BqQ==", + "dev": true, + "dependencies": { + "lodash": "^4.17.21", + "string-natural-compare": "^3.0.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@babel/plugin-syntax-flow": "^7.14.5", + "@babel/plugin-transform-react-jsx": "^7.14.9", + "eslint": "^8.1.0" + } + }, + "node_modules/eslint-plugin-fp": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-fp/-/eslint-plugin-fp-2.3.0.tgz", + "integrity": "sha512-3n2oHibwoIxAht9/+ZaTldhI6brXORgl8oNXqZd+d9xuAQt2SBJ2/aml0oQRMWvXrgsz2WG6wfC++NjzSG3prA==", + "dev": true, + "dependencies": { + "create-eslint-index": "^1.0.0", + "eslint-ast-utils": "^1.0.0", + "lodash": "^4.13.1", + "req-all": "^0.1.0" + }, + "engines": { + "node": ">=4.0.0" + }, + "peerDependencies": { + "eslint": ">=3" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jest": { + "version": "27.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz", + "integrity": "sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "^5.10.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0 || ^7.0.0", + "eslint": "^7.0.0 || ^8.0.0", + "jest": "*" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-jest/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-plugin-jest/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-plugin-jest/node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/eslint-plugin-jsdoc": { + "version": "46.10.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.10.1.tgz", + "integrity": "sha512-x8wxIpv00Y50NyweDUpa+58ffgSAI5sqe+zcZh33xphD0AVh+1kqr1ombaTRb7Fhpove1zfUuujlX9DWWBP5ag==", + "dev": true, + "dependencies": { + "@es-joy/jsdoccomment": "~0.41.0", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.1", + "debug": "^4.3.4", + "escape-string-regexp": "^4.0.0", + "esquery": "^1.5.0", + "is-builtin-module": "^3.2.1", + "semver": "^7.5.4", + "spdx-expression-parse": "^4.0.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-json": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-json/-/eslint-plugin-json-3.1.0.tgz", + "integrity": "sha512-MrlG2ynFEHe7wDGwbUuFPsaT2b1uhuEFhJ+W1f1u+1C2EkXmTYJp4B1aAdQQ8M+CC3t//N/oRKiIVw14L2HR1g==", + "dev": true, + "dependencies": { + "lodash": "^4.17.21", + "vscode-json-languageservice": "^4.1.6" + }, + "engines": { + "node": ">=12.0" + } + }, + "node_modules/eslint-plugin-jsonc": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsonc/-/eslint-plugin-jsonc-2.14.1.tgz", + "integrity": "sha512-Tei6G4N7pZulP5MHi0EIdtseiCqUPkDMd0O8Zrw4muMIlsjJ5/B9X+U3Pfo6B7l0mTL9LN9FwuWT70dRJ6z7tg==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "eslint-compat-utils": "^0.5.0", + "espree": "^9.6.1", + "graphemer": "^1.4.0", + "jsonc-eslint-parser": "^2.0.4", + "natural-compare": "^1.4.0", + "synckit": "^0.6.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz", + "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.23.2", + "aria-query": "^5.3.0", + "array-includes": "^3.1.7", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "=4.7.0", + "axobject-query": "^3.2.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "es-iterator-helpers": "^1.0.15", + "hasown": "^2.0.0", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.entries": "^1.1.7", + "object.fromentries": "^2.0.7" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/eslint-plugin-lodash": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-lodash/-/eslint-plugin-lodash-7.4.0.tgz", + "integrity": "sha512-Tl83UwVXqe1OVeBRKUeWcfg6/pCW1GTRObbdnbEJgYwjxp5Q92MEWQaH9+dmzbRt6kvYU1Mp893E79nJiCSM8A==", + "dev": true, + "dependencies": { + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": ">=2" + } + }, + "node_modules/eslint-plugin-mocha": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-10.4.1.tgz", + "integrity": "sha512-G85ALUgKaLzuEuHhoW3HVRgPTmia6njQC3qCG6CEvA8/Ja9PDZnRZOuzekMki+HaViEQXINuYsmhp5WR5/4MfA==", + "dev": true, + "dependencies": { + "eslint-utils": "^3.0.0", + "globals": "^13.24.0", + "rambda": "^7.4.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-modules-newline": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/eslint-plugin-modules-newline/-/eslint-plugin-modules-newline-0.0.6.tgz", + "integrity": "sha512-69NpBr68U6pmXL+y+KHl/64PwRarceC3/sCNUVxRbe0gPI32SIw8AtdpkqNiJYCa2yMd4lRrkrnU09Yio7KVzA==", + "dev": true, + "dependencies": { + "requireindex": "~1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-node": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", + "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", + "dev": true, + "dependencies": { + "eslint-plugin-es": "^3.0.0", + "eslint-utils": "^2.0.0", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" + }, + "engines": { + "node": ">=8.10.0" + }, + "peerDependencies": { + "eslint": ">=5.16.0" + } + }, + "node_modules/eslint-plugin-node/node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/eslint-plugin-node/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-plugin-node/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-promise": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", + "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.34.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz", + "integrity": "sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlast": "^1.2.4", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.toreversed": "^1.1.2", + "array.prototype.tosorted": "^1.1.3", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.17", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.7", + "object.fromentries": "^2.0.7", + "object.hasown": "^1.1.3", + "object.values": "^1.1.7", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.10" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-regexp": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-1.15.0.tgz", + "integrity": "sha512-YEtQPfdudafU7RBIFci81R/Q1yErm0mVh3BkGnXD2Dk8DLwTFdc2ITYH1wCnHKim2gnHfPFgrkh+b2ozyyU7ag==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "comment-parser": "^1.1.2", + "grapheme-splitter": "^1.0.4", + "jsdoctypeparser": "^9.0.0", + "refa": "^0.11.0", + "regexp-ast-analysis": "^0.6.0", + "scslre": "^0.2.0" + }, + "engines": { + "node": "^12 || >=14" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/eslint-plugin-simple-import-sort": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-10.0.0.tgz", + "integrity": "sha512-AeTvO9UCMSNzIHRkg8S6c3RPy5YEwKWSQPx3DYghLedo2ZQxowPFLGDN1AZ2evfg6r6mjBSZSLxLFsWSu3acsw==", + "dev": true, + "peerDependencies": { + "eslint": ">=5.0.0" + } + }, + "node_modules/eslint-plugin-typescript-sort-keys": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-typescript-sort-keys/-/eslint-plugin-typescript-sort-keys-3.2.0.tgz", + "integrity": "sha512-GutszvriaVtwmn7pQjuj9/9o0iXhD7XZs0/424+zsozdRr/fdg5e8206t478Vnqnqi1GjuxcAolj1kf74KnhPA==", + "dev": true, + "dependencies": { + "@typescript-eslint/experimental-utils": "^5.0.0", + "json-schema": "^0.4.0", + "natural-compare-lite": "^1.4.0" + }, + "engines": { + "node": ">= 16" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6 || ^7", + "eslint": "^7 || ^8", + "typescript": "^3 || ^4 || ^5" + } + }, + "node_modules/eslint-plugin-unicorn": { + "version": "48.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-48.0.1.tgz", + "integrity": "sha512-FW+4r20myG/DqFcCSzoumaddKBicIPeFnTrifon2mWIzlfyvzwyqZjqVP7m4Cqr/ZYisS2aiLghkUWaPg6vtCw==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.5", + "@eslint-community/eslint-utils": "^4.4.0", + "ci-info": "^3.8.0", + "clean-regexp": "^1.0.0", + "esquery": "^1.5.0", + "indent-string": "^4.0.0", + "is-builtin-module": "^3.2.1", + "jsesc": "^3.0.2", + "lodash": "^4.17.21", + "pluralize": "^8.0.0", + "read-pkg-up": "^7.0.1", + "regexp-tree": "^0.1.27", + "regjsparser": "^0.10.0", + "semver": "^7.5.4", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sindresorhus/eslint-plugin-unicorn?sponsor=1" + }, + "peerDependencies": { + "eslint": ">=8.44.0" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-plugin-vitest": { + "version": "0.3.26", + "resolved": "https://registry.npmjs.org/eslint-plugin-vitest/-/eslint-plugin-vitest-0.3.26.tgz", + "integrity": "sha512-oxe5JSPgRjco8caVLTh7Ti8PxpwJdhSV0hTQAmkFcNcmy/9DnqLB/oNVRA11RmVRP//2+jIIT6JuBEcpW3obYg==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "^7.1.1" + }, + "engines": { + "node": "^18.0.0 || >= 20.0.0" + }, + "peerDependencies": { + "eslint": ">=8.0.0", + "vitest": "*" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "vitest": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/scope-manager": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz", + "integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/visitor-keys": "7.4.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/types": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz", + "integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz", + "integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/visitor-keys": "7.4.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/utils": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.4.0.tgz", + "integrity": "sha512-NQt9QLM4Tt8qrlBVY9lkMYzfYtNz8/6qwZg8pI3cMGlPnj6mOpRxxAm7BMJN9K0AiY+1BwJ5lVC650YJqYOuNg==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "7.4.0", + "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/typescript-estree": "7.4.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz", + "integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.4.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-vitest/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/eslint-plugin-vitest/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/eslint-plugin-yml": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-yml/-/eslint-plugin-yml-1.13.2.tgz", + "integrity": "sha512-1i71VhmsG5UxE41rIJmJjhlTTxYy7upAY5Hqj8AdBc7rfJzRIZr3a2spuOS8+N7ZDCWsHAWY3J6lzQNQHDv6Uw==", + "dev": true, + "dependencies": { + "debug": "^4.3.2", + "eslint-compat-utils": "^0.5.0", + "lodash": "^4.17.21", + "natural-compare": "^1.4.0", + "yaml-eslint-parser": "^1.2.1" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/eslint-plugin-zod": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-zod/-/eslint-plugin-zod-1.4.0.tgz", + "integrity": "sha512-i9WzQGw2X5fQcuQh33mA8DQjZJM/yuyZvs1Fc5EyTidX7Ed/g832+1FEQ4u5gtXy+jZ+DVsB5+oMHj4tIOfeZg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "eslint": ">=8.1.0" + } + }, + "node_modules/eslint-rule-composer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz", + "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/eslint/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/espurify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/espurify/-/espurify-2.1.1.tgz", + "integrity": "sha512-zttWvnkhcDyGOhSH4vO2qCBILpdCMv/MX8lp4cqgRkQoDRGK2oZxi2GfWhlP2dIXmk7BaKeOTuzbHhyC68o8XQ==", + "dev": true + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/exec-sh": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.1.tgz", + "integrity": "sha512-aLt95pexaugVtQerpmE51+4QfWrNc304uez7jvj6fWnN8GeEHpttB8F36n8N7uVhUMbH/1enbxQ9HImZ4w/9qg==", + "dev": true, + "dependencies": { + "merge": "^1.1.3" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/extract-files": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-11.0.0.tgz", + "integrity": "sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ==", + "dev": true, + "engines": { + "node": "^12.20 || >= 14.13" + }, + "funding": { + "url": "https://github.com/sponsors/jaydenseric" + } + }, + "node_modules/fast-decode-uri-component": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", + "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==", + "dev": true + }, + "node_modules/fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "dev": true + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fast-printf": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/fast-printf/-/fast-printf-1.6.9.tgz", + "integrity": "sha512-FChq8hbz65WMj4rstcQsFB0O7Cy++nmbNfLYnD9cYv2cRn8EG6k/MGn9kO/tjO66t09DLDugj3yL+V2o6Qftrg==", + "dev": true, + "dependencies": { + "boolean": "^3.1.4" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/fast-querystring": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fast-querystring/-/fast-querystring-1.1.2.tgz", + "integrity": "sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==", + "dev": true, + "dependencies": { + "fast-decode-uri-component": "^1.0.1" + } + }, + "node_modules/fast-url-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", + "dev": true, + "dependencies": { + "punycode": "^1.3.2" + } + }, + "node_modules/fast-url-parser/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-replace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", + "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "dependencies": { + "array-back": "^3.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-set-props": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-set-props/-/get-set-props-0.1.0.tgz", + "integrity": "sha512-7oKuKzAGKj0ag+eWZwcGw2fjiZ78tXnXQoBgY0aU7ZOxTu4bB7hSuQSDgtKy978EDH062P5FmD2EWiDpQS9K9Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/get-stdin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.3.tgz", + "integrity": "sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/graphql": { + "version": "0.11.7", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-0.11.7.tgz", + "integrity": "sha512-x7uDjyz8Jx+QPbpCFCMQ8lltnQa4p4vSYHx6ADe8rVYRTdsyhCJbvSty5DAsLVmU6cGakl+r8HQYolKHxk/tiw==", + "dependencies": { + "iterall": "1.1.3" + } + }, + "node_modules/graphql-config": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/graphql-config/-/graphql-config-4.5.0.tgz", + "integrity": "sha512-x6D0/cftpLUJ0Ch1e5sj1TZn6Wcxx4oMfmhaG9shM0DKajA9iR+j1z86GSTQ19fShbGvrSSvbIQsHku6aQ6BBw==", + "dev": true, + "dependencies": { + "@graphql-tools/graphql-file-loader": "^7.3.7", + "@graphql-tools/json-file-loader": "^7.3.7", + "@graphql-tools/load": "^7.5.5", + "@graphql-tools/merge": "^8.2.6", + "@graphql-tools/url-loader": "^7.9.7", + "@graphql-tools/utils": "^9.0.0", + "cosmiconfig": "8.0.0", + "jiti": "1.17.1", + "minimatch": "4.2.3", + "string-env-interpolation": "1.0.1", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "cosmiconfig-toml-loader": "^1.0.0", + "graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + }, + "peerDependenciesMeta": { + "cosmiconfig-toml-loader": { + "optional": true + } + } + }, + "node_modules/graphql-config/node_modules/@graphql-tools/graphql-file-loader": { + "version": "7.5.17", + "resolved": "https://registry.npmjs.org/@graphql-tools/graphql-file-loader/-/graphql-file-loader-7.5.17.tgz", + "integrity": "sha512-hVwwxPf41zOYgm4gdaZILCYnKB9Zap7Ys9OhY1hbwuAuC4MMNY9GpUjoTU3CQc3zUiPoYStyRtUGkHSJZ3HxBw==", + "dev": true, + "dependencies": { + "@graphql-tools/import": "6.7.18", + "@graphql-tools/utils": "^9.2.1", + "globby": "^11.0.3", + "tslib": "^2.4.0", + "unixify": "^1.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/graphql-config/node_modules/@graphql-tools/graphql-file-loader/node_modules/@graphql-tools/import": { + "version": "6.7.18", + "resolved": "https://registry.npmjs.org/@graphql-tools/import/-/import-6.7.18.tgz", + "integrity": "sha512-XQDdyZTp+FYmT7as3xRWH/x8dx0QZA2WZqfMF5EWb36a0PiH7WwlRQYIdyYXj8YCLpiWkeBXgBRHmMnwEYR8iQ==", + "dev": true, + "dependencies": { + "@graphql-tools/utils": "^9.2.1", + "resolve-from": "5.0.0", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/graphql-config/node_modules/@graphql-tools/json-file-loader": { + "version": "7.4.18", + "resolved": "https://registry.npmjs.org/@graphql-tools/json-file-loader/-/json-file-loader-7.4.18.tgz", + "integrity": "sha512-AJ1b6Y1wiVgkwsxT5dELXhIVUPs/u3VZ8/0/oOtpcoyO/vAeM5rOvvWegzicOOnQw8G45fgBRMkkRfeuwVt6+w==", + "dev": true, + "dependencies": { + "@graphql-tools/utils": "^9.2.1", + "globby": "^11.0.3", + "tslib": "^2.4.0", + "unixify": "^1.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/graphql-config/node_modules/@graphql-tools/load": { + "version": "7.8.14", + "resolved": "https://registry.npmjs.org/@graphql-tools/load/-/load-7.8.14.tgz", + "integrity": "sha512-ASQvP+snHMYm+FhIaLxxFgVdRaM0vrN9wW2BKInQpktwWTXVyk+yP5nQUCEGmn0RTdlPKrffBaigxepkEAJPrg==", + "dev": true, + "dependencies": { + "@graphql-tools/schema": "^9.0.18", + "@graphql-tools/utils": "^9.2.1", + "p-limit": "3.1.0", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/graphql-config/node_modules/@graphql-tools/load/node_modules/@graphql-tools/schema": { + "version": "9.0.19", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-9.0.19.tgz", + "integrity": "sha512-oBRPoNBtCkk0zbUsyP4GaIzCt8C0aCI4ycIRUL67KK5pOHljKLBBtGT+Jr6hkzA74C8Gco8bpZPe7aWFjiaK2w==", + "dev": true, + "dependencies": { + "@graphql-tools/merge": "^8.4.1", + "@graphql-tools/utils": "^9.2.1", + "tslib": "^2.4.0", + "value-or-promise": "^1.0.12" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/graphql-config/node_modules/@graphql-tools/merge": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.4.2.tgz", + "integrity": "sha512-XbrHAaj8yDuINph+sAfuq3QCZ/tKblrTLOpirK0+CAgNlZUCHs0Fa+xtMUURgwCVThLle1AF7svJCxFizygLsw==", + "dev": true, + "dependencies": { + "@graphql-tools/utils": "^9.2.1", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/graphql-config/node_modules/@graphql-tools/url-loader": { + "version": "7.17.18", + "resolved": "https://registry.npmjs.org/@graphql-tools/url-loader/-/url-loader-7.17.18.tgz", + "integrity": "sha512-ear0CiyTj04jCVAxi7TvgbnGDIN2HgqzXzwsfcqiVg9cvjT40NcMlZ2P1lZDgqMkZ9oyLTV8Bw6j+SyG6A+xPw==", + "dev": true, + "dependencies": { + "@ardatan/sync-fetch": "^0.0.1", + "@graphql-tools/delegate": "^9.0.31", + "@graphql-tools/executor-graphql-ws": "^0.0.14", + "@graphql-tools/executor-http": "^0.1.7", + "@graphql-tools/executor-legacy-ws": "^0.0.11", + "@graphql-tools/utils": "^9.2.1", + "@graphql-tools/wrap": "^9.4.2", + "@types/ws": "^8.0.0", + "@whatwg-node/fetch": "^0.8.0", + "isomorphic-ws": "^5.0.0", + "tslib": "^2.4.0", + "value-or-promise": "^1.0.11", + "ws": "^8.12.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/graphql-config/node_modules/@graphql-tools/url-loader/node_modules/@graphql-tools/delegate": { + "version": "9.0.35", + "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-9.0.35.tgz", + "integrity": "sha512-jwPu8NJbzRRMqi4Vp/5QX1vIUeUPpWmlQpOkXQD2r1X45YsVceyUUBnktCrlJlDB4jPRVy7JQGwmYo3KFiOBMA==", + "dev": true, + "dependencies": { + "@graphql-tools/batch-execute": "^8.5.22", + "@graphql-tools/executor": "^0.0.20", + "@graphql-tools/schema": "^9.0.19", + "@graphql-tools/utils": "^9.2.1", + "dataloader": "^2.2.2", + "tslib": "^2.5.0", + "value-or-promise": "^1.0.12" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/graphql-config/node_modules/@graphql-tools/url-loader/node_modules/@graphql-tools/delegate/node_modules/@graphql-tools/batch-execute": { + "version": "8.5.22", + "resolved": "https://registry.npmjs.org/@graphql-tools/batch-execute/-/batch-execute-8.5.22.tgz", + "integrity": "sha512-hcV1JaY6NJQFQEwCKrYhpfLK8frSXDbtNMoTur98u10Cmecy1zrqNKSqhEyGetpgHxaJRqszGzKeI3RuroDN6A==", + "dev": true, + "dependencies": { + "@graphql-tools/utils": "^9.2.1", + "dataloader": "^2.2.2", + "tslib": "^2.4.0", + "value-or-promise": "^1.0.12" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/graphql-config/node_modules/@graphql-tools/url-loader/node_modules/@graphql-tools/delegate/node_modules/@graphql-tools/executor": { + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/@graphql-tools/executor/-/executor-0.0.20.tgz", + "integrity": "sha512-GdvNc4vszmfeGvUqlcaH1FjBoguvMYzxAfT6tDd4/LgwymepHhinqLNA5otqwVLW+JETcDaK7xGENzFomuE6TA==", + "dev": true, + "dependencies": { + "@graphql-tools/utils": "^9.2.1", + "@graphql-typed-document-node/core": "3.2.0", + "@repeaterjs/repeater": "^3.0.4", + "tslib": "^2.4.0", + "value-or-promise": "^1.0.12" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/graphql-config/node_modules/@graphql-tools/url-loader/node_modules/@graphql-tools/delegate/node_modules/@graphql-tools/schema": { + "version": "9.0.19", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-9.0.19.tgz", + "integrity": "sha512-oBRPoNBtCkk0zbUsyP4GaIzCt8C0aCI4ycIRUL67KK5pOHljKLBBtGT+Jr6hkzA74C8Gco8bpZPe7aWFjiaK2w==", + "dev": true, + "dependencies": { + "@graphql-tools/merge": "^8.4.1", + "@graphql-tools/utils": "^9.2.1", + "tslib": "^2.4.0", + "value-or-promise": "^1.0.12" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/graphql-config/node_modules/@graphql-tools/url-loader/node_modules/@graphql-tools/executor-graphql-ws": { + "version": "0.0.14", + "resolved": "https://registry.npmjs.org/@graphql-tools/executor-graphql-ws/-/executor-graphql-ws-0.0.14.tgz", + "integrity": "sha512-P2nlkAsPZKLIXImFhj0YTtny5NQVGSsKnhi7PzXiaHSXc6KkzqbWZHKvikD4PObanqg+7IO58rKFpGXP7eeO+w==", + "dev": true, + "dependencies": { + "@graphql-tools/utils": "^9.2.1", + "@repeaterjs/repeater": "3.0.4", + "@types/ws": "^8.0.0", + "graphql-ws": "5.12.1", + "isomorphic-ws": "5.0.0", + "tslib": "^2.4.0", + "ws": "8.13.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/graphql-config/node_modules/@graphql-tools/url-loader/node_modules/@graphql-tools/executor-http": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/@graphql-tools/executor-http/-/executor-http-0.1.10.tgz", + "integrity": "sha512-hnAfbKv0/lb9s31LhWzawQ5hghBfHS+gYWtqxME6Rl0Aufq9GltiiLBcl7OVVOnkLF0KhwgbYP1mB5VKmgTGpg==", + "dev": true, + "dependencies": { + "@graphql-tools/utils": "^9.2.1", + "@repeaterjs/repeater": "^3.0.4", + "@whatwg-node/fetch": "^0.8.1", + "dset": "^3.1.2", + "extract-files": "^11.0.0", + "meros": "^1.2.1", + "tslib": "^2.4.0", + "value-or-promise": "^1.0.12" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/graphql-config/node_modules/@graphql-tools/url-loader/node_modules/@graphql-tools/executor-legacy-ws": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/@graphql-tools/executor-legacy-ws/-/executor-legacy-ws-0.0.11.tgz", + "integrity": "sha512-4ai+NnxlNfvIQ4c70hWFvOZlSUN8lt7yc+ZsrwtNFbFPH/EroIzFMapAxM9zwyv9bH38AdO3TQxZ5zNxgBdvUw==", + "dev": true, + "dependencies": { + "@graphql-tools/utils": "^9.2.1", + "@types/ws": "^8.0.0", + "isomorphic-ws": "5.0.0", + "tslib": "^2.4.0", + "ws": "8.13.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/graphql-config/node_modules/@graphql-tools/url-loader/node_modules/@graphql-tools/wrap": { + "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/wrap/-/wrap-9.4.2.tgz", + "integrity": "sha512-DFcd9r51lmcEKn0JW43CWkkI2D6T9XI1juW/Yo86i04v43O9w2/k4/nx2XTJv4Yv+iXwUw7Ok81PGltwGJSDSA==", + "dev": true, + "dependencies": { + "@graphql-tools/delegate": "^9.0.31", + "@graphql-tools/schema": "^9.0.18", + "@graphql-tools/utils": "^9.2.1", + "tslib": "^2.4.0", + "value-or-promise": "^1.0.12" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/graphql-config/node_modules/@graphql-tools/url-loader/node_modules/@graphql-tools/wrap/node_modules/@graphql-tools/schema": { + "version": "9.0.19", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-9.0.19.tgz", + "integrity": "sha512-oBRPoNBtCkk0zbUsyP4GaIzCt8C0aCI4ycIRUL67KK5pOHljKLBBtGT+Jr6hkzA74C8Gco8bpZPe7aWFjiaK2w==", + "dev": true, + "dependencies": { + "@graphql-tools/merge": "^8.4.1", + "@graphql-tools/utils": "^9.2.1", + "tslib": "^2.4.0", + "value-or-promise": "^1.0.12" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/graphql-config/node_modules/@graphql-tools/utils": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-9.2.1.tgz", + "integrity": "sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A==", + "dev": true, + "dependencies": { + "@graphql-typed-document-node/core": "^3.1.1", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/graphql-config/node_modules/minimatch": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.3.tgz", + "integrity": "sha512-lIUdtK5hdofgCTu3aT0sOaHsYR37viUuIc0rwnnDXImbwFRcumyLMeZaM0t0I/fgxS6s6JMfu0rLD1Wz9pv1ng==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/graphql-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/graphql-config/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, + "node_modules/graphql-config/node_modules/ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/graphql-depth-limit": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/graphql-depth-limit/-/graphql-depth-limit-1.1.0.tgz", + "integrity": "sha512-+3B2BaG8qQ8E18kzk9yiSdAa75i/hnnOwgSeAxVJctGQPvmeiLtqKOYF6HETCyRjiF7Xfsyal0HbLlxCQkgkrw==", + "dev": true, + "dependencies": { + "arrify": "^1.0.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "graphql": "*" + } + }, + "node_modules/graphql-ws": { + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.12.1.tgz", + "integrity": "sha512-umt4f5NnMK46ChM2coO36PTFhHouBrK9stWWBczERguwYrGnPNxJ9dimU6IyOBfOkC6Izhkg4H8+F51W/8CYDg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "graphql": ">=0.11 <=16" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-modules": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-modules/-/import-modules-2.1.0.tgz", + "integrity": "sha512-8HEWcnkbGpovH9yInoisxaSoIg9Brbul+Ju3Kqe2UsYDUBJD/iQjSgEj0zPcTDPKfPp2fs5xlv1i+JSye/m1/A==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-builtin-module": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", + "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "dev": true, + "dependencies": { + "builtin-modules": "^3.3.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-builtin-module/node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-get-set-prop": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-get-set-prop/-/is-get-set-prop-1.0.0.tgz", + "integrity": "sha512-DvAYZ1ZgGUz4lzxKMPYlt08qAUqyG9ckSg2pIjfvcQ7+pkVNUHk8yVLXOnCLe5WKXhLop8oorWFBJHpwWQpszQ==", + "dev": true, + "dependencies": { + "get-set-props": "^0.1.0", + "lowercase-keys": "^1.0.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-js-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-js-type/-/is-js-type-2.0.0.tgz", + "integrity": "sha512-Aj13l47+uyTjlQNHtXBV8Cji3jb037vxwMWCgopRR8h6xocgBGW3qG8qGlIOEmbXQtkKShKuBM9e8AA1OeQ+xw==", + "dev": true, + "dependencies": { + "js-types": "^1.0.0" + } + }, + "node_modules/is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-obj-prop": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-obj-prop/-/is-obj-prop-1.0.0.tgz", + "integrity": "sha512-5Idb61slRlJlsAzi0Wsfwbp+zZY+9LXKUAZpvT/1ySw+NxKLRWfa0Bzj+wXI3fX5O9hiddm5c3DAaRSNP/yl2w==", + "dev": true, + "dependencies": { + "lowercase-keys": "^1.0.0", + "obj-props": "^1.0.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-proto-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-proto-prop/-/is-proto-prop-2.0.0.tgz", + "integrity": "sha512-jl3NbQ/fGLv5Jhan4uX+Ge9ohnemqyblWVVCpAvtTQzNFvV2xhJq+esnkIbYQ9F1nITXoLfDDQLp7LBw/zzncg==", + "dev": true, + "dependencies": { + "lowercase-keys": "^1.0.0", + "proto-props": "^2.0.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" + }, + "node_modules/is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isomorphic-ws": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", + "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "dev": true, + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/iterall": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.1.3.tgz", + "integrity": "sha512-Cu/kb+4HiNSejAPhSaN1VukdNTTi/r4/e+yykqjlG/IW+1gZH5b4+Bq3whDX4tvbYugta3r8KTMUiqT3fIGxuQ==" + }, + "node_modules/iterator.prototype": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", + "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + } + }, + "node_modules/jiti": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.17.1.tgz", + "integrity": "sha512-NZIITw8uZQFuzQimqjUxIrIcEdxYDFIe/0xYfIlVXTkiBjjyBEvgasj5bb0/cHtPRD/NziPbT312sFrkI5ALpw==", + "dev": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-base64": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.3.tgz", + "integrity": "sha512-H7ErYLM34CvDMto3GbD6xD0JLUGYXR3QTcH6B/tr4Hi/QpSThnCsIp+Sy5FRTw3B0d6py4HcNkW7nO/wdtGWEw==" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-types": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/js-types/-/js-types-1.0.0.tgz", + "integrity": "sha512-bfwqBW9cC/Lp7xcRpug7YrXm0IVw+T9e3g4mCYnv0Pjr3zIzU9PCQElYU9oSGAWzXlbdl9X5SAMPejO9sxkeUw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsdoc-type-pratt-parser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", + "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", + "dev": true, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/jsdoctypeparser": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/jsdoctypeparser/-/jsdoctypeparser-9.0.0.tgz", + "integrity": "sha512-jrTA2jJIL6/DAEILBEh2/w9QxCuwmvNXIry39Ay/HVfhE3o2yVV0U44blYkqdHA/OKloJEqvJy0xU+GSdE2SIw==", + "dev": true, + "bin": { + "jsdoctypeparser": "bin/jsdoctypeparser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-eslint-parser": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonc-eslint-parser/-/jsonc-eslint-parser-2.4.0.tgz", + "integrity": "sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==", + "dev": true, + "dependencies": { + "acorn": "^8.5.0", + "eslint-visitor-keys": "^3.0.0", + "espree": "^9.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + } + }, + "node_modules/jsonc-parser": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", + "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", + "dev": true + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", + "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==", + "dev": true + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.assignwith": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assignwith/-/lodash.assignwith-4.2.0.tgz", + "integrity": "sha512-ZznplvbvtjK2gMvnQ1BR/zqPFZmS6jbK4p+6Up4xcRYA7yMIwxHCfbTcrYxXKzzqLsQ05eJPVznEW3tuwV7k1g==" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "dev": true + }, + "node_modules/lodash.lowercase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.lowercase/-/lodash.lowercase-4.3.0.tgz", + "integrity": "sha512-UcvP1IZYyDKyEL64mmrwoA1AbFu5ahojhTtkOUr1K9dbuxzS9ev8i4TxMMGCqRC9TE8uDaSoufNAXxRPNTseVA==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.zip": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz", + "integrity": "sha512-C7IOaBBK/0gMORRBd8OETNx3kmOkgIWIPvyDpZSCTwUrpYmgZwJkjZeOD8ww4xbOUOs4/attY+pciKvadNfFbg==", + "dev": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-error": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz", + "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==" + }, + "node_modules/merge": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz", + "integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/meros": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/meros/-/meros-1.3.0.tgz", + "integrity": "sha512-2BNGOimxEz5hmjUG2FwoxCt5HN7BXdaWyFqEwxPTrJzVdABtrL4TiHTcsWSFAxPQ/tOnEaQEJh3qWq71QRMY+w==", + "dev": true, + "engines": { + "node": ">=13" + }, + "peerDependencies": { + "@types/node": ">=13" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/micro-spelling-correcter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/micro-spelling-correcter/-/micro-spelling-correcter-1.1.1.tgz", + "integrity": "sha512-lkJ3Rj/mtjlRcHk6YyCbvZhyWTOzdBvTHsxMmZSk5jxN1YyVSQ+JETAom55mdzfcyDrY/49Z7UCW760BK30crg==", + "dev": true + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", + "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, + "node_modules/node-fetch": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", + "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/obj-props": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/obj-props/-/obj-props-1.4.0.tgz", + "integrity": "sha512-p7p/7ltzPDiBs6DqxOrIbtRdwxxVRBj5ROukeNb9RgA+fawhrz5n2hpNz8DDmYR//tviJSj7nUnlppGmONkjiQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.hasown": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.4.tgz", + "integrity": "sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pako": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", + "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-equal": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/path-equal/-/path-equal-1.2.5.tgz", + "integrity": "sha512-i73IctDr3F2W+bsOWDyyVm/lqsXO47aY9nsFZUjTT/aljSbkxHxxCoyZ9UUrM8jK0JVod+An+rl48RCsvWM+9g==" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "dev": true, + "dependencies": { + "find-up": "^5.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "engines": { + "node": ">=4" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/promise-timeout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/promise-timeout/-/promise-timeout-1.3.0.tgz", + "integrity": "sha512-5yANTE0tmi5++POym6OgtFmwfDvOXABD9oj/jLQr5GPEyuNEb7jH4wbbANJceJid49jwhi1RddxnhnEAb/doqg==", + "dev": true + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/proto-props": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/proto-props/-/proto-props-2.0.0.tgz", + "integrity": "sha512-2yma2tog9VaRZY2mn3Wq51uiSW4NcPYT1cQdBagwyrznrilKSZwIZ0UG3ZPL/mx+axEns0hE35T5ufOYZXEnBQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pvtsutils": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.5.tgz", + "integrity": "sha512-ARvb14YB9Nm2Xi6nBq1ZX6dAM0FsJnuk+31aUp4TrcZEdKUlSqOqsxJHUPJDNE3qiIp+iUPEIeR6Je/tgV7zsA==", + "dev": true, + "dependencies": { + "tslib": "^2.6.1" + } + }, + "node_modules/pvtsutils/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, + "node_modules/pvutils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quicktype-core": { + "resolved": "packages/quicktype-core", + "link": true + }, + "node_modules/quicktype-graphql-input": { + "resolved": "packages/quicktype-graphql-input", + "link": true + }, + "node_modules/quicktype-typescript-input": { + "resolved": "packages/quicktype-typescript-input", + "link": true + }, + "node_modules/rambda": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/rambda/-/rambda-7.5.0.tgz", + "integrity": "sha512-y/M9weqWAH4iopRd7EHDEQQvpFPHj1AA3oHozE9tfITHUtTR7Z9PSlIRRG2l1GuW7sefC1cXFfIcF+cgnShdBA==", + "dev": true + }, + "node_modules/ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/readable-stream/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/recast": { + "version": "0.23.6", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.6.tgz", + "integrity": "sha512-9FHoNjX1yjuesMwuthAmPKabxYQdOgihFYmT5ebXfYGBcnqXZf3WOVz+5foEZ8Y83P4ZY6yQD5GMmtV+pgCCAQ==", + "dev": true, + "dependencies": { + "ast-types": "^0.16.1", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tiny-invariant": "^1.3.3", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/recast/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/refa": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/refa/-/refa-0.11.0.tgz", + "integrity": "sha512-486O8/pQXwj9jV0mVvUnTsxq0uknpBnNJ0eCUhkZqJRQ8KutrT1PhzmumdCeM1hSBF2eMlFPmwECRER4IbKXlQ==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.0" + }, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true + }, + "node_modules/regexp-ast-analysis": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regexp-ast-analysis/-/regexp-ast-analysis-0.6.0.tgz", + "integrity": "sha512-OLxjyjPkVH+rQlBLb1I/P/VTmamSjGkvN5PTV5BXP432k3uVz727J7H29GA5IFiY0m7e1xBN7049Wn59FY3DEQ==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.0", + "refa": "^0.11.0" + }, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/regexp-tree": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", + "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==", + "dev": true, + "bin": { + "regexp-tree": "bin/regexp-tree" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/regjsparser": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.10.0.tgz", + "integrity": "sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", + "dev": true + }, + "node_modules/req-all": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/req-all/-/req-all-0.1.0.tgz", + "integrity": "sha512-ZdvPr8uXy9ujX3KujwE2P1HWkMYgogIhqeAeyb47MqWjSfyxERSm0TNbN/IapCCmWDufXab04AYrRgObaJCJ6Q==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requireindex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.1.0.tgz", + "integrity": "sha512-LBnkqsDE7BZKvqylbmn7lTIVdpx4K/QCduRATpO5R+wtPmky/a8pN1bO2D6wXppn1497AJF9mNjqAXr6bdl9jg==", + "dev": true, + "engines": { + "node": ">=0.10.5" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/roarr": { + "version": "7.21.1", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-7.21.1.tgz", + "integrity": "sha512-3niqt5bXFY1InKU8HKWqqYTYjtrBaxBMnXELXCXUYgtNYGUtZM5rB46HIC430AyacL95iEniGf7RgqsesykLmQ==", + "dev": true, + "dependencies": { + "fast-printf": "^1.6.9", + "safe-stable-stringify": "^2.4.3", + "semver-compare": "^1.0.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-stable-stringify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/scslre": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/scslre/-/scslre-0.2.0.tgz", + "integrity": "sha512-4hc49fUMmX3jM0XdFUAPBrs1xwEcdHa0KyjEsjFs+Zfc66mpFpq5YmRgDtl+Ffo6AtJIilfei+yKw8fUn3N88w==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.0", + "refa": "^0.11.0", + "regexp-ast-analysis": "^0.6.0" + } + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "dev": true, + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-correct/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", + "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz", + "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==", + "dev": true + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dev": true, + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/stream-chain": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz", + "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==" + }, + "node_modules/stream-json": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.8.0.tgz", + "integrity": "sha512-HZfXngYHUAr1exT4fxlbc1IOce1RYxp2ldeaf97LYCOPSoOqY/1Psp7iGvpb+6JIOgkra9zDYnPX01hGAHzEPw==", + "dependencies": { + "stream-chain": "^2.2.5" + } + }, + "node_modules/stream-read-all": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/stream-read-all/-/stream-read-all-3.0.1.tgz", + "integrity": "sha512-EWZT9XOceBPlVJRrYcykW8jyRSZYbkb/0ZK36uLEmoWVO5gxBOnntNTseNzfREsqxqdfEGQrD8SXQ3QWbBmq8A==", + "engines": { + "node": ">=10" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-env-interpolation": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string-env-interpolation/-/string-env-interpolation-1.0.1.tgz", + "integrity": "sha512-78lwMoCcn0nNu8LszbP1UA7g55OeE4v7rCeWnM5B453rnNr4aq+5it3FEYtZrSEiMvHZOZ9Jlqb0OD0M2VInqg==", + "dev": true + }, + "node_modules/string-natural-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-3.0.1.tgz", + "integrity": "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==", + "dev": true + }, + "node_modules/string-to-stream": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/string-to-stream/-/string-to-stream-3.0.1.tgz", + "integrity": "sha512-Hl092MV3USJuUCC6mfl9sPzGloA3K5VwdIeJjYIkXY/8K+mUvaeEabWJgArp+xXrsWxCajeT2pc4axbVhIZJyg==", + "dependencies": { + "readable-stream": "^3.4.0" + } + }, + "node_modules/string-to-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/synckit": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.6.2.tgz", + "integrity": "sha512-Vhf+bUa//YSTYKseDiiEuQmhGCoIF3CVBhunm3r/DQnYiGT4JssmnKQc44BIyOZRK2pKjXXAgbhfmbeoC9CJpA==", + "dev": true, + "dependencies": { + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=12.20" + } + }, + "node_modules/synckit/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, + "node_modules/table-layout": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-3.0.2.tgz", + "integrity": "sha512-rpyNZYRw+/C+dYkcQ3Pr+rLxW4CfHpXjPDnG7lYhdRoUcZTUt+KEsX+94RGp/aVp/MQU35JCITv2T/beY4m+hw==", + "dependencies": { + "@75lb/deep-merge": "^1.1.1", + "array-back": "^6.2.2", + "command-line-args": "^5.2.1", + "command-line-usage": "^7.0.0", + "stream-read-all": "^3.0.1", + "typical": "^7.1.1", + "wordwrapjs": "^5.1.0" + }, + "bin": { + "table-layout": "bin/cli.js" + }, + "engines": { + "node": ">=12.17" + } + }, + "node_modules/table-layout/node_modules/array-back": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", + "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", + "engines": { + "node": ">=12.17" + } + }, + "node_modules/table-layout/node_modules/typical": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-7.1.1.tgz", + "integrity": "sha512-T+tKVNs6Wu7IWiAce5BgMd7OZfNYUndHwc5MknN+UHOudi7sGZzuHdCadllRuqJ3fPtgFtIH9+lt9qRv6lmpfA==", + "engines": { + "node": ">=12.17" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/tiny-inflate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.2.tgz", + "integrity": "sha1-k9nez/yIBb1X6uQxDwt0Xptvs6c=" + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-unused-exports": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ts-unused-exports/-/ts-unused-exports-9.0.5.tgz", + "integrity": "sha512-1XAXaH2i4Al/aZO06pWDn9MUgTN0KQi+fvWudiWfHUTHAav45gzrx7Xq6JAsu6+LoMlVoyGvNvZSPW3KTjDncA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "tsconfig-paths": "^3.9.0" + }, + "bin": { + "ts-unused-exports": "bin/ts-unused-exports" + }, + "funding": { + "url": "https://github.com/pzavolinsky/ts-unused-exports?sponsor=1" + }, + "peerDependencies": { + "typescript": ">=3.8.3" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": false + } + } + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tslint": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", + "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", + "deprecated": "TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.3", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.13.0", + "tsutils": "^2.29.0" + }, + "bin": { + "tslint": "bin/tslint" + }, + "engines": { + "node": ">=4.8.0" + }, + "peerDependencies": { + "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev" + } + }, + "node_modules/tslint/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/tslint/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "peerDependencies": { + "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/typical": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", + "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unicode-properties": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", + "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==", + "dependencies": { + "base64-js": "^1.3.0", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/unicode-properties/node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" + }, + "node_modules/unicode-properties/node_modules/unicode-trie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", + "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", + "dependencies": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + } + }, + "node_modules/unixify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unixify/-/unixify-1.0.0.tgz", + "integrity": "sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg==", + "dev": true, + "dependencies": { + "normalize-path": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/urijs": { + "version": "1.19.11", + "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.11.tgz", + "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==" + }, + "node_modules/urlpattern-polyfill": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-8.0.2.tgz", + "integrity": "sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ==", + "dev": true + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/value-or-promise": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.12.tgz", + "integrity": "sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/vscode-json-languageservice": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-4.2.1.tgz", + "integrity": "sha512-xGmv9QIWs2H8obGbWg+sIPI/3/pFgj/5OWBhNzs00BkYQ9UaB2F6JJaGB/2/YOZJ3BvLXQTC4Q7muqU25QgAhA==", + "dev": true, + "dependencies": { + "jsonc-parser": "^3.0.0", + "vscode-languageserver-textdocument": "^1.0.3", + "vscode-languageserver-types": "^3.16.0", + "vscode-nls": "^5.0.0", + "vscode-uri": "^3.0.3" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz", + "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==", + "dev": true + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "dev": true + }, + "node_modules/vscode-nls": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-5.2.0.tgz", + "integrity": "sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==", + "dev": true + }, + "node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "dev": true + }, + "node_modules/watch": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/watch/-/watch-1.0.2.tgz", + "integrity": "sha1-NApxe952Vyb6CqB9ch4BR6VR3ww=", + "dev": true, + "dependencies": { + "exec-sh": "^0.2.0", + "minimist": "^1.2.0" + }, + "bin": { + "watch": "cli.js" + }, + "engines": { + "node": ">=0.1.95" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/webcrypto-core": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.7.8.tgz", + "integrity": "sha512-eBR98r9nQXTqXt/yDRtInszPMjTaSAMJAFDg2AHsgrnczawT1asx9YNBX6k5p+MekbPF4+s/UJJrr88zsTqkSg==", + "dev": true, + "dependencies": { + "@peculiar/asn1-schema": "^2.3.8", + "@peculiar/json-schema": "^1.1.12", + "asn1js": "^3.0.1", + "pvtsutils": "^1.3.5", + "tslib": "^2.6.2" + } + }, + "node_modules/webcrypto-core/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-fetch": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", + "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", + "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "dev": true, + "dependencies": { + "function.prototype.name": "^1.1.5", + "has-tostringtag": "^1.0.0", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dev": true, + "dependencies": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "node_modules/wordwrapjs": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-5.1.0.tgz", + "integrity": "sha512-JNjcULU2e4KJwUNv6CHgI46UvDGitb6dGryHajXTDiLgg1/RiGoPSDw4kZfYnwGtEXf2ZMeIewDQgFGzkCB2Sg==", + "engines": { + "node": ">=12.17" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xregexp": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-5.1.1.tgz", + "integrity": "sha512-fKXeVorD+CzWvFs7VBuKTYIW63YD1e1osxwQ8caZ6o1jg6pDAbABDG54LCIq0j5cy7PjRvGIq6sef9DYPXpncg==", + "dev": true, + "dependencies": { + "@babel/runtime-corejs3": "^7.16.5" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yaml": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", + "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", + "engines": { + "node": ">= 14" + } + }, + "node_modules/yaml-eslint-parser": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/yaml-eslint-parser/-/yaml-eslint-parser-1.2.2.tgz", + "integrity": "sha512-pEwzfsKbTrB8G3xc/sN7aw1v6A6c/pKxLAkjclnAyo5g5qOh6eL9WGu0o3cSDQZKrTNk4KL4lQSwZW+nBkANEg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.0.0", + "lodash": "^4.17.21", + "yaml": "^2.0.0" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + } + }, + "node_modules/yargs": { + "version": "17.6.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", + "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/quicktype-core": { + "version": "18.0.15", + "license": "Apache-2.0", + "dependencies": { + "@glideapps/ts-necessities": "2.1.3", + "@types/urijs": "^1.19.25", + "browser-or-node": "^2.1.1", + "collection-utils": "^1.0.1", + "cross-fetch": "^4.0.0", + "is-url": "^1.2.4", + "js-base64": "^3.7.5", + "lodash": "^4.17.21", + "pako": "^1.0.6", + "pluralize": "^8.0.0", + "readable-stream": "4.5.2", + "unicode-properties": "^1.4.1", + "urijs": "^1.19.1", + "wordwrap": "^1.0.0", + "yaml": "^2.3.1" + }, + "devDependencies": { + "@types/browser-or-node": "^1.3.2", + "@types/js-base64": "^3.3.1", + "@types/node": "18.14.0", + "@types/pako": "^1.0.0", + "@types/pluralize": "0.0.30", + "@types/readable-stream": "4.0.10", + "@types/unicode-properties": "^1.3.0", + "@types/yaml": "^1.9.7", + "tslint": "^6.1.3", + "typescript": "4.9.5" + } + }, + "packages/quicktype-core/node_modules/browser-or-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-2.1.1.tgz", + "integrity": "sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg==" + }, + "packages/quicktype-core/node_modules/js-base64": { + "version": "3.7.5", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.5.tgz", + "integrity": "sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA==" + }, + "packages/quicktype-core/node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "engines": { + "node": ">=4" + } + }, + "packages/quicktype-graphql-input": { + "version": "18.0.15", + "license": "Apache-2.0", + "dependencies": { + "collection-utils": "^1.0.1", + "graphql": "^0.11.7", + "quicktype-core": "file:../quicktype-core" + }, + "devDependencies": { + "@types/graphql": "^0.11.7", + "@types/node": "18.14.0", + "tslint": "^6.1.3", + "typescript": "4.9.5" + } + }, + "packages/quicktype-typescript-input": { + "version": "18.0.15", + "license": "Apache-2.0", + "dependencies": { + "@mark.probst/typescript-json-schema": "0.55.0", + "quicktype-core": "file:../quicktype-core", + "typescript": "4.9.5" + }, + "devDependencies": { + "@types/node": "18.14.0", + "tslint": "^6.1.3" + } + }, + "packages/quicktype-typescript-input/node_modules/@glideapps/ts-necessities": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@glideapps/ts-necessities/-/ts-necessities-2.1.2.tgz", + "integrity": "sha512-tLjfhinr6doUBcWi7BWnkT2zT6G5UhiZftsiIH6xVvykeXE+FU7Wr0MyqwmqideWlDD5rG+VjVLptLviGo04CA==" + }, + "packages/quicktype-typescript-input/node_modules/isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha512-9c4TNAKYXM5PRyVcwUZrF3W09nQ+sO7+jydgs4ZGW9dhsLG2VOlISJABombdQqQRXCwuYG3sYV/puGf5rp0qmA==", + "dependencies": { + "node-fetch": "^1.0.1", + "whatwg-fetch": ">=0.10.0" + } + }, + "packages/quicktype-typescript-input/node_modules/node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "dependencies": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + }, + "packages/quicktype-typescript-input/node_modules/quicktype-core": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/quicktype-core/-/quicktype-core-20.0.0.tgz", + "integrity": "sha512-zuvQAk/i4STnhLC4t3nNWPr6u5ArHBW+TME3jA7YQQMp1UdDsFD+4lzqt49b73aYhhmrk9BlO/fX7PcRR5l6YQ==", + "dependencies": { + "@glideapps/ts-necessities": "2.1.2", + "@types/urijs": "^1.19.8", + "browser-or-node": "^1.2.1", + "collection-utils": "^1.0.1", + "is-url": "^1.2.4", + "isomorphic-fetch": "^2.2.1", + "js-base64": "^2.4.3", + "lodash": "^4.17.21", + "pako": "^1.0.6", + "pluralize": "^7.0.0", + "readable-stream": "2.3.7", + "unicode-properties": "^1.4.1", + "urijs": "^1.19.1", + "wordwrap": "^1.0.0", + "yaml": "^1.5.0" + } + }, + "packages/quicktype-typescript-input/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "packages/quicktype-typescript-input/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + } + }, + "dependencies": { + "@75lb/deep-merge": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@75lb/deep-merge/-/deep-merge-1.1.1.tgz", + "integrity": "sha512-xvgv6pkMGBA6GwdyJbNAnDmfAIR/DfWhrj9jgWh3TY7gRm3KO46x/GPjRg6wJ0nOepwqrNxFfojebh0Df4h4Tw==", + "requires": { + "lodash.assignwith": "^4.2.0", + "typical": "^7.1.1" + }, + "dependencies": { + "typical": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-7.1.1.tgz", + "integrity": "sha512-T+tKVNs6Wu7IWiAce5BgMd7OZfNYUndHwc5MknN+UHOudi7sGZzuHdCadllRuqJ3fPtgFtIH9+lt9qRv6lmpfA==" + } + } + }, + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, + "@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + } + } + }, + "@ardatan/sync-fetch": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@ardatan/sync-fetch/-/sync-fetch-0.0.1.tgz", + "integrity": "sha512-xhlTqH0m31mnsG0tIP4ETgfSB6gXDaYYsUWTrlUV93fFQPI9dd8hE0Ot6MHLCtqgB32hwJAC3YZMWlXZw7AleA==", + "dev": true, + "requires": { + "node-fetch": "^2.6.1" + } + }, + "@babel/code-frame": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "dev": true, + "requires": { + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" + } + }, + "@babel/compat-data": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.1.tgz", + "integrity": "sha512-Pc65opHDliVpRHuKfzI+gSA4zcgr65O4cl64fFJIWEEh8JoHIHh0Oez1Eo8Arz8zq/JhgKodQaxEwUPRtZylVA==", + "dev": true + }, + "@babel/core": { + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.3.tgz", + "integrity": "sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.1", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.24.1", + "@babel/parser": "^7.24.1", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/eslint-parser": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.24.1.tgz", + "integrity": "sha512-d5guuzMlPeDfZIbpQ8+g1NaCNuAGBBGNECh0HVqz1sjOeVLh2CEaifuOysCH18URW6R7pqXINvf5PaR/dC6jLQ==", + "dev": true, + "requires": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.1" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/eslint-plugin": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/eslint-plugin/-/eslint-plugin-7.23.5.tgz", + "integrity": "sha512-03+E/58Hoo/ui69gR+beFdGpplpoVK0BSIdke2iw4/Bz7eGN0ssRenNlnU4nmbkowNQOPCStKSwFr8H6DiY49g==", + "dev": true, + "requires": { + "eslint-rule-composer": "^0.3.0" + } + }, + "@babel/generator": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.1.tgz", + "integrity": "sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A==", + "dev": true, + "requires": { + "@babel/types": "^7.24.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "dev": true, + "peer": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true + }, + "@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "requires": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-module-imports": { + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", + "dev": true, + "requires": { + "@babel/types": "^7.24.0" + } + }, + "@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", + "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", + "dev": true + }, + "@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-string-parser": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "dev": true + }, + "@babel/helpers": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.1.tgz", + "integrity": "sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg==", + "dev": true, + "requires": { + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0" + } + }, + "@babel/highlight": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, + "@babel/parser": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz", + "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==", + "dev": true + }, + "@babel/plugin-syntax-flow": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.1.tgz", + "integrity": "sha512-sxi2kLTI5DeW5vDtMUsk4mTPwvlUDbjOnoWayhynCwrw4QXRld4QEYwqzY8JmQXaJUtgUuCIurtSRH5sn4c7mA==", + "dev": true, + "peer": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.0" + } + }, + "@babel/plugin-syntax-import-assertions": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.1.tgz", + "integrity": "sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", + "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", + "dev": true, + "peer": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.0" + } + }, + "@babel/plugin-transform-react-jsx": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.23.4.tgz", + "integrity": "sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA==", + "dev": true, + "peer": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.23.3", + "@babel/types": "^7.23.4" + } + }, + "@babel/runtime": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.1.tgz", + "integrity": "sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.14.0" + } + }, + "@babel/runtime-corejs3": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.24.1.tgz", + "integrity": "sha512-T9ko/35G+Bkl+win48GduaPlhSlOjjE5s1TeiEcD+QpxlLQnoEfb/nO/T+TQqkm+ipFwORn+rB8w14iJ/uD0bg==", + "dev": true, + "requires": { + "core-js-pure": "^3.30.2", + "regenerator-runtime": "^0.14.0" + } + }, + "@babel/template": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" + } + }, + "@babel/traverse": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", + "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.24.1", + "@babel/generator": "^7.24.1", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.24.1", + "@babel/types": "^7.24.0", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "dependencies": { + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + } + }, + "@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "requires": { + "@jridgewell/trace-mapping": "0.3.9" + } + }, + "@es-joy/jsdoccomment": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.41.0.tgz", + "integrity": "sha512-aKUhyn1QI5Ksbqcr3fFJj16p99QdjUxXAEuFst1Z47DRyoiMwivIH9MV/ARcJOCXVjPfjITciej8ZD2O/6qUmw==", + "dev": true, + "requires": { + "comment-parser": "1.4.1", + "esquery": "^1.5.0", + "jsdoc-type-pratt-parser": "~4.0.0" + } + }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true + }, + "@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + } + } + }, + "@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true + }, + "@glideapps/ts-necessities": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@glideapps/ts-necessities/-/ts-necessities-2.1.3.tgz", + "integrity": "sha512-q9U8v/n9qbkd2zDYjuX3qtlbl+OIyI9zF+zQhZjfYOE9VMDH7tfcUSJ9p0lXoY3lxmGFne09yi4iiNeQUwV7AA==" + }, + "@graphql-eslint/eslint-plugin": { + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@graphql-eslint/eslint-plugin/-/eslint-plugin-3.20.1.tgz", + "integrity": "sha512-RbwVlz1gcYG62sECR1u0XqMh8w5e5XMCCZoMvPQ3nJzEBCTfXLGX727GBoRmSvY1x4gJmqNZ1lsOX7lZY14RIw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@graphql-tools/code-file-loader": "^7.3.6", + "@graphql-tools/graphql-tag-pluck": "^7.3.6", + "@graphql-tools/utils": "^9.0.0", + "chalk": "^4.1.2", + "debug": "^4.3.4", + "fast-glob": "^3.2.12", + "graphql-config": "^4.4.0", + "graphql-depth-limit": "^1.1.0", + "lodash.lowercase": "^4.3.0", + "tslib": "^2.4.1" + }, + "dependencies": { + "@graphql-tools/code-file-loader": { + "version": "7.3.23", + "resolved": "https://registry.npmjs.org/@graphql-tools/code-file-loader/-/code-file-loader-7.3.23.tgz", + "integrity": "sha512-8Wt1rTtyTEs0p47uzsPJ1vAtfAx0jmxPifiNdmo9EOCuUPyQGEbMaik/YkqZ7QUFIEYEQu+Vgfo8tElwOPtx5Q==", + "dev": true, + "requires": { + "@graphql-tools/graphql-tag-pluck": "7.5.2", + "@graphql-tools/utils": "^9.2.1", + "globby": "^11.0.3", + "tslib": "^2.4.0", + "unixify": "^1.0.0" + } + }, + "@graphql-tools/graphql-tag-pluck": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/graphql-tag-pluck/-/graphql-tag-pluck-7.5.2.tgz", + "integrity": "sha512-RW+H8FqOOLQw0BPXaahYepVSRjuOHw+7IL8Opaa5G5uYGOBxoXR7DceyQ7BcpMgktAOOmpDNQ2WtcboChOJSRA==", + "dev": true, + "requires": { + "@babel/parser": "^7.16.8", + "@babel/plugin-syntax-import-assertions": "^7.20.0", + "@babel/traverse": "^7.16.8", + "@babel/types": "^7.16.8", + "@graphql-tools/utils": "^9.2.1", + "tslib": "^2.4.0" + } + }, + "@graphql-tools/utils": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-9.2.1.tgz", + "integrity": "sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A==", + "dev": true, + "requires": { + "@graphql-typed-document-node/core": "^3.1.1", + "tslib": "^2.4.0" + } + }, + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + } + } + }, + "@graphql-typed-document-node/core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "dev": true, + "requires": {} + }, + "@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "dev": true + }, + "@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + } + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" + }, + "@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + }, + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@mark.probst/typescript-json-schema": { + "version": "0.55.0", + "resolved": "https://registry.npmjs.org/@mark.probst/typescript-json-schema/-/typescript-json-schema-0.55.0.tgz", + "integrity": "sha512-jI48mSnRgFQxXiE/UTUCVCpX8lK3wCFKLF1Ss2aEreboKNuLQGt3e0/YFqWVHe/WENxOaqiJvwOz+L/SrN2+qQ==", + "requires": { + "@types/json-schema": "^7.0.9", + "@types/node": "^16.9.2", + "glob": "^7.1.7", + "path-equal": "^1.1.2", + "safe-stable-stringify": "^2.2.0", + "ts-node": "^10.9.1", + "typescript": "4.9.4", + "yargs": "^17.1.1" + }, + "dependencies": { + "@types/node": { + "version": "16.18.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", + "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==" + }, + "typescript": { + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==" + } + } + }, + "@next/eslint-plugin-next": { + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.5.6.tgz", + "integrity": "sha512-ng7pU/DDsxPgT6ZPvuprxrkeew3XaRf4LAT4FabaEO/hAbvVx4P7wqnqdbTdDn1kgTvsI4tpIgT4Awn/m0bGbg==", + "dev": true, + "requires": { + "glob": "7.1.7" + }, + "dependencies": { + "glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dev": true, + "requires": { + "eslint-scope": "5.1.1" + }, + "dependencies": { + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + } + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@peculiar/asn1-schema": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.8.tgz", + "integrity": "sha512-ULB1XqHKx1WBU/tTFIA+uARuRoBVZ4pNdOA878RDrRbBfBGcSzi5HBkdScC6ZbHn8z7L8gmKCgPC1LHRrP46tA==", + "dev": true, + "requires": { + "asn1js": "^3.0.5", + "pvtsutils": "^1.3.5", + "tslib": "^2.6.2" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + } + } + }, + "@peculiar/json-schema": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", + "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", + "dev": true, + "requires": { + "tslib": "^2.0.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + } + } + }, + "@peculiar/webcrypto": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.4.5.tgz", + "integrity": "sha512-oDk93QCDGdxFRM8382Zdminzs44dg3M2+E5Np+JWkpqLDyJC9DviMh8F8mEJkYuUcUOGA5jHO5AJJ10MFWdbZw==", + "dev": true, + "requires": { + "@peculiar/asn1-schema": "^2.3.8", + "@peculiar/json-schema": "^1.1.12", + "pvtsutils": "^1.3.5", + "tslib": "^2.6.2", + "webcrypto-core": "^1.7.8" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + } + } + }, + "@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true + }, + "@repeaterjs/repeater": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.4.tgz", + "integrity": "sha512-AW8PKd6iX3vAZ0vA43nOUOnbq/X5ihgU+mSXXqunMkeQADGiqw/PY0JNeYtD5sr0PAy51YPgAPbDoeapv9r8WA==", + "dev": true + }, + "@rushstack/eslint-patch": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.8.0.tgz", + "integrity": "sha512-0HejFckBN2W+ucM6cUOlwsByTKt9/+0tWhqUffNIcHqCXkthY/mZ7AuYPK/2IIaGWhdl0h+tICDO0ssLMd6XMQ==", + "dev": true + }, + "@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" + }, + "@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + }, + "@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + }, + "@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==" + }, + "@tsconfig/node18": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node18/-/node18-1.0.1.tgz", + "integrity": "sha512-sNFeK6X2ATlhlvzyH4kKYQlfHXE2f2/wxtB9ClvYXevWpmwkUT7VaSrjIN9E76Qebz8qP5JOJJ9jD3QoD/Z9TA==", + "dev": true + }, + "@types/browser-or-node": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/browser-or-node/-/browser-or-node-1.3.2.tgz", + "integrity": "sha512-CkvJrvVMI4ZHbiL+Df22Owzq1IYnHnoSrM8s6Dmy4MRdqvdFi9bHsIvyFrSGJPOxvFI9Y3MqY2gFCqIafJBcfw==", + "dev": true + }, + "@types/command-line-args": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@types/command-line-args/-/command-line-args-5.2.0.tgz", + "integrity": "sha512-UuKzKpJJ/Ief6ufIaIzr3A/0XnluX7RvFgwkV89Yzvm77wCh1kFaFmqN8XEnGcN62EuHdedQjEMb8mYxFLGPyA==", + "dev": true + }, + "@types/command-line-usage": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@types/command-line-usage/-/command-line-usage-5.0.2.tgz", + "integrity": "sha512-n7RlEEJ+4x4TS7ZQddTmNSxP+zziEG0TNsMfiRIxcIVXt71ENJ9ojeXmGO3wPoTdn7pJcU2xc3CJYMktNT6DPg==", + "dev": true + }, + "@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/graphql": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@types/graphql/-/graphql-0.11.8.tgz", + "integrity": "sha512-xGWx4kx9JKlqxDrZA12gw5qi2lvxPNLxnQQcoTXVX83MuGcXcpb7TADatGyGW51GaaXQOQTbjw3x4HuL3ULBaA==", + "dev": true + }, + "@types/js-base64": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/js-base64/-/js-base64-3.3.1.tgz", + "integrity": "sha512-Zw33oQNAvDdAN9b0IE5stH0y2MylYvtU7VVTKEJPxhyM2q57CVaNJhtJW258ah24NRtaiA23tptUmVn3dmTKpw==", + "dev": true, + "requires": { + "js-base64": "*" + } + }, + "@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "@types/lodash": { + "version": "4.14.197", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.197.tgz", + "integrity": "sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g==", + "dev": true + }, + "@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true + }, + "@types/node": { + "version": "18.14.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.0.tgz", + "integrity": "sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A==" + }, + "@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true + }, + "@types/pako": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/pako/-/pako-1.0.0.tgz", + "integrity": "sha1-6q6DZNG391LiY7w/1o3+yY5hNsU=", + "dev": true + }, + "@types/pluralize": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/pluralize/-/pluralize-0.0.30.tgz", + "integrity": "sha512-kVww6xZrW/db5BR9OqiT71J9huRdQ+z/r+LbDuT7/EK50mCmj5FoaIARnVv0rvjUS/YpDox0cDU9lpQT011VBA==", + "dev": true + }, + "@types/readable-stream": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.10.tgz", + "integrity": "sha512-AbUKBjcC8SHmImNi4yK2bbjogQlkFSg7shZCcicxPQapniOlajG8GCc39lvXzCWX4lLRRs7DM3VAeSlqmEVZUA==", + "dev": true, + "requires": { + "@types/node": "*", + "safe-buffer": "~5.1.1" + } + }, + "@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "dev": true + }, + "@types/shelljs": { + "version": "0.8.12", + "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.8.12.tgz", + "integrity": "sha512-ZA8U81/gldY+rR5zl/7HSHrG2KDfEb3lzG6uCUDhW1DTQE9yC/VBQ45fXnXq8f3CgInfhZmjtdu/WOUlrXRQUg==", + "dev": true, + "requires": { + "@types/glob": "~7.2.0", + "@types/node": "*" + } + }, + "@types/stream-chain": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stream-chain/-/stream-chain-2.0.1.tgz", + "integrity": "sha512-D+Id9XpcBpampptkegH7WMsEk6fUdf9LlCIX7UhLydILsqDin4L0QT7ryJR0oycwC7OqohIzdfcMHVZ34ezNGg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/stream-json": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@types/stream-json/-/stream-json-1.7.3.tgz", + "integrity": "sha512-Jqsyq5VPOTWorvEmzWhEWH5tJnHA+bB8vt/Zzb11vSDj8esfSHDMj2rbVjP0mfJQzl3YBJSXBBq08iiyaBK3KA==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/stream-chain": "*" + } + }, + "@types/unicode-properties": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@types/unicode-properties/-/unicode-properties-1.3.0.tgz", + "integrity": "sha512-kDVlxpdkCfgvzfXcglkr7j4OSMjCEEo/Jloj4tFuldYZpQ9Uypy7FGXPhNstoj4eGvhddwuu5n0EfI+XdWVoVA==", + "dev": true + }, + "@types/urijs": { + "version": "1.19.25", + "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.25.tgz", + "integrity": "sha512-XOfUup9r3Y06nFAZh3WvO0rBU4OtlfPB/vgxpjg+NRdGU6CN6djdc6OEiH+PcqHCY6eFLo9Ista73uarf4gnBg==" + }, + "@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/yaml": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@types/yaml/-/yaml-1.9.7.tgz", + "integrity": "sha512-8WMXRDD1D+wCohjfslHDgICd2JtMATZU8CkhH8LVJqcJs6dyYj5TGptzP8wApbmEullGBSsCEzzap73DQ1HJaA==", + "dev": true, + "requires": { + "yaml": "*" + } + }, + "@typescript-eslint/eslint-plugin": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/experimental-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.62.0.tgz", + "integrity": "sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==", + "dev": true, + "requires": { + "@typescript-eslint/utils": "5.62.0" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + } + }, + "@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + } + }, + "@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "@whatwg-node/events": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@whatwg-node/events/-/events-0.0.3.tgz", + "integrity": "sha512-IqnKIDWfXBJkvy/k6tzskWTc2NK3LcqHlb+KHGCrjOCH4jfQckRX0NAiIcC/vIqQkzLYw2r2CTSwAxcrtcD6lA==", + "dev": true + }, + "@whatwg-node/fetch": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.8.8.tgz", + "integrity": "sha512-CdcjGC2vdKhc13KKxgsc6/616BQ7ooDIgPeTuAiE8qfCnS0mGzcfCOoZXypQSz73nxI+GWc7ZReIAVhxoE1KCg==", + "dev": true, + "requires": { + "@peculiar/webcrypto": "^1.4.0", + "@whatwg-node/node-fetch": "^0.3.6", + "busboy": "^1.6.0", + "urlpattern-polyfill": "^8.0.0", + "web-streams-polyfill": "^3.2.1" + } + }, + "@whatwg-node/node-fetch": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.3.6.tgz", + "integrity": "sha512-w9wKgDO4C95qnXZRwZTfCmLWqyRnooGjcIwG0wADWjw9/HN0p7dtvtgSvItZtUyNteEvgTrd8QojNEqV6DAGTA==", + "dev": true, + "requires": { + "@whatwg-node/events": "^0.0.3", + "busboy": "^1.6.0", + "fast-querystring": "^1.1.1", + "fast-url-parser": "^1.1.3", + "tslib": "^2.3.1" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + } + } + }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "requires": { + "event-target-shim": "^5.0.0" + } + }, + "acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==" + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "are-docs-informative": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", + "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", + "dev": true + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "requires": { + "dequal": "^2.0.3" + } + }, + "array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==" + }, + "array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "requires": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + } + }, + "array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + } + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + } + }, + "array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + } + }, + "array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } + }, + "array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } + }, + "array.prototype.toreversed": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", + "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } + }, + "array.prototype.tosorted": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz", + "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==", + "dev": true, + "requires": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.1.0", + "es-shim-unscopables": "^1.0.2" + } + }, + "arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "requires": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + } + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true + }, + "asn1js": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", + "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", + "dev": true, + "requires": { + "pvtsutils": "^1.3.2", + "pvutils": "^1.1.3", + "tslib": "^2.4.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + } + } + }, + "ast-types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "dev": true, + "requires": { + "tslib": "^2.0.1" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + } + } + }, + "ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true + }, + "available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "requires": { + "possible-typed-array-names": "^1.0.0" + } + }, + "axe-core": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz", + "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==", + "dev": true + }, + "axobject-query": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", + "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", + "dev": true, + "requires": { + "dequal": "^2.0.3" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browser-or-node": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-1.2.1.tgz", + "integrity": "sha512-sVIA0cysIED0nbmNOm7sZzKfgN1rpFmrqvLZaFWspaBAftfQcezlC81G6j6U2RJf4Lh66zFxrCeOsvkUXIcPWg==" + }, + "browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + } + }, + "buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dev": true, + "requires": { + "streamsearch": "^1.1.0" + } + }, + "call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001600", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001600.tgz", + "integrity": "sha512-+2S9/2JFhYmYaDpZvo0lKkfvuKIglrx68MwOBqMGHhQsNkLjB5xtc/TGoEPs+MxjSyN/72qer2g97nzR641mOQ==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "chalk-template": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz", + "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==", + "requires": { + "chalk": "^4.1.2" + } + }, + "chance": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/chance/-/chance-1.1.11.tgz", + "integrity": "sha512-kqTg3WWywappJPqtgrdvbA380VoXO2eu9VCV895JgbyHsaErXdyHK9LOZ911OvAk6L0obK7kDk9CGs8+oBawVA==", + "dev": true + }, + "ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true + }, + "clean-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", + "integrity": "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "collection-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/collection-utils/-/collection-utils-1.0.1.tgz", + "integrity": "sha512-LA2YTIlR7biSpXkKYwwuzGjwL5rjWEZVOSnvdUc7gObvWe4WkjxOpfrdhoP7Hs09YWDVfg0Mal9BpAqLfVEzQg==" + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + }, + "dependencies": { + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + } + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "command-line-args": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", + "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", + "requires": { + "array-back": "^3.1.0", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" + } + }, + "command-line-usage": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-7.0.1.tgz", + "integrity": "sha512-NCyznE//MuTjwi3y84QVUGEOT+P5oto1e1Pk/jFPVdPPfsG03qpTIl3yw6etR+v73d0lXsoojRpvbru2sqePxQ==", + "requires": { + "array-back": "^6.2.2", + "chalk-template": "^0.4.0", + "table-layout": "^3.0.0", + "typical": "^7.1.1" + }, + "dependencies": { + "array-back": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", + "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==" + }, + "typical": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-7.1.1.tgz", + "integrity": "sha512-T+tKVNs6Wu7IWiAce5BgMd7OZfNYUndHwc5MknN+UHOudi7sGZzuHdCadllRuqJ3fPtgFtIH9+lt9qRv6lmpfA==" + } + } + }, + "commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, + "comment-parser": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", + "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "core-js-pure": { + "version": "3.36.1", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.36.1.tgz", + "integrity": "sha512-NXCvHvSVYSrewP0L5OhltzXeWFJLo2AL2TYnj6iLV3Bw8mM62wAQMNgUCRI6EBu6hVVpbCxmOPlxh1Ikw2PfUA==", + "dev": true + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "cosmiconfig": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.0.0.tgz", + "integrity": "sha512-da1EafcpH6b/TD8vDRaWV7xFINlHlF6zKsGwS1TsuVJTZRkquaS5HTMq7uq6h31619QjbsYl21gVDOm32KM1vQ==", + "dev": true, "requires": { - "lodash.assignwith": "^4.2.0", - "typical": "^7.1.1" + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0" }, "dependencies": { - "typical": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-7.1.1.tgz", - "integrity": "sha512-T+tKVNs6Wu7IWiAce5BgMd7OZfNYUndHwc5MknN+UHOudi7sGZzuHdCadllRuqJ3fPtgFtIH9+lt9qRv6lmpfA==" + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } } } }, - "@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "create-eslint-index": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/create-eslint-index/-/create-eslint-index-1.0.0.tgz", + "integrity": "sha512-nXvJjnfDytOOaPOonX0h0a1ggMoqrhdekGeZkD6hkcWYvlCWhU719tKFVh8eU04CnMwu3uwe1JjwuUF2C3k2qg==", + "dev": true, "requires": { - "@jridgewell/trace-mapping": "0.3.9" + "lodash.get": "^4.3.0" } }, - "@glideapps/ts-necessities": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@glideapps/ts-necessities/-/ts-necessities-2.1.3.tgz", - "integrity": "sha512-q9U8v/n9qbkd2zDYjuX3qtlbl+OIyI9zF+zQhZjfYOE9VMDH7tfcUSJ9p0lXoY3lxmGFne09yi4iiNeQUwV7AA==" + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" + "cross-fetch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", + "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", + "requires": { + "node-fetch": "^2.6.12" + } }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } }, - "@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true + }, + "data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" } }, - "@mark.probst/typescript-json-schema": { - "version": "0.55.0", - "resolved": "https://registry.npmjs.org/@mark.probst/typescript-json-schema/-/typescript-json-schema-0.55.0.tgz", - "integrity": "sha512-jI48mSnRgFQxXiE/UTUCVCpX8lK3wCFKLF1Ss2aEreboKNuLQGt3e0/YFqWVHe/WENxOaqiJvwOz+L/SrN2+qQ==", + "data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, "requires": { - "@types/json-schema": "^7.0.9", - "@types/node": "^16.9.2", - "glob": "^7.1.7", - "path-equal": "^1.1.2", - "safe-stable-stringify": "^2.2.0", - "ts-node": "^10.9.1", - "typescript": "4.9.4", - "yargs": "^17.1.1" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, + "data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "requires": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, + "dataloader": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.2.2.tgz", + "integrity": "sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==", + "dev": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "deep-equal": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz", + "integrity": "sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==", + "dev": true, + "requires": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.1", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.0", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" }, "dependencies": { - "@types/node": { - "version": "16.18.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", - "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==" - }, - "typescript": { - "version": "4.9.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", - "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==" + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true } } }, - "@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" - }, - "@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true }, - "@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + "define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + } }, - "@tsconfig/node16": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==" + "define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "requires": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } }, - "@tsconfig/node18": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@tsconfig/node18/-/node18-1.0.1.tgz", - "integrity": "sha512-sNFeK6X2ATlhlvzyH4kKYQlfHXE2f2/wxtB9ClvYXevWpmwkUT7VaSrjIN9E76Qebz8qP5JOJJ9jD3QoD/Z9TA==", + "dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", "dev": true }, - "@types/browser-or-node": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/browser-or-node/-/browser-or-node-1.3.2.tgz", - "integrity": "sha512-CkvJrvVMI4ZHbiL+Df22Owzq1IYnHnoSrM8s6Dmy4MRdqvdFi9bHsIvyFrSGJPOxvFI9Y3MqY2gFCqIafJBcfw==", - "dev": true + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" }, - "@types/command-line-args": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@types/command-line-args/-/command-line-args-5.2.0.tgz", - "integrity": "sha512-UuKzKpJJ/Ief6ufIaIzr3A/0XnluX7RvFgwkV89Yzvm77wCh1kFaFmqN8XEnGcN62EuHdedQjEMb8mYxFLGPyA==", + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dset": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.3.tgz", + "integrity": "sha512-20TuZZHCEZ2O71q9/+8BwKwZ0QtD9D8ObhrihJPr+vLLYlSuAU3/zL4cSlgbfeoGHTjCSJBa7NGcrF9/Bx/WJQ==", "dev": true }, - "@types/command-line-usage": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@types/command-line-usage/-/command-line-usage-5.0.2.tgz", - "integrity": "sha512-n7RlEEJ+4x4TS7ZQddTmNSxP+zziEG0TNsMfiRIxcIVXt71ENJ9ojeXmGO3wPoTdn7pJcU2xc3CJYMktNT6DPg==", + "electron-to-chromium": { + "version": "1.4.717", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.717.tgz", + "integrity": "sha512-6Fmg8QkkumNOwuZ/5mIbMU9WI3H2fmn5ajcVya64I5Yr5CcNmO7vcLt0Y7c96DCiMO5/9G+4sI2r6eEvdg1F7A==", "dev": true }, - "@types/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "requires": { + "iconv-lite": "^0.6.2" + } + }, + "enhance-visitors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/enhance-visitors/-/enhance-visitors-1.0.0.tgz", + "integrity": "sha512-+29eJLiUixTEDRaZ35Vu8jP3gPLNcQQkQkOQjLp2X+6cZGGPDD/uasbFzvLsJKnGZnvmyZ0srxudwOtskHeIDA==", "dev": true, "requires": { - "@types/minimatch": "*", - "@types/node": "*" + "lodash": "^4.13.1" } }, - "@types/graphql": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@types/graphql/-/graphql-0.11.8.tgz", - "integrity": "sha512-xGWx4kx9JKlqxDrZA12gw5qi2lvxPNLxnQQcoTXVX83MuGcXcpb7TADatGyGW51GaaXQOQTbjw3x4HuL3ULBaA==", - "dev": true + "enhanced-resolve": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz", + "integrity": "sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } }, - "@types/js-base64": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@types/js-base64/-/js-base64-3.3.1.tgz", - "integrity": "sha512-Zw33oQNAvDdAN9b0IE5stH0y2MylYvtU7VVTKEJPxhyM2q57CVaNJhtJW258ah24NRtaiA23tptUmVn3dmTKpw==", + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "requires": { - "js-base64": "*" + "is-arrayish": "^0.2.1" } }, - "@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" + "es-abstract": { + "version": "1.23.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.2.tgz", + "integrity": "sha512-60s3Xv2T2p1ICykc7c+DNDPLDMm9t4QxCOUU0K9JxiLjM3C1zB9YVdN7tjxrFd4+AkZ8CdX1ovUga4P2+1e+/w==", + "dev": true, + "requires": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.5", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + } + }, + "es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "requires": { + "get-intrinsic": "^1.2.4" + } }, - "@types/lodash": { - "version": "4.14.197", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.197.tgz", - "integrity": "sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g==", + "es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true }, - "@types/minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", - "dev": true + "es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + } + } }, - "@types/node": { - "version": "18.14.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.0.tgz", - "integrity": "sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A==" + "es-iterator-helpers": { + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.18.tgz", + "integrity": "sha512-scxAJaewsahbqTYrGKJihhViaM6DDZDDoucfvzNbK0pOren1g/daDQ3IAhzn+1G14rBG7w+i5N+qul60++zlKA==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.1.2" + } }, - "@types/pako": { + "es-object-atoms": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/pako/-/pako-1.0.0.tgz", - "integrity": "sha1-6q6DZNG391LiY7w/1o3+yY5hNsU=", - "dev": true - }, - "@types/pluralize": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/@types/pluralize/-/pluralize-0.0.30.tgz", - "integrity": "sha512-kVww6xZrW/db5BR9OqiT71J9huRdQ+z/r+LbDuT7/EK50mCmj5FoaIARnVv0rvjUS/YpDox0cDU9lpQT011VBA==", - "dev": true - }, - "@types/readable-stream": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.10.tgz", - "integrity": "sha512-AbUKBjcC8SHmImNi4yK2bbjogQlkFSg7shZCcicxPQapniOlajG8GCc39lvXzCWX4lLRRs7DM3VAeSlqmEVZUA==", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, "requires": { - "@types/node": "*", - "safe-buffer": "~5.1.1" + "es-errors": "^1.3.0" } }, - "@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", - "dev": true - }, - "@types/shelljs": { - "version": "0.8.12", - "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.8.12.tgz", - "integrity": "sha512-ZA8U81/gldY+rR5zl/7HSHrG2KDfEb3lzG6uCUDhW1DTQE9yC/VBQ45fXnXq8f3CgInfhZmjtdu/WOUlrXRQUg==", + "es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, "requires": { - "@types/glob": "~7.2.0", - "@types/node": "*" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" } }, - "@types/stream-chain": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stream-chain/-/stream-chain-2.0.1.tgz", - "integrity": "sha512-D+Id9XpcBpampptkegH7WMsEk6fUdf9LlCIX7UhLydILsqDin4L0QT7ryJR0oycwC7OqohIzdfcMHVZ34ezNGg==", + "es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", "dev": true, "requires": { - "@types/node": "*" + "hasown": "^2.0.0" } }, - "@types/stream-json": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@types/stream-json/-/stream-json-1.7.3.tgz", - "integrity": "sha512-Jqsyq5VPOTWorvEmzWhEWH5tJnHA+bB8vt/Zzb11vSDj8esfSHDMj2rbVjP0mfJQzl3YBJSXBBq08iiyaBK3KA==", + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, "requires": { - "@types/node": "*", - "@types/stream-chain": "*" + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" } }, - "@types/unicode-properties": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@types/unicode-properties/-/unicode-properties-1.3.0.tgz", - "integrity": "sha512-kDVlxpdkCfgvzfXcglkr7j4OSMjCEEo/Jloj4tFuldYZpQ9Uypy7FGXPhNstoj4eGvhddwuu5n0EfI+XdWVoVA==", - "dev": true + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" }, - "@types/urijs": { - "version": "1.19.25", - "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.25.tgz", - "integrity": "sha512-XOfUup9r3Y06nFAZh3WvO0rBU4OtlfPB/vgxpjg+NRdGU6CN6djdc6OEiH+PcqHCY6eFLo9Ista73uarf4gnBg==" + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true }, - "@types/yaml": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@types/yaml/-/yaml-1.9.7.tgz", - "integrity": "sha512-8WMXRDD1D+wCohjfslHDgICd2JtMATZU8CkhH8LVJqcJs6dyYj5TGptzP8wApbmEullGBSsCEzzap73DQ1HJaA==", + "eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, "requires": { - "yaml": "*" + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + } } }, - "abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "eslint-ast-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-ast-utils/-/eslint-ast-utils-1.1.0.tgz", + "integrity": "sha512-otzzTim2/1+lVrlH19EfQQJEhVJSu0zOb9ygb3iapN6UlyaDtyRq4b5U1FuW0v1lRa9Fp/GJyHkSwm6NqABgCA==", + "dev": true, "requires": { - "event-target-shim": "^5.0.0" + "lodash.get": "^4.4.2", + "lodash.zip": "^4.2.0" } }, - "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" - }, - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "eslint-compat-utils": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.0.tgz", + "integrity": "sha512-dc6Y8tzEcSYZMHa+CMPLi/hyo1FzNeonbhJL7Ol0ccuKQkwopJcJBA9YL/xmMTLU1eKigXo9vj9nALElWYSowg==", "dev": true, "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" + "semver": "^7.5.4" } }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "eslint-config-canonical": { + "version": "41.4.2", + "resolved": "https://registry.npmjs.org/eslint-config-canonical/-/eslint-config-canonical-41.4.2.tgz", + "integrity": "sha512-ayP7OPe7Mh0Vf1K8PXQshekyeM3dNcEVwoJAu5ozrZXftaY36NPaH57Oj1FcmMzr2gpc3WbjQ5frVqxnqjnKMg==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "@babel/core": "^7.23.0", + "@babel/eslint-parser": "^7.22.15", + "@babel/eslint-plugin": "^7.22.10", + "@babel/plugin-syntax-import-assertions": "^7.22.5", + "@graphql-eslint/eslint-plugin": "^3.20.1", + "@next/eslint-plugin-next": "^13.5.4", + "@rushstack/eslint-patch": "^1.5.1", + "@typescript-eslint/eslint-plugin": "^6.7.5", + "@typescript-eslint/parser": "^6.7.5", + "eslint-config-prettier": "^9.0.0", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-ava": "^14.0.0", + "eslint-plugin-canonical": "^4.14.0", + "eslint-plugin-cypress": "^2.15.1", + "eslint-plugin-eslint-comments": "^3.2.0", + "eslint-plugin-flowtype": "^8.0.3", + "eslint-plugin-fp": "^2.3.0", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jest": "^27.4.2", + "eslint-plugin-jsdoc": "^46.8.2", + "eslint-plugin-jsonc": "^2.10.0", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-lodash": "^7.4.0", + "eslint-plugin-mocha": "^10.2.0", + "eslint-plugin-modules-newline": "0.0.6", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^5.0.1", + "eslint-plugin-promise": "^6.1.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-regexp": "^1.15.0", + "eslint-plugin-simple-import-sort": "^10.0.0", + "eslint-plugin-typescript-sort-keys": "^3.0.0", + "eslint-plugin-unicorn": "^48.0.1", + "eslint-plugin-vitest": "^0.3.2", + "eslint-plugin-yml": "^1.10.0", + "eslint-plugin-zod": "^1.4.0", + "prettier": "^3.0.3", + "ramda": "^0.29.1", + "yaml-eslint-parser": "^1.2.2" + }, + "dependencies": { + "eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "requires": {} + }, + "eslint-plugin-canonical": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-canonical/-/eslint-plugin-canonical-4.18.0.tgz", + "integrity": "sha512-0Egc0FKOnCRdu3bFEJhfHkdkusIgW0UxdemukkowZQnQsnf12FHSJ7K26b+tZ5pKB7cTyECSaqvEpoIJfplX4g==", + "dev": true, + "requires": { + "@typescript-eslint/utils": "^6.1.0", + "chance": "^1.1.11", + "debug": "^4.3.4", + "eslint-import-resolver-typescript": "^3.5.3", + "eslint-module-utils": "^2.7.4", + "is-get-set-prop": "^1.0.0", + "is-js-type": "^2.0.0", + "is-obj-prop": "^1.0.0", + "is-proto-prop": "^2.0.0", + "lodash": "^4.17.21", + "natural-compare": "^1.4.0", + "recast": "^0.23.2", + "roarr": "^7.14.2", + "ts-unused-exports": "^9.0.3", + "xregexp": "^5.1.1" + } + }, + "eslint-plugin-prettier": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", + "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.6" + } + }, + "synckit": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "dev": true, + "requires": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + } + }, + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + } } }, - "arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + "eslint-config-prettier": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz", + "integrity": "sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw==", + "dev": true, + "requires": { + "get-stdin": "^6.0.0" + } }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, "requires": { - "sprintf-js": "~1.0.2" + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } } }, - "array-back": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==" + "eslint-import-resolver-typescript": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", + "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", + "dev": true, + "requires": { + "debug": "^4.3.4", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "fast-glob": "^3.3.1", + "get-tsconfig": "^4.5.0", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3" + } }, - "array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "eslint-module-utils": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "debug": "^3.2.7" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } } }, - "available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true + "eslint-plugin-ava": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-ava/-/eslint-plugin-ava-14.0.0.tgz", + "integrity": "sha512-XmKT6hppaipwwnLVwwvQliSU6AF1QMHiNoLD5JQfzhUhf0jY7CO0O624fQrE+Y/fTb9vbW8r77nKf7M/oHulxw==", + "dev": true, + "requires": { + "enhance-visitors": "^1.0.0", + "eslint-utils": "^3.0.0", + "espree": "^9.0.0", + "espurify": "^2.1.1", + "import-modules": "^2.1.0", + "micro-spelling-correcter": "^1.1.1", + "pkg-dir": "^5.0.0", + "resolve-from": "^5.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + } + } }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "eslint-plugin-canonical": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-canonical/-/eslint-plugin-canonical-3.4.0.tgz", + "integrity": "sha512-akY2RpJD3VC2XXsU/02VsbzkHfybsZTsruOKPI7pJzQ+lZaS3UGM1H0vUKf0itXsbMHHJbIT78hUXU2d2HemZQ==", + "dev": true, + "requires": { + "is-get-set-prop": "^1.0.0", + "is-js-type": "^2.0.0", + "is-obj-prop": "^1.0.0", + "is-proto-prop": "^2.0.0", + "lodash": "^4.17.21", + "natural-compare": "^1.4.0", + "ts-unused-exports": "^9.0.3", + "xregexp": "^5.1.1" + } }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + "eslint-plugin-cypress": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-cypress/-/eslint-plugin-cypress-2.15.1.tgz", + "integrity": "sha512-eLHLWP5Q+I4j2AWepYq0PgFEei9/s5LvjuSqWrxurkg1YZ8ltxdvMNmdSf0drnsNo57CTgYY/NIHHLRSWejR7w==", + "dev": true, + "requires": { + "globals": "^13.20.0" + } }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "eslint-plugin-es": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", + "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", + "dev": true, "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + }, + "dependencies": { + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } } }, - "browser-or-node": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-1.2.1.tgz", - "integrity": "sha512-sVIA0cysIED0nbmNOm7sZzKfgN1rpFmrqvLZaFWspaBAftfQcezlC81G6j6U2RJf4Lh66zFxrCeOsvkUXIcPWg==" + "eslint-plugin-eslint-comments": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.2.0.tgz", + "integrity": "sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "ignore": "^5.0.5" + } }, - "buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "eslint-plugin-flowtype": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz", + "integrity": "sha512-dX8l6qUL6O+fYPtpNRideCFSpmWOUVx5QcaGLVqe/vlDiBSe4vYljDWDETwnyFzpl7By/WVIu6rcrniCgH9BqQ==", + "dev": true, "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "lodash": "^4.17.21", + "string-natural-compare": "^3.0.1" } }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true + "eslint-plugin-fp": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-fp/-/eslint-plugin-fp-2.3.0.tgz", + "integrity": "sha512-3n2oHibwoIxAht9/+ZaTldhI6brXORgl8oNXqZd+d9xuAQt2SBJ2/aml0oQRMWvXrgsz2WG6wfC++NjzSG3prA==", + "dev": true, + "requires": { + "create-eslint-index": "^1.0.0", + "eslint-ast-utils": "^1.0.0", + "lodash": "^4.13.1", + "req-all": "^0.1.0" + } }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "eslint-plugin-import": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", "dev": true, "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } } }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "eslint-plugin-jest": { + "version": "27.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz", + "integrity": "sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==", + "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@typescript-eslint/utils": "^5.10.0" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, "requires": { - "color-convert": "^2.0.1" + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" } }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, "requires": { - "color-name": "~1.1.4" + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" } }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + } }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, "requires": { - "has-flag": "^4.0.0" + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" } } } }, - "chalk-template": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz", - "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==", + "eslint-plugin-jsdoc": { + "version": "46.10.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.10.1.tgz", + "integrity": "sha512-x8wxIpv00Y50NyweDUpa+58ffgSAI5sqe+zcZh33xphD0AVh+1kqr1ombaTRb7Fhpove1zfUuujlX9DWWBP5ag==", + "dev": true, "requires": { - "chalk": "^4.1.2" + "@es-joy/jsdoccomment": "~0.41.0", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.1", + "debug": "^4.3.4", + "escape-string-regexp": "^4.0.0", + "esquery": "^1.5.0", + "is-builtin-module": "^3.2.1", + "semver": "^7.5.4", + "spdx-expression-parse": "^4.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + } } }, - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "eslint-plugin-json": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-json/-/eslint-plugin-json-3.1.0.tgz", + "integrity": "sha512-MrlG2ynFEHe7wDGwbUuFPsaT2b1uhuEFhJ+W1f1u+1C2EkXmTYJp4B1aAdQQ8M+CC3t//N/oRKiIVw14L2HR1g==", + "dev": true, "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "lodash": "^4.17.21", + "vscode-json-languageservice": "^4.1.6" } }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "collection-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collection-utils/-/collection-utils-1.0.1.tgz", - "integrity": "sha512-LA2YTIlR7biSpXkKYwwuzGjwL5rjWEZVOSnvdUc7gObvWe4WkjxOpfrdhoP7Hs09YWDVfg0Mal9BpAqLfVEzQg==" + "eslint-plugin-jsonc": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsonc/-/eslint-plugin-jsonc-2.14.1.tgz", + "integrity": "sha512-Tei6G4N7pZulP5MHi0EIdtseiCqUPkDMd0O8Zrw4muMIlsjJ5/B9X+U3Pfo6B7l0mTL9LN9FwuWT70dRJ6z7tg==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "eslint-compat-utils": "^0.5.0", + "espree": "^9.6.1", + "graphemer": "^1.4.0", + "jsonc-eslint-parser": "^2.0.4", + "natural-compare": "^1.4.0", + "synckit": "^0.6.0" + } }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "eslint-plugin-jsx-a11y": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz", + "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==", "dev": true, "requires": { - "color-name": "1.1.3" + "@babel/runtime": "^7.23.2", + "aria-query": "^5.3.0", + "array-includes": "^3.1.7", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "=4.7.0", + "axobject-query": "^3.2.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "es-iterator-helpers": "^1.0.15", + "hasown": "^2.0.0", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.entries": "^1.1.7", + "object.fromentries": "^2.0.7" }, "dependencies": { - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true } } }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "eslint-plugin-lodash": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-lodash/-/eslint-plugin-lodash-7.4.0.tgz", + "integrity": "sha512-Tl83UwVXqe1OVeBRKUeWcfg6/pCW1GTRObbdnbEJgYwjxp5Q92MEWQaH9+dmzbRt6kvYU1Mp893E79nJiCSM8A==", + "dev": true, + "requires": { + "lodash": "^4.17.21" + } }, - "command-line-args": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", - "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", + "eslint-plugin-mocha": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-10.4.1.tgz", + "integrity": "sha512-G85ALUgKaLzuEuHhoW3HVRgPTmia6njQC3qCG6CEvA8/Ja9PDZnRZOuzekMki+HaViEQXINuYsmhp5WR5/4MfA==", + "dev": true, "requires": { - "array-back": "^3.1.0", - "find-replace": "^3.0.0", - "lodash.camelcase": "^4.3.0", - "typical": "^4.0.0" + "eslint-utils": "^3.0.0", + "globals": "^13.24.0", + "rambda": "^7.4.0" } }, - "command-line-usage": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-7.0.1.tgz", - "integrity": "sha512-NCyznE//MuTjwi3y84QVUGEOT+P5oto1e1Pk/jFPVdPPfsG03qpTIl3yw6etR+v73d0lXsoojRpvbru2sqePxQ==", + "eslint-plugin-modules-newline": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/eslint-plugin-modules-newline/-/eslint-plugin-modules-newline-0.0.6.tgz", + "integrity": "sha512-69NpBr68U6pmXL+y+KHl/64PwRarceC3/sCNUVxRbe0gPI32SIw8AtdpkqNiJYCa2yMd4lRrkrnU09Yio7KVzA==", + "dev": true, "requires": { - "array-back": "^6.2.2", - "chalk-template": "^0.4.0", - "table-layout": "^3.0.0", - "typical": "^7.1.1" + "requireindex": "~1.1.0" + } + }, + "eslint-plugin-node": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", + "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", + "dev": true, + "requires": { + "eslint-plugin-es": "^3.0.0", + "eslint-utils": "^2.0.0", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" }, "dependencies": { - "array-back": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", - "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==" + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } }, - "typical": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-7.1.1.tgz", - "integrity": "sha512-T+tKVNs6Wu7IWiAce5BgMd7OZfNYUndHwc5MknN+UHOudi7sGZzuHdCadllRuqJ3fPtgFtIH9+lt9qRv6lmpfA==" + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true } } }, - "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true + "eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "eslint-plugin-promise": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", + "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", + "dev": true, + "requires": {} }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + "eslint-plugin-react": { + "version": "7.34.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz", + "integrity": "sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==", + "dev": true, + "requires": { + "array-includes": "^3.1.7", + "array.prototype.findlast": "^1.2.4", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.toreversed": "^1.1.2", + "array.prototype.tosorted": "^1.1.3", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.17", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.7", + "object.fromentries": "^2.0.7", + "object.hasown": "^1.1.3", + "object.values": "^1.1.7", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.10" + }, + "dependencies": { + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } }, - "create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + "eslint-plugin-react-hooks": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "dev": true, + "requires": {} }, - "cross-fetch": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", - "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", + "eslint-plugin-regexp": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-1.15.0.tgz", + "integrity": "sha512-YEtQPfdudafU7RBIFci81R/Q1yErm0mVh3BkGnXD2Dk8DLwTFdc2ITYH1wCnHKim2gnHfPFgrkh+b2ozyyU7ag==", + "dev": true, "requires": { - "node-fetch": "^2.6.12" + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "comment-parser": "^1.1.2", + "grapheme-splitter": "^1.0.4", + "jsdoctypeparser": "^9.0.0", + "refa": "^0.11.0", + "regexp-ast-analysis": "^0.6.0", + "scslre": "^0.2.0" } }, - "deep-equal": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz", - "integrity": "sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==", + "eslint-plugin-simple-import-sort": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-10.0.0.tgz", + "integrity": "sha512-AeTvO9UCMSNzIHRkg8S6c3RPy5YEwKWSQPx3DYghLedo2ZQxowPFLGDN1AZ2evfg6r6mjBSZSLxLFsWSu3acsw==", + "dev": true, + "requires": {} + }, + "eslint-plugin-typescript-sort-keys": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-typescript-sort-keys/-/eslint-plugin-typescript-sort-keys-3.2.0.tgz", + "integrity": "sha512-GutszvriaVtwmn7pQjuj9/9o0iXhD7XZs0/424+zsozdRr/fdg5e8206t478Vnqnqi1GjuxcAolj1kf74KnhPA==", "dev": true, "requires": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.1", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.2", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.0", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "@typescript-eslint/experimental-utils": "^5.0.0", + "json-schema": "^0.4.0", + "natural-compare-lite": "^1.4.0" + } + }, + "eslint-plugin-unicorn": { + "version": "48.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-48.0.1.tgz", + "integrity": "sha512-FW+4r20myG/DqFcCSzoumaddKBicIPeFnTrifon2mWIzlfyvzwyqZjqVP7m4Cqr/ZYisS2aiLghkUWaPg6vtCw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.22.5", + "@eslint-community/eslint-utils": "^4.4.0", + "ci-info": "^3.8.0", + "clean-regexp": "^1.0.0", + "esquery": "^1.5.0", + "indent-string": "^4.0.0", + "is-builtin-module": "^3.2.1", + "jsesc": "^3.0.2", + "lodash": "^4.17.21", + "pluralize": "^8.0.0", + "read-pkg-up": "^7.0.1", + "regexp-tree": "^0.1.27", + "regjsparser": "^0.10.0", + "semver": "^7.5.4", + "strip-indent": "^3.0.0" }, "dependencies": { - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "dev": true + }, + "pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true + } + } + }, + "eslint-plugin-vitest": { + "version": "0.3.26", + "resolved": "https://registry.npmjs.org/eslint-plugin-vitest/-/eslint-plugin-vitest-0.3.26.tgz", + "integrity": "sha512-oxe5JSPgRjco8caVLTh7Ti8PxpwJdhSV0hTQAmkFcNcmy/9DnqLB/oNVRA11RmVRP//2+jIIT6JuBEcpW3obYg==", + "dev": true, + "requires": { + "@typescript-eslint/utils": "^7.1.1" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz", + "integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/visitor-keys": "7.4.0" + } + }, + "@typescript-eslint/types": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz", + "integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==", "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz", + "integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/visitor-keys": "7.4.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/utils": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.4.0.tgz", + "integrity": "sha512-NQt9QLM4Tt8qrlBVY9lkMYzfYtNz8/6qwZg8pI3cMGlPnj6mOpRxxAm7BMJN9K0AiY+1BwJ5lVC650YJqYOuNg==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "7.4.0", + "@typescript-eslint/types": "7.4.0", + "@typescript-eslint/typescript-estree": "7.4.0", + "semver": "^7.5.4" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz", + "integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "7.4.0", + "eslint-visitor-keys": "^3.4.1" + } + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } } } }, - "define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "eslint-plugin-yml": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-yml/-/eslint-plugin-yml-1.13.2.tgz", + "integrity": "sha512-1i71VhmsG5UxE41rIJmJjhlTTxYy7upAY5Hqj8AdBc7rfJzRIZr3a2spuOS8+N7ZDCWsHAWY3J6lzQNQHDv6Uw==", "dev": true, "requires": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" + "debug": "^4.3.2", + "eslint-compat-utils": "^0.5.0", + "lodash": "^4.17.21", + "natural-compare": "^1.4.0", + "yaml-eslint-parser": "^1.2.1" } }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" + "eslint-plugin-zod": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-zod/-/eslint-plugin-zod-1.4.0.tgz", + "integrity": "sha512-i9WzQGw2X5fQcuQh33mA8DQjZJM/yuyZvs1Fc5EyTidX7Ed/g832+1FEQ4u5gtXy+jZ+DVsB5+oMHj4tIOfeZg==", + "dev": true, + "requires": {} }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "eslint-rule-composer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz", + "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==", + "dev": true }, - "encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, "requires": { - "iconv-lite": "^0.6.2" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" } }, - "es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" + "eslint-visitor-keys": "^2.0.0" }, "dependencies": { - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", "dev": true } } }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "requires": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "espurify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/espurify/-/espurify-2.1.1.tgz", + "integrity": "sha512-zttWvnkhcDyGOhSH4vO2qCBILpdCMv/MX8lp4cqgRkQoDRGK2oZxi2GfWhlP2dIXmk7BaKeOTuzbHhyC68o8XQ==", + "dev": true + }, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true }, "esutils": { @@ -3141,18 +12424,128 @@ "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", "dev": true }, + "extract-files": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-11.0.0.tgz", + "integrity": "sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ==", + "dev": true + }, + "fast-decode-uri-component": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", + "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==", + "dev": true + }, "fast-deep-equal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, + "fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", "dev": true }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "fast-printf": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/fast-printf/-/fast-printf-1.6.9.tgz", + "integrity": "sha512-FChq8hbz65WMj4rstcQsFB0O7Cy++nmbNfLYnD9cYv2cRn8EG6k/MGn9kO/tjO66t09DLDugj3yL+V2o6Qftrg==", + "dev": true, + "requires": { + "boolean": "^3.1.4" + } + }, + "fast-querystring": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fast-querystring/-/fast-querystring-1.1.2.tgz", + "integrity": "sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==", + "dev": true, + "requires": { + "fast-decode-uri-component": "^1.0.1" + } + }, + "fast-url-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", + "dev": true, + "requires": { + "punycode": "^1.3.2" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true + } + } + }, + "fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, "find-replace": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", @@ -3161,6 +12554,33 @@ "array-back": "^3.0.1" } }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "requires": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, "for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -3176,32 +12596,83 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true }, + "function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + } + }, "functions-have-names": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + } + }, + "get-set-props": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-set-props/-/get-set-props-0.1.0.tgz", + "integrity": "sha512-7oKuKzAGKj0ag+eWZwcGw2fjiZ78tXnXQoBgY0aU7ZOxTu4bB7hSuQSDgtKy978EDH062P5FmD2EWiDpQS9K9Q==", + "dev": true + }, + "get-stdin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "dev": true + }, + "get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "requires": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + } + }, + "get-tsconfig": { + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.3.tgz", + "integrity": "sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==", + "dev": true, + "requires": { + "resolve-pkg-maps": "^1.0.0" } }, "glob": { @@ -3217,6 +12688,47 @@ "path-is-absolute": "^1.0.0" } }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3" + } + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, "gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -3226,6 +12738,24 @@ "get-intrinsic": "^1.1.3" } }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "graphql": { "version": "0.11.7", "resolved": "https://registry.npmjs.org/graphql/-/graphql-0.11.7.tgz", @@ -3234,15 +12764,303 @@ "iterall": "1.1.3" } }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "graphql-config": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/graphql-config/-/graphql-config-4.5.0.tgz", + "integrity": "sha512-x6D0/cftpLUJ0Ch1e5sj1TZn6Wcxx4oMfmhaG9shM0DKajA9iR+j1z86GSTQ19fShbGvrSSvbIQsHku6aQ6BBw==", + "dev": true, + "requires": { + "@graphql-tools/graphql-file-loader": "^7.3.7", + "@graphql-tools/json-file-loader": "^7.3.7", + "@graphql-tools/load": "^7.5.5", + "@graphql-tools/merge": "^8.2.6", + "@graphql-tools/url-loader": "^7.9.7", + "@graphql-tools/utils": "^9.0.0", + "cosmiconfig": "8.0.0", + "jiti": "1.17.1", + "minimatch": "4.2.3", + "string-env-interpolation": "1.0.1", + "tslib": "^2.4.0" + }, + "dependencies": { + "@graphql-tools/graphql-file-loader": { + "version": "7.5.17", + "resolved": "https://registry.npmjs.org/@graphql-tools/graphql-file-loader/-/graphql-file-loader-7.5.17.tgz", + "integrity": "sha512-hVwwxPf41zOYgm4gdaZILCYnKB9Zap7Ys9OhY1hbwuAuC4MMNY9GpUjoTU3CQc3zUiPoYStyRtUGkHSJZ3HxBw==", + "dev": true, + "requires": { + "@graphql-tools/import": "6.7.18", + "@graphql-tools/utils": "^9.2.1", + "globby": "^11.0.3", + "tslib": "^2.4.0", + "unixify": "^1.0.0" + }, + "dependencies": { + "@graphql-tools/import": { + "version": "6.7.18", + "resolved": "https://registry.npmjs.org/@graphql-tools/import/-/import-6.7.18.tgz", + "integrity": "sha512-XQDdyZTp+FYmT7as3xRWH/x8dx0QZA2WZqfMF5EWb36a0PiH7WwlRQYIdyYXj8YCLpiWkeBXgBRHmMnwEYR8iQ==", + "dev": true, + "requires": { + "@graphql-tools/utils": "^9.2.1", + "resolve-from": "5.0.0", + "tslib": "^2.4.0" + } + } + } + }, + "@graphql-tools/json-file-loader": { + "version": "7.4.18", + "resolved": "https://registry.npmjs.org/@graphql-tools/json-file-loader/-/json-file-loader-7.4.18.tgz", + "integrity": "sha512-AJ1b6Y1wiVgkwsxT5dELXhIVUPs/u3VZ8/0/oOtpcoyO/vAeM5rOvvWegzicOOnQw8G45fgBRMkkRfeuwVt6+w==", + "dev": true, + "requires": { + "@graphql-tools/utils": "^9.2.1", + "globby": "^11.0.3", + "tslib": "^2.4.0", + "unixify": "^1.0.0" + } + }, + "@graphql-tools/load": { + "version": "7.8.14", + "resolved": "https://registry.npmjs.org/@graphql-tools/load/-/load-7.8.14.tgz", + "integrity": "sha512-ASQvP+snHMYm+FhIaLxxFgVdRaM0vrN9wW2BKInQpktwWTXVyk+yP5nQUCEGmn0RTdlPKrffBaigxepkEAJPrg==", + "dev": true, + "requires": { + "@graphql-tools/schema": "^9.0.18", + "@graphql-tools/utils": "^9.2.1", + "p-limit": "3.1.0", + "tslib": "^2.4.0" + }, + "dependencies": { + "@graphql-tools/schema": { + "version": "9.0.19", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-9.0.19.tgz", + "integrity": "sha512-oBRPoNBtCkk0zbUsyP4GaIzCt8C0aCI4ycIRUL67KK5pOHljKLBBtGT+Jr6hkzA74C8Gco8bpZPe7aWFjiaK2w==", + "dev": true, + "requires": { + "@graphql-tools/merge": "^8.4.1", + "@graphql-tools/utils": "^9.2.1", + "tslib": "^2.4.0", + "value-or-promise": "^1.0.12" + } + } + } + }, + "@graphql-tools/merge": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.4.2.tgz", + "integrity": "sha512-XbrHAaj8yDuINph+sAfuq3QCZ/tKblrTLOpirK0+CAgNlZUCHs0Fa+xtMUURgwCVThLle1AF7svJCxFizygLsw==", + "dev": true, + "requires": { + "@graphql-tools/utils": "^9.2.1", + "tslib": "^2.4.0" + } + }, + "@graphql-tools/url-loader": { + "version": "7.17.18", + "resolved": "https://registry.npmjs.org/@graphql-tools/url-loader/-/url-loader-7.17.18.tgz", + "integrity": "sha512-ear0CiyTj04jCVAxi7TvgbnGDIN2HgqzXzwsfcqiVg9cvjT40NcMlZ2P1lZDgqMkZ9oyLTV8Bw6j+SyG6A+xPw==", + "dev": true, + "requires": { + "@ardatan/sync-fetch": "^0.0.1", + "@graphql-tools/delegate": "^9.0.31", + "@graphql-tools/executor-graphql-ws": "^0.0.14", + "@graphql-tools/executor-http": "^0.1.7", + "@graphql-tools/executor-legacy-ws": "^0.0.11", + "@graphql-tools/utils": "^9.2.1", + "@graphql-tools/wrap": "^9.4.2", + "@types/ws": "^8.0.0", + "@whatwg-node/fetch": "^0.8.0", + "isomorphic-ws": "^5.0.0", + "tslib": "^2.4.0", + "value-or-promise": "^1.0.11", + "ws": "^8.12.0" + }, + "dependencies": { + "@graphql-tools/delegate": { + "version": "9.0.35", + "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-9.0.35.tgz", + "integrity": "sha512-jwPu8NJbzRRMqi4Vp/5QX1vIUeUPpWmlQpOkXQD2r1X45YsVceyUUBnktCrlJlDB4jPRVy7JQGwmYo3KFiOBMA==", + "dev": true, + "requires": { + "@graphql-tools/batch-execute": "^8.5.22", + "@graphql-tools/executor": "^0.0.20", + "@graphql-tools/schema": "^9.0.19", + "@graphql-tools/utils": "^9.2.1", + "dataloader": "^2.2.2", + "tslib": "^2.5.0", + "value-or-promise": "^1.0.12" + }, + "dependencies": { + "@graphql-tools/batch-execute": { + "version": "8.5.22", + "resolved": "https://registry.npmjs.org/@graphql-tools/batch-execute/-/batch-execute-8.5.22.tgz", + "integrity": "sha512-hcV1JaY6NJQFQEwCKrYhpfLK8frSXDbtNMoTur98u10Cmecy1zrqNKSqhEyGetpgHxaJRqszGzKeI3RuroDN6A==", + "dev": true, + "requires": { + "@graphql-tools/utils": "^9.2.1", + "dataloader": "^2.2.2", + "tslib": "^2.4.0", + "value-or-promise": "^1.0.12" + } + }, + "@graphql-tools/executor": { + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/@graphql-tools/executor/-/executor-0.0.20.tgz", + "integrity": "sha512-GdvNc4vszmfeGvUqlcaH1FjBoguvMYzxAfT6tDd4/LgwymepHhinqLNA5otqwVLW+JETcDaK7xGENzFomuE6TA==", + "dev": true, + "requires": { + "@graphql-tools/utils": "^9.2.1", + "@graphql-typed-document-node/core": "3.2.0", + "@repeaterjs/repeater": "^3.0.4", + "tslib": "^2.4.0", + "value-or-promise": "^1.0.12" + } + }, + "@graphql-tools/schema": { + "version": "9.0.19", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-9.0.19.tgz", + "integrity": "sha512-oBRPoNBtCkk0zbUsyP4GaIzCt8C0aCI4ycIRUL67KK5pOHljKLBBtGT+Jr6hkzA74C8Gco8bpZPe7aWFjiaK2w==", + "dev": true, + "requires": { + "@graphql-tools/merge": "^8.4.1", + "@graphql-tools/utils": "^9.2.1", + "tslib": "^2.4.0", + "value-or-promise": "^1.0.12" + } + } + } + }, + "@graphql-tools/executor-graphql-ws": { + "version": "0.0.14", + "resolved": "https://registry.npmjs.org/@graphql-tools/executor-graphql-ws/-/executor-graphql-ws-0.0.14.tgz", + "integrity": "sha512-P2nlkAsPZKLIXImFhj0YTtny5NQVGSsKnhi7PzXiaHSXc6KkzqbWZHKvikD4PObanqg+7IO58rKFpGXP7eeO+w==", + "dev": true, + "requires": { + "@graphql-tools/utils": "^9.2.1", + "@repeaterjs/repeater": "3.0.4", + "@types/ws": "^8.0.0", + "graphql-ws": "5.12.1", + "isomorphic-ws": "5.0.0", + "tslib": "^2.4.0", + "ws": "8.13.0" + } + }, + "@graphql-tools/executor-http": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/@graphql-tools/executor-http/-/executor-http-0.1.10.tgz", + "integrity": "sha512-hnAfbKv0/lb9s31LhWzawQ5hghBfHS+gYWtqxME6Rl0Aufq9GltiiLBcl7OVVOnkLF0KhwgbYP1mB5VKmgTGpg==", + "dev": true, + "requires": { + "@graphql-tools/utils": "^9.2.1", + "@repeaterjs/repeater": "^3.0.4", + "@whatwg-node/fetch": "^0.8.1", + "dset": "^3.1.2", + "extract-files": "^11.0.0", + "meros": "^1.2.1", + "tslib": "^2.4.0", + "value-or-promise": "^1.0.12" + } + }, + "@graphql-tools/executor-legacy-ws": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/@graphql-tools/executor-legacy-ws/-/executor-legacy-ws-0.0.11.tgz", + "integrity": "sha512-4ai+NnxlNfvIQ4c70hWFvOZlSUN8lt7yc+ZsrwtNFbFPH/EroIzFMapAxM9zwyv9bH38AdO3TQxZ5zNxgBdvUw==", + "dev": true, + "requires": { + "@graphql-tools/utils": "^9.2.1", + "@types/ws": "^8.0.0", + "isomorphic-ws": "5.0.0", + "tslib": "^2.4.0", + "ws": "8.13.0" + } + }, + "@graphql-tools/wrap": { + "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/wrap/-/wrap-9.4.2.tgz", + "integrity": "sha512-DFcd9r51lmcEKn0JW43CWkkI2D6T9XI1juW/Yo86i04v43O9w2/k4/nx2XTJv4Yv+iXwUw7Ok81PGltwGJSDSA==", + "dev": true, + "requires": { + "@graphql-tools/delegate": "^9.0.31", + "@graphql-tools/schema": "^9.0.18", + "@graphql-tools/utils": "^9.2.1", + "tslib": "^2.4.0", + "value-or-promise": "^1.0.12" + }, + "dependencies": { + "@graphql-tools/schema": { + "version": "9.0.19", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-9.0.19.tgz", + "integrity": "sha512-oBRPoNBtCkk0zbUsyP4GaIzCt8C0aCI4ycIRUL67KK5pOHljKLBBtGT+Jr6hkzA74C8Gco8bpZPe7aWFjiaK2w==", + "dev": true, + "requires": { + "@graphql-tools/merge": "^8.4.1", + "@graphql-tools/utils": "^9.2.1", + "tslib": "^2.4.0", + "value-or-promise": "^1.0.12" + } + } + } + } + } + }, + "@graphql-tools/utils": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-9.2.1.tgz", + "integrity": "sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A==", + "dev": true, + "requires": { + "@graphql-typed-document-node/core": "^3.1.1", + "tslib": "^2.4.0" + } + }, + "minimatch": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.3.tgz", + "integrity": "sha512-lIUdtK5hdofgCTu3aT0sOaHsYR37viUuIc0rwnnDXImbwFRcumyLMeZaM0t0I/fgxS6s6JMfu0rLD1Wz9pv1ng==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, + "ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "dev": true, + "requires": {} + } + } + }, + "graphql-depth-limit": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/graphql-depth-limit/-/graphql-depth-limit-1.1.0.tgz", + "integrity": "sha512-+3B2BaG8qQ8E18kzk9yiSdAa75i/hnnOwgSeAxVJctGQPvmeiLtqKOYF6HETCyRjiF7Xfsyal0HbLlxCQkgkrw==", "dev": true, "requires": { - "function-bind": "^1.1.1" + "arrify": "^1.0.1" } }, + "graphql-ws": { + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.12.1.tgz", + "integrity": "sha512-umt4f5NnMK46ChM2coO36PTFhHouBrK9stWWBczERguwYrGnPNxJ9dimU6IyOBfOkC6Izhkg4H8+F51W/8CYDg==", + "dev": true, + "requires": {} + }, "has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -3256,18 +13074,18 @@ "dev": true }, "has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "requires": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" } }, "has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "dev": true }, "has-symbols": { @@ -3277,14 +13095,29 @@ "dev": true }, "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.3" + } + }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, "requires": { - "has-symbols": "^1.0.2" + "function-bind": "^1.1.2" } }, + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, "iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", @@ -3298,6 +13131,40 @@ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, + "ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "import-modules": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-modules/-/import-modules-2.1.0.tgz", + "integrity": "sha512-8HEWcnkbGpovH9yInoisxaSoIg9Brbul+Ju3Kqe2UsYDUBJD/iQjSgEj0zPcTDPKfPp2fs5xlv1i+JSye/m1/A==", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -3313,13 +13180,13 @@ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "internal-slot": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.4.tgz", - "integrity": "sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, "requires": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "hasown": "^2.0.0", "side-channel": "^1.0.4" } }, @@ -3340,14 +13207,28 @@ } }, "is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, "requires": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "get-intrinsic": "^1.2.1" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" } }, "is-bigint": { @@ -3369,12 +13250,47 @@ "has-tostringtag": "^1.0.0" } }, + "is-builtin-module": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", + "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "dev": true, + "requires": { + "builtin-modules": "^3.3.0" + }, + "dependencies": { + "builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true + } + } + }, "is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true }, + "is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "requires": { + "hasown": "^2.0.0" + } + }, + "is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "requires": { + "is-typed-array": "^1.1.13" + } + }, "is-date-object": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", @@ -3384,17 +13300,81 @@ "has-tostringtag": "^1.0.0" } }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, + "is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-get-set-prop": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-get-set-prop/-/is-get-set-prop-1.0.0.tgz", + "integrity": "sha512-DvAYZ1ZgGUz4lzxKMPYlt08qAUqyG9ckSg2pIjfvcQ7+pkVNUHk8yVLXOnCLe5WKXhLop8oorWFBJHpwWQpszQ==", + "dev": true, + "requires": { + "get-set-props": "^0.1.0", + "lowercase-keys": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-js-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-js-type/-/is-js-type-2.0.0.tgz", + "integrity": "sha512-Aj13l47+uyTjlQNHtXBV8Cji3jb037vxwMWCgopRR8h6xocgBGW3qG8qGlIOEmbXQtkKShKuBM9e8AA1OeQ+xw==", + "dev": true, + "requires": { + "js-types": "^1.0.0" + } + }, "is-map": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", "dev": true }, + "is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, "is-number-object": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", @@ -3404,6 +13384,32 @@ "has-tostringtag": "^1.0.0" } }, + "is-obj-prop": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-obj-prop/-/is-obj-prop-1.0.0.tgz", + "integrity": "sha512-5Idb61slRlJlsAzi0Wsfwbp+zZY+9LXKUAZpvT/1ySw+NxKLRWfa0Bzj+wXI3fX5O9hiddm5c3DAaRSNP/yl2w==", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0", + "obj-props": "^1.0.0" + } + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, + "is-proto-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-proto-prop/-/is-proto-prop-2.0.0.tgz", + "integrity": "sha512-jl3NbQ/fGLv5Jhan4uX+Ge9ohnemqyblWVVCpAvtTQzNFvV2xhJq+esnkIbYQ9F1nITXoLfDDQLp7LBw/zzncg==", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0", + "proto-props": "^2.0.0" + } + }, "is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -3421,12 +13427,12 @@ "dev": true }, "is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, "requires": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" } }, "is-stream": { @@ -3453,16 +13459,12 @@ } }, "is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "which-typed-array": "^1.1.14" } }, "is-url": { @@ -3476,6 +13478,15 @@ "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", "dev": true }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, "is-weakset": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", @@ -3491,16 +13502,60 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "isomorphic-ws": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", + "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "dev": true, + "requires": {} + }, "iterall": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.1.3.tgz", "integrity": "sha512-Cu/kb+4HiNSejAPhSaN1VukdNTTi/r4/e+yykqjlG/IW+1gZH5b4+Bq3whDX4tvbYugta3r8KTMUiqT3fIGxuQ==" }, + "iterator.prototype": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", + "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "dev": true, + "requires": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + } + }, + "jiti": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.17.1.tgz", + "integrity": "sha512-NZIITw8uZQFuzQimqjUxIrIcEdxYDFIe/0xYfIlVXTkiBjjyBEvgasj5bb0/cHtPRD/NziPbT312sFrkI5ALpw==", + "dev": true + }, "js-base64": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.3.tgz", "integrity": "sha512-H7ErYLM34CvDMto3GbD6xD0JLUGYXR3QTcH6B/tr4Hi/QpSThnCsIp+Sy5FRTw3B0d6py4HcNkW7nO/wdtGWEw==" }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-types": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/js-types/-/js-types-1.0.0.tgz", + "integrity": "sha512-bfwqBW9cC/Lp7xcRpug7YrXm0IVw+T9e3g4mCYnv0Pjr3zIzU9PCQElYU9oSGAWzXlbdl9X5SAMPejO9sxkeUw==", + "dev": true + }, "js-yaml": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", @@ -3509,22 +13564,141 @@ "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" - }, - "dependencies": { - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - } } }, + "jsdoc-type-pratt-parser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", + "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", + "dev": true + }, + "jsdoctypeparser": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/jsdoctypeparser/-/jsdoctypeparser-9.0.0.tgz", + "integrity": "sha512-jrTA2jJIL6/DAEILBEh2/w9QxCuwmvNXIry39Ay/HVfhE3o2yVV0U44blYkqdHA/OKloJEqvJy0xU+GSdE2SIw==", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, "json-schema-traverse": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", "dev": true }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true + }, + "jsonc-eslint-parser": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonc-eslint-parser/-/jsonc-eslint-parser-2.4.0.tgz", + "integrity": "sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==", + "dev": true, + "requires": { + "acorn": "^8.5.0", + "eslint-visitor-keys": "^3.0.0", + "espree": "^9.0.0", + "semver": "^7.3.5" + } + }, + "jsonc-parser": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", + "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", + "dev": true + }, + "jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "requires": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + } + }, + "keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, + "language-subtag-registry": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", + "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==", + "dev": true + }, + "language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "requires": { + "language-subtag-registry": "^0.3.20" + } + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -3540,6 +13714,45 @@ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "dev": true + }, + "lodash.lowercase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.lowercase/-/lodash.lowercase-4.3.0.tgz", + "integrity": "sha512-UcvP1IZYyDKyEL64mmrwoA1AbFu5ahojhTtkOUr1K9dbuxzS9ev8i4TxMMGCqRC9TE8uDaSoufNAXxRPNTseVA==", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.zip": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz", + "integrity": "sha512-C7IOaBBK/0gMORRBd8OETNx3kmOkgIWIPvyDpZSCTwUrpYmgZwJkjZeOD8ww4xbOUOs4/attY+pciKvadNfFbg==", + "dev": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -3560,6 +13773,41 @@ "integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==", "dev": true }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "meros": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/meros/-/meros-1.3.0.tgz", + "integrity": "sha512-2BNGOimxEz5hmjUG2FwoxCt5HN7BXdaWyFqEwxPTrJzVdABtrL4TiHTcsWSFAxPQ/tOnEaQEJh3qWq71QRMY+w==", + "dev": true, + "requires": {} + }, + "micro-spelling-correcter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/micro-spelling-correcter/-/micro-spelling-correcter-1.1.1.tgz", + "integrity": "sha512-lkJ3Rj/mtjlRcHk6YyCbvZhyWTOzdBvTHsxMmZSk5jxN1YyVSQ+JETAom55mdzfcyDrY/49Z7UCW760BK30crg==", + "dev": true + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true + }, "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3588,6 +13836,24 @@ "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "node-fetch": { "version": "2.6.12", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", @@ -3596,10 +13862,57 @@ "whatwg-url": "^5.0.0" } }, + "node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true + } + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "obj-props": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/obj-props/-/obj-props-1.4.0.tgz", + "integrity": "sha512-p7p/7ltzPDiBs6DqxOrIbtRdwxxVRBj5ROukeNb9RgA+fawhrz5n2hpNz8DDmYR//tviJSj7nUnlppGmONkjiQ==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true + }, "object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "dev": true }, "object-is": { @@ -3619,17 +13932,73 @@ "dev": true }, "object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" } }, + "object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + } + }, + "object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + } + }, + "object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + } + }, + "object.hasown": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.4.tgz", + "integrity": "sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==", + "dev": true, + "requires": { + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + } + }, + "object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3638,38 +14007,157 @@ "wrappy": "1" } }, + "optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, "pako": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==" }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, "path-equal": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/path-equal/-/path-equal-1.2.5.tgz", "integrity": "sha512-i73IctDr3F2W+bsOWDyyVm/lqsXO47aY9nsFZUjTT/aljSbkxHxxCoyZ9UUrM8jK0JVod+An+rl48RCsvWM+9g==" }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pkg-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "dev": true, + "requires": { + "find-up": "^5.0.0" + } + }, "pluralize": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==" }, + "possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, "prettier": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.1.tgz", - "integrity": "sha512-fcOWSnnpCrovBsmFZIGIy9UqK2FaI7Hqax+DIO0A9UxeVoY4iweyaFjS5TavZN97Hfehph0nhsZnjlVKzEQSrQ==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", "dev": true }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -3686,6 +14174,58 @@ "integrity": "sha512-5yANTE0tmi5++POym6OgtFmwfDvOXABD9oj/jLQr5GPEyuNEb7jH4wbbANJceJid49jwhi1RddxnhnEAb/doqg==", "dev": true }, + "prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "proto-props": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/proto-props/-/proto-props-2.0.0.tgz", + "integrity": "sha512-2yma2tog9VaRZY2mn3Wq51uiSW4NcPYT1cQdBagwyrznrilKSZwIZ0UG3ZPL/mx+axEns0hE35T5ufOYZXEnBQ==", + "dev": true + }, + "punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true + }, + "pvtsutils": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.5.tgz", + "integrity": "sha512-ARvb14YB9Nm2Xi6nBq1ZX6dAM0FsJnuk+31aUp4TrcZEdKUlSqOqsxJHUPJDNE3qiIp+iUPEIeR6Je/tgV7zsA==", + "dev": true, + "requires": { + "tslib": "^2.6.1" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + } + } + }, + "pvutils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, "quicktype-core": { "version": "file:packages/quicktype-core", "requires": { @@ -3820,6 +14360,100 @@ } } }, + "rambda": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/rambda/-/rambda-7.5.0.tgz", + "integrity": "sha512-y/M9weqWAH4iopRd7EHDEQQvpFPHj1AA3oHozE9tfITHUtTR7Z9PSlIRRG2l1GuW7sefC1cXFfIcF+cgnShdBA==", + "dev": true + }, + "ramda": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.1.tgz", + "integrity": "sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==", + "dev": true + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + } + } + }, "readable-stream": { "version": "4.5.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", @@ -3847,6 +14481,27 @@ } } }, + "recast": { + "version": "0.23.6", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.6.tgz", + "integrity": "sha512-9FHoNjX1yjuesMwuthAmPKabxYQdOgihFYmT5ebXfYGBcnqXZf3WOVz+5foEZ8Y83P4ZY6yQD5GMmtV+pgCCAQ==", + "dev": true, + "requires": { + "ast-types": "^0.16.1", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tiny-invariant": "^1.3.3", + "tslib": "^2.0.1" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + } + } + }, "rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", @@ -3856,29 +14511,186 @@ "resolve": "^1.1.6" } }, + "refa": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/refa/-/refa-0.11.0.tgz", + "integrity": "sha512-486O8/pQXwj9jV0mVvUnTsxq0uknpBnNJ0eCUhkZqJRQ8KutrT1PhzmumdCeM1hSBF2eMlFPmwECRER4IbKXlQ==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.5.0" + } + }, + "reflect.getprototypeof": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + } + }, + "regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true + }, + "regexp-ast-analysis": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regexp-ast-analysis/-/regexp-ast-analysis-0.6.0.tgz", + "integrity": "sha512-OLxjyjPkVH+rQlBLb1I/P/VTmamSjGkvN5PTV5BXP432k3uVz727J7H29GA5IFiY0m7e1xBN7049Wn59FY3DEQ==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.5.0", + "refa": "^0.11.0" + } + }, + "regexp-tree": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", + "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==", + "dev": true + }, "regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + } + }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, + "regjsparser": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.10.0.tgz", + "integrity": "sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true + } } }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", + "dev": true + }, + "req-all": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/req-all/-/req-all-0.1.0.tgz", + "integrity": "sha512-ZdvPr8uXy9ujX3KujwE2P1HWkMYgogIhqeAeyb47MqWjSfyxERSm0TNbN/IapCCmWDufXab04AYrRgObaJCJ6Q==", + "dev": true + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" }, + "requireindex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.1.0.tgz", + "integrity": "sha512-LBnkqsDE7BZKvqylbmn7lTIVdpx4K/QCduRATpO5R+wtPmky/a8pN1bO2D6wXppn1497AJF9mNjqAXr6bdl9jg==", + "dev": true + }, "resolve": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", - "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "roarr": { + "version": "7.21.1", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-7.21.1.tgz", + "integrity": "sha512-3niqt5bXFY1InKU8HKWqqYTYjtrBaxBMnXELXCXUYgtNYGUtZM5rB46HIC430AyacL95iEniGf7RgqsesykLmQ==", + "dev": true, + "requires": { + "fast-printf": "^1.6.9", + "safe-stable-stringify": "^2.4.3", + "semver-compare": "^1.0.0" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "requires": { - "path-parse": "^1.0.5" + "queue-microtask": "^1.2.2" + } + }, + "safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + } } }, "safe-buffer": { @@ -3886,25 +14698,94 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "requires": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + } + }, "safe-stable-stringify": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.2.tgz", - "integrity": "sha512-gMxvPJYhP0O9n2pvcfYfIuYgbledAOJFcqRThtPRmjscaipiwcwPPKLytpVzMkG2HAN87Qmo2d4PtGiri1dSLA==" + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==" }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "scslre": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/scslre/-/scslre-0.2.0.tgz", + "integrity": "sha512-4hc49fUMmX3jM0XdFUAPBrs1xwEcdHa0KyjEsjFs+Zfc66mpFpq5YmRgDtl+Ffo6AtJIilfei+yKw8fUn3N88w==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.5.0", + "refa": "^0.11.0", + "regexp-ast-analysis": "^0.6.0" + } + }, "semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "lru-cache": "^6.0.0" + } + }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true + }, + "set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "requires": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + } + }, + "set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "requires": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" } }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, "shelljs": { "version": "0.8.5", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", @@ -3917,16 +14798,73 @@ } }, "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + }, + "dependencies": { + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + } + } + }, + "spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true + }, + "spdx-expression-parse": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", + "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", "dev": true, "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, + "spdx-license-ids": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz", + "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==", + "dev": true + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -3960,6 +14898,12 @@ "resolved": "https://registry.npmjs.org/stream-read-all/-/stream-read-all-3.0.1.tgz", "integrity": "sha512-EWZT9XOceBPlVJRrYcykW8jyRSZYbkb/0ZK36uLEmoWVO5gxBOnntNTseNzfREsqxqdfEGQrD8SXQ3QWbBmq8A==" }, + "streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "dev": true + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -3968,6 +14912,18 @@ "safe-buffer": "~5.1.0" } }, + "string-env-interpolation": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string-env-interpolation/-/string-env-interpolation-1.0.1.tgz", + "integrity": "sha512-78lwMoCcn0nNu8LszbP1UA7g55OeE4v7rCeWnM5B453rnNr4aq+5it3FEYtZrSEiMvHZOZ9Jlqb0OD0M2VInqg==", + "dev": true + }, + "string-natural-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-3.0.1.tgz", + "integrity": "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==", + "dev": true + }, "string-to-stream": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/string-to-stream/-/string-to-stream-3.0.1.tgz", @@ -3998,6 +14954,60 @@ "strip-ansi": "^6.0.1" } }, + "string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + } + }, + "string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + } + }, + "string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + } + }, + "string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + } + }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -4006,6 +15016,27 @@ "ansi-regex": "^5.0.1" } }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true + }, + "strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "requires": { + "min-indent": "^1.0.0" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -4015,6 +15046,29 @@ "has-flag": "^3.0.0" } }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "synckit": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.6.2.tgz", + "integrity": "sha512-Vhf+bUa//YSTYKseDiiEuQmhGCoIF3CVBhunm3r/DQnYiGT4JssmnKQc44BIyOZRK2pKjXXAgbhfmbeoC9CJpA==", + "dev": true, + "requires": { + "tslib": "^2.3.1" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + } + } + }, "table-layout": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-3.0.2.tgz", @@ -4041,16 +15095,56 @@ } } }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, "tiny-inflate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.2.tgz", "integrity": "sha1-k9nez/yIBb1X6uQxDwt0Xptvs6c=" }, + "tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, "tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, + "ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "requires": {} + }, "ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -4069,12 +15163,38 @@ "make-error": "^1.1.1", "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" + } + }, + "ts-unused-exports": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ts-unused-exports/-/ts-unused-exports-9.0.5.tgz", + "integrity": "sha512-1XAXaH2i4Al/aZO06pWDn9MUgTN0KQi+fvWudiWfHUTHAav45gzrx7Xq6JAsu6+LoMlVoyGvNvZSPW3KTjDncA==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "tsconfig-paths": "^3.9.0" + } + }, + "tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" }, "dependencies": { - "acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==" + "json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } } } }, @@ -4105,26 +15225,6 @@ "tsutils": "^2.29.0" }, "dependencies": { - "@babel/code-frame": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", - "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", - "dev": true, - "requires": { - "@babel/highlight": "^7.0.0" - } - }, - "@babel/highlight": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", - "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - } - }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -4136,12 +15236,6 @@ "supports-color": "^5.3.0" } }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -4159,6 +15253,73 @@ "tslib": "^1.8.1" } }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, + "typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + } + }, + "typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + } + }, + "typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + } + }, + "typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + } + }, "typescript": { "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", @@ -4169,6 +15330,18 @@ "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==" }, + "unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + } + }, "unicode-properties": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", @@ -4194,11 +15367,45 @@ } } }, + "unixify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unixify/-/unixify-1.0.0.tgz", + "integrity": "sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg==", + "dev": true, + "requires": { + "normalize-path": "^2.1.1" + } + }, + "update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, "urijs": { "version": "1.19.11", "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.11.tgz", "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==" }, + "urlpattern-polyfill": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-8.0.2.tgz", + "integrity": "sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ==", + "dev": true + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -4209,6 +15416,71 @@ "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + }, + "dependencies": { + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + } + } + }, + "value-or-promise": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.12.tgz", + "integrity": "sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q==", + "dev": true + }, + "vscode-json-languageservice": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-4.2.1.tgz", + "integrity": "sha512-xGmv9QIWs2H8obGbWg+sIPI/3/pFgj/5OWBhNzs00BkYQ9UaB2F6JJaGB/2/YOZJ3BvLXQTC4Q7muqU25QgAhA==", + "dev": true, + "requires": { + "jsonc-parser": "^3.0.0", + "vscode-languageserver-textdocument": "^1.0.3", + "vscode-languageserver-types": "^3.16.0", + "vscode-nls": "^5.0.0", + "vscode-uri": "^3.0.3" + } + }, + "vscode-languageserver-textdocument": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz", + "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==", + "dev": true + }, + "vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "dev": true + }, + "vscode-nls": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-5.2.0.tgz", + "integrity": "sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==", + "dev": true + }, + "vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "dev": true + }, "watch": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/watch/-/watch-1.0.2.tgz", @@ -4219,6 +15491,33 @@ "minimist": "^1.2.0" } }, + "web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "dev": true + }, + "webcrypto-core": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.7.8.tgz", + "integrity": "sha512-eBR98r9nQXTqXt/yDRtInszPMjTaSAMJAFDg2AHsgrnczawT1asx9YNBX6k5p+MekbPF4+s/UJJrr88zsTqkSg==", + "dev": true, + "requires": { + "@peculiar/asn1-schema": "^2.3.8", + "@peculiar/json-schema": "^1.1.12", + "asn1js": "^3.0.1", + "pvtsutils": "^1.3.5", + "tslib": "^2.6.2" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + } + } + }, "webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -4238,6 +15537,15 @@ "webidl-conversions": "^3.0.0" } }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, "which-boxed-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", @@ -4251,6 +15559,34 @@ "is-symbol": "^1.0.3" } }, + "which-builtin-type": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", + "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "dev": true, + "requires": { + "function.prototype.name": "^1.1.5", + "has-tostringtag": "^1.0.0", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + } + } + }, "which-collection": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", @@ -4264,17 +15600,16 @@ } }, "which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dev": true, "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "has-tostringtag": "^1.0.2" } }, "wordwrap": { @@ -4320,6 +15655,23 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, + "ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "dev": true, + "peer": true, + "requires": {} + }, + "xregexp": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-5.1.1.tgz", + "integrity": "sha512-fKXeVorD+CzWvFs7VBuKTYIW63YD1e1osxwQ8caZ6o1jg6pDAbABDG54LCIq0j5cy7PjRvGIq6sef9DYPXpncg==", + "dev": true, + "requires": { + "@babel/runtime-corejs3": "^7.16.5" + } + }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -4336,6 +15688,17 @@ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==" }, + "yaml-eslint-parser": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/yaml-eslint-parser/-/yaml-eslint-parser-1.2.2.tgz", + "integrity": "sha512-pEwzfsKbTrB8G3xc/sN7aw1v6A6c/pKxLAkjclnAyo5g5qOh6eL9WGu0o3cSDQZKrTNk4KL4lQSwZW+nBkANEg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.0.0", + "lodash": "^4.17.21", + "yaml": "^2.0.0" + } + }, "yargs": { "version": "17.6.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", @@ -4359,6 +15722,12 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true } } } diff --git a/package.json b/package.json index 32092e0c7..7bea464c7 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "test": "script/test", "start": "script/watch", "clean": "rm -rf dist node_modules *~ packages/*/{dist,node_modules}", - "debug": "node --inspect-brk --max-old-space-size=4096 ./dist/index.js" + "debug": "node --inspect-brk --max-old-space-size=4096 ./dist/index.js", + "lint": "eslint src/** packages/*/src/**" }, "workspaces": [ "./packages/quicktype-core", @@ -49,8 +50,18 @@ "@types/shelljs": "^0.8.12", "@types/stream-json": "^1.7.3", "@types/urijs": "^1.19.25", + "@typescript-eslint/eslint-plugin": "^6.3.0", + "@typescript-eslint/parser": "^6.3.0", "ajv": "^5.5.2", "deep-equal": "^2.2.2", + "eslint": "^8.57.0", + "eslint-config-canonical": "^41.1.7", + "eslint-config-prettier": "^6.10.0", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-canonical": "^3.4.0", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-json": "^3.1.0", + "eslint-plugin-prettier": "^4.2.1", "exit": "^0.1.2", "prettier": "^3.0.1", "promise-timeout": "^1.3.0", From b97c2b2bd81b67cdfe26817f486c99303ccd6823 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sun, 7 Apr 2024 08:51:03 -0700 Subject: [PATCH 18/94] add eslint config --- .eslintrc.json | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 .eslintrc.json diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 000000000..922bb451a --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,44 @@ +{ + "overrides": [ + { + "extends": ["canonical/json"], + "files": "*.json" + }, + { + "extends": ["eslint:recommended", "canonical/typescript", "canonical/typescript-type-checking"], + "parserOptions": { + "tsconfigRootDir": "./", + "project": ["./tsconfig.json", "./packages/*/tsconfig.json"] + }, + "plugins": ["canonical"], + "rules": { + "canonical/prefer-inline-type-import": "error", + "@typescript-eslint/consistent-type-definitions": ["error", "interface"], + "@typescript-eslint/consistent-type-imports": ["error", { "prefer": "type-imports" }], + "@typescript-eslint/explicit-function-return-type": "warn", + "@typescript-eslint/indent": ["error", 4], + "@typescript-eslint/quotes": ["error", "double"], + "@typescript-eslint/no-misused-promises": ["error", { "checksVoidReturn": false }], + "@typescript-eslint/naming-convention": "error", + "@typescript-eslint/no-empty-interface": "warn", + "@typescript-eslint/no-unused-vars": ["error", { "vars": "local", "args": "none" }], + "@typescript-eslint/no-use-before-define": "warn", + "@typescript-eslint/no-useless-empty-export": "error", + "@typescript-eslint/prefer-readonly": "warn", + "@typescript-eslint/prefer-reduce-type-parameter": "off", + "@typescript-eslint/switch-exhaustiveness-check": "error", + "@typescript-eslint/unified-signatures": "error" + }, + "overrides": [ + { + "files": "*.d.ts", + "rules": { + "no-var": "off" + } + } + ], + "files": "*.ts" + } + ], + "root": true +} From e504a8a01db8e9e3b1a8a92d629d3542ef85e261 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sun, 7 Apr 2024 08:53:46 -0700 Subject: [PATCH 19/94] remove tslint --- .vscode/tasks.json | 13 - package-lock.json | 225 +----------------- package.json | 1 - packages/quicktype-core/package.json | 4 +- packages/quicktype-core/src/TypeUtils.ts | 2 - packages/quicktype-core/src/input/Inputs.ts | 1 - packages/quicktype-graphql-input/package.json | 6 +- .../src/GraphQLSchema.ts | 2 +- packages/quicktype-graphql-input/src/index.ts | 2 - .../quicktype-typescript-input/package.json | 6 +- src/index.ts | 2 - tslint.json | 67 ------ 12 files changed, 7 insertions(+), 324 deletions(-) delete mode 100644 .vscode/tasks.json delete mode 100644 tslint.json diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index f36e83f3d..000000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - // See https://go.microsoft.com/fwlink/?LinkId=733558 - // for the documentation about the tasks.json format - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "script": "tslint", - "group": "build", - "problemMatcher": ["$tslint5"] - } - ] -} diff --git a/package-lock.json b/package-lock.json index a0ff1b196..6bcb1cc29 100644 --- a/package-lock.json +++ b/package-lock.json @@ -62,7 +62,6 @@ "semver": "^7.5.4", "shelljs": "^0.8.5", "ts-node": "^10.9.2", - "tslint": "^6.1.3", "watch": "^1.0.2" }, "engines": { @@ -1861,15 +1860,6 @@ "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, "node_modules/aria-query": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", @@ -2252,15 +2242,6 @@ "ieee754": "^1.2.1" } }, - "node_modules/builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -2519,12 +2500,6 @@ "node": ">=12.17" } }, - "node_modules/commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, "node_modules/comment-parser": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", @@ -6160,19 +6135,6 @@ "node": ">=0.10.0" } }, - "node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/jsdoc-type-pratt-parser": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", @@ -6505,18 +6467,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, "node_modules/moment": { "version": "2.29.4", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", @@ -7763,12 +7713,6 @@ "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==", "dev": true }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, "node_modules/stop-iteration-iterator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", @@ -8222,72 +8166,6 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, - "node_modules/tslint": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", - "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", - "deprecated": "TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.3", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.13.0", - "tsutils": "^2.29.0" - }, - "bin": { - "tslint": "bin/tslint" - }, - "engines": { - "node": ">=4.8.0" - }, - "peerDependencies": { - "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev" - } - }, - "node_modules/tslint/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/tslint/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "peerDependencies": { - "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" - } - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -8944,7 +8822,6 @@ "@types/readable-stream": "4.0.10", "@types/unicode-properties": "^1.3.0", "@types/yaml": "^1.9.7", - "tslint": "^6.1.3", "typescript": "4.9.5" } }, @@ -8977,7 +8854,6 @@ "devDependencies": { "@types/graphql": "^0.11.7", "@types/node": "18.14.0", - "tslint": "^6.1.3", "typescript": "4.9.5" } }, @@ -8990,8 +8866,7 @@ "typescript": "4.9.5" }, "devDependencies": { - "@types/node": "18.14.0", - "tslint": "^6.1.3" + "@types/node": "18.14.0" } }, "packages/quicktype-typescript-input/node_modules/@glideapps/ts-necessities": { @@ -10444,15 +10319,6 @@ "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, "aria-query": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", @@ -10722,12 +10588,6 @@ "ieee754": "^1.2.1" } }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, "busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -10908,12 +10768,6 @@ } } }, - "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, "comment-parser": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", @@ -13556,16 +13410,6 @@ "integrity": "sha512-bfwqBW9cC/Lp7xcRpug7YrXm0IVw+T9e3g4mCYnv0Pjr3zIzU9PCQElYU9oSGAWzXlbdl9X5SAMPejO9sxkeUw==", "dev": true }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, "jsdoc-type-pratt-parser": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", @@ -13822,15 +13666,6 @@ "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", "dev": true }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - }, "moment": { "version": "2.29.4", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", @@ -14248,7 +14083,6 @@ "pako": "^1.0.6", "pluralize": "^8.0.0", "readable-stream": "4.5.2", - "tslint": "^6.1.3", "typescript": "4.9.5", "unicode-properties": "^1.4.1", "urijs": "^1.19.1", @@ -14281,7 +14115,6 @@ "collection-utils": "^1.0.1", "graphql": "^0.11.7", "quicktype-core": "file:../quicktype-core", - "tslint": "^6.1.3", "typescript": "4.9.5" } }, @@ -14291,7 +14124,6 @@ "@mark.probst/typescript-json-schema": "0.55.0", "@types/node": "18.14.0", "quicktype-core": "file:../quicktype-core", - "tslint": "^6.1.3", "typescript": "4.9.5" }, "dependencies": { @@ -14865,12 +14697,6 @@ "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==", "dev": true }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, "stop-iteration-iterator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", @@ -15204,55 +15030,6 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, - "tslint": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", - "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.3", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.13.0", - "tsutils": "^2.29.0" - }, - "dependencies": { - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", diff --git a/package.json b/package.json index 7bea464c7..f221ca9ed 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,6 @@ "semver": "^7.5.4", "shelljs": "^0.8.5", "ts-node": "^10.9.2", - "tslint": "^6.1.3", "watch": "^1.0.2" }, "files": [ diff --git a/packages/quicktype-core/package.json b/packages/quicktype-core/package.json index 0550516ff..0cbd4a35b 100644 --- a/packages/quicktype-core/package.json +++ b/packages/quicktype-core/package.json @@ -8,8 +8,7 @@ "repository": "https://github.com/quicktype/quicktype", "scripts": { "clean": "rm -rf dist node_modules *~", - "build": "tsc", - "tslint": "tslint --project ." + "build": "tsc" }, "dependencies": { "@glideapps/ts-necessities": "2.1.3", @@ -37,7 +36,6 @@ "@types/readable-stream": "4.0.10", "@types/unicode-properties": "^1.3.0", "@types/yaml": "^1.9.7", - "tslint": "^6.1.3", "typescript": "4.9.5" }, "files": [ diff --git a/packages/quicktype-core/src/TypeUtils.ts b/packages/quicktype-core/src/TypeUtils.ts index 4f3c57f29..36fb166a9 100644 --- a/packages/quicktype-core/src/TypeUtils.ts +++ b/packages/quicktype-core/src/TypeUtils.ts @@ -290,7 +290,6 @@ export function matchType( return panic(`Unsupported type ${t.kind} in non-exhaustive match`); } - /* tslint:disable:strict-boolean-expressions */ return matchTypeExhaustive( type, typeNotSupported, @@ -308,7 +307,6 @@ export function matchType( unionType, transformedStringType || typeNotSupported ); - /* tslint:enable */ } export function matchCompoundType( diff --git a/packages/quicktype-core/src/input/Inputs.ts b/packages/quicktype-core/src/input/Inputs.ts index 3baefd9c5..9ff8905fa 100644 --- a/packages/quicktype-core/src/input/Inputs.ts +++ b/packages/quicktype-core/src/input/Inputs.ts @@ -60,7 +60,6 @@ export class JSONInput implements Input> { private readonly _topLevels: Map = new Map(); - /* tslint:disable:no-unused-variable */ constructor(private readonly _compressedJSON: CompressedJSON) {} private addSample(topLevelName: string, sample: Value): void { diff --git a/packages/quicktype-graphql-input/package.json b/packages/quicktype-graphql-input/package.json index ae4b23648..75e96e5bc 100644 --- a/packages/quicktype-graphql-input/package.json +++ b/packages/quicktype-graphql-input/package.json @@ -8,8 +8,7 @@ "repository": "https://github.com/quicktype/quicktype", "scripts": { "clean": "rm -rf dist node_modules *~", - "build": "tsc", - "tslint": "tslint --project ." + "build": "tsc" }, "dependencies": { "quicktype-core": "file:../quicktype-core", @@ -19,8 +18,7 @@ "devDependencies": { "@types/node": "18.14.0", "@types/graphql": "^0.11.7", - "typescript": "4.9.5", - "tslint": "^6.1.3" + "typescript": "4.9.5" }, "files": [ "dist" diff --git a/packages/quicktype-graphql-input/src/GraphQLSchema.ts b/packages/quicktype-graphql-input/src/GraphQLSchema.ts index 5f8d570b9..e53072baf 100644 --- a/packages/quicktype-graphql-input/src/GraphQLSchema.ts +++ b/packages/quicktype-graphql-input/src/GraphQLSchema.ts @@ -1,4 +1,4 @@ -/* tslint:disable */ +/* eslint-disable */ // This file was automatically generated and should not be edited. // A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies. diff --git a/packages/quicktype-graphql-input/src/index.ts b/packages/quicktype-graphql-input/src/index.ts index bd3cc0feb..515c5c258 100644 --- a/packages/quicktype-graphql-input/src/index.ts +++ b/packages/quicktype-graphql-input/src/index.ts @@ -1,5 +1,3 @@ -/* tslint:disable:strict-boolean-expressions */ - import { DocumentNode, SelectionSetNode, diff --git a/packages/quicktype-typescript-input/package.json b/packages/quicktype-typescript-input/package.json index 9926b394e..813c0575e 100644 --- a/packages/quicktype-typescript-input/package.json +++ b/packages/quicktype-typescript-input/package.json @@ -8,8 +8,7 @@ "repository": "https://github.com/quicktype/quicktype", "scripts": { "clean": "rm -rf dist node_modules *~", - "build": "tsc", - "tslint": "tslint --project ." + "build": "tsc" }, "dependencies": { "quicktype-core": "file:../quicktype-core", @@ -17,8 +16,7 @@ "@mark.probst/typescript-json-schema": "0.55.0" }, "devDependencies": { - "@types/node": "18.14.0", - "tslint": "^6.1.3" + "@types/node": "18.14.0" }, "files": [ "dist" diff --git a/src/index.ts b/src/index.ts index 943abdfb9..109161c79 100644 --- a/src/index.ts +++ b/src/index.ts @@ -271,7 +271,6 @@ function inferCLIOptions(opts: Partial, targetLanguage: TargetLangua language = maybeLanguage; } - /* tslint:disable:strict-boolean-expressions */ const options: CLIOptions = { src: opts.src || [], srcUrls: opts.srcUrls, @@ -295,7 +294,6 @@ function inferCLIOptions(opts: Partial, targetLanguage: TargetLangua debug: opts.debug, telemetry: opts.telemetry }; - /* tslint:enable */ for (const flagName of inferenceFlagNames) { const cliName = negatedInferenceFlagName(flagName); options[cliName] = !!opts[cliName]; diff --git a/tslint.json b/tslint.json deleted file mode 100644 index ac74002e7..000000000 --- a/tslint.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "rules": { - "await-promise": true, - "promise-function-async": true, - "no-floating-promises": true, - "align": [true, "parameters", "statements"], - "ban": false, - "class-name": true, - "comment-format": [true, "check-space"], - "curly": false, - "eofline": false, - "forin": true, - "indent": [true, "spaces", 4], - "interface-name": [true, "never-prefix"], - "jsdoc-format": true, - "jsx-no-lambda": false, - "jsx-no-multiline-js": false, - "label-position": true, - "max-line-length": false, - "member-ordering": [true, "static-before-instance"], - - "no-any": false, - - "no-arg": true, - "no-bitwise": false, - "no-console": [false, "log", "error", "debug", "info", "time", "timeEnd", "trace"], - "no-consecutive-blank-lines": true, - "no-construct": true, - "no-debugger": true, - "no-duplicate-variable": true, - "no-empty": [true, "allow-empty-catch"], - "no-eval": true, - "no-shadowed-variable": true, - "no-string-literal": false, - "no-switch-case-fall-through": true, - "no-trailing-whitespace": false, - "no-unsafe-any": false, - "no-unused-expression": true, - "no-use-before-declare": false, - "no-unused-variable": true, - "no-var-keyword": true, - "no-void-expression": false, - "strict-boolean-expressions": true, - "one-line": [true, "check-catch", "check-else", "check-open-brace", "check-whitespace"], - "quotemark": [true, "double", "avoid-escape"], - "radix": true, - "semicolon": [true, "always", "ignore-bound-class-methods"], - "switch-default": true, - - "trailing-comma": false, - - "triple-equals": [true, "allow-null-check"], - "typedef": [true, "parameter", "property-declaration"], - "typedef-whitespace": [ - true, - { - "call-signature": "nospace", - "index-signature": "nospace", - "parameter": "nospace", - "property-declaration": "nospace", - "variable-declaration": "nospace" - } - ], - "variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore", "allow-pascal-case"], - "whitespace": [false] - } -} From 92bd5635a79b141b50ca051290793184ae9696be Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sun, 7 Apr 2024 08:59:27 -0700 Subject: [PATCH 20/94] eslint autofix --- packages/quicktype-core/src/Annotation.ts | 6 +- .../quicktype-core/src/ConvenienceRenderer.ts | 326 ++++--- packages/quicktype-core/src/CycleBreaker.ts | 14 +- packages/quicktype-core/src/DateTime.ts | 16 +- packages/quicktype-core/src/DeclarationIR.ts | 34 +- packages/quicktype-core/src/GatherNames.ts | 42 +- packages/quicktype-core/src/Graph.ts | 39 +- packages/quicktype-core/src/GraphRewriting.ts | 196 ++-- .../quicktype-core/src/MakeTransformations.ts | 130 +-- packages/quicktype-core/src/MarkovChain.ts | 54 +- packages/quicktype-core/src/Messages.ts | 139 +-- packages/quicktype-core/src/Naming.ts | 100 +- packages/quicktype-core/src/Renderer.ts | 137 +-- .../quicktype-core/src/RendererOptions.ts | 61 +- packages/quicktype-core/src/Run.ts | 270 +++--- packages/quicktype-core/src/Source.ts | 86 +- packages/quicktype-core/src/TargetLanguage.ts | 55 +- packages/quicktype-core/src/Transformers.ts | 361 ++++---- packages/quicktype-core/src/Type.ts | 283 +++--- packages/quicktype-core/src/TypeBuilder.ts | 198 ++-- packages/quicktype-core/src/TypeGraph.ts | 171 ++-- packages/quicktype-core/src/TypeUtils.ts | 125 +-- packages/quicktype-core/src/UnifyClasses.ts | 69 +- packages/quicktype-core/src/UnionBuilder.ts | 123 +-- .../src/attributes/AccessorNames.ts | 59 +- .../src/attributes/Constraints.ts | 70 +- .../src/attributes/Description.ts | 45 +- .../src/attributes/EnumValues.ts | 20 +- .../src/attributes/StringTypes.ts | 72 +- .../src/attributes/TypeAttributes.ts | 61 +- .../src/attributes/TypeNames.ts | 103 ++- .../src/attributes/URIAttributes.ts | 30 +- packages/quicktype-core/src/index.ts | 56 +- .../src/input/CompressedJSON.ts | 96 +- .../src/input/FetchingJSONSchemaStore.ts | 7 +- .../quicktype-core/src/input/Inference.ts | 86 +- packages/quicktype-core/src/input/Inputs.ts | 94 +- .../src/input/JSONSchemaInput.ts | 349 ++++--- .../src/input/JSONSchemaStore.ts | 15 +- .../src/input/PostmanCollection.ts | 17 +- .../quicktype-core/src/input/io/NodeIO.ts | 12 +- .../src/input/io/get-stream/buffer-stream.ts | 6 +- .../src/input/io/get-stream/index.ts | 14 +- packages/quicktype-core/src/language/All.ts | 9 +- packages/quicktype-core/src/language/CJSON.ts | 851 +++++++++--------- .../quicktype-core/src/language/CPlusPlus.ts | 830 +++++++++-------- .../quicktype-core/src/language/CSharp.ts | 576 +++++++----- .../quicktype-core/src/language/Crystal.ts | 93 +- packages/quicktype-core/src/language/Dart.ts | 261 +++--- packages/quicktype-core/src/language/Elm.ts | 186 ++-- .../quicktype-core/src/language/Golang.ts | 142 +-- .../quicktype-core/src/language/Haskell.ts | 141 +-- .../quicktype-core/src/language/JSONSchema.ts | 79 +- packages/quicktype-core/src/language/Java.ts | 435 +++++---- .../quicktype-core/src/language/JavaScript.ts | 179 ++-- .../src/language/JavaScriptPropTypes.ts | 90 +- .../src/language/JavaScriptUnicodeMaps.ts | 24 +- .../quicktype-core/src/language/Kotlin.ts | 300 +++--- .../src/language/Objective-C.ts | 274 +++--- packages/quicktype-core/src/language/Php.ts | 329 ++++--- packages/quicktype-core/src/language/Pike.ts | 95 +- .../quicktype-core/src/language/Python.ts | 417 +++++---- packages/quicktype-core/src/language/Rust.ts | 154 ++-- .../quicktype-core/src/language/Scala3.ts | 204 +++-- .../quicktype-core/src/language/Smithy4s.ts | 164 ++-- packages/quicktype-core/src/language/Swift.ts | 283 +++--- .../src/language/TypeScriptEffectSchema.ts | 80 +- .../src/language/TypeScriptFlow.ts | 137 +-- .../src/language/TypeScriptZod.ts | 131 +-- .../quicktype-core/src/language/ruby/index.ts | 167 ++-- .../src/language/ruby/keywords.ts | 8 +- .../src/rewrites/CombineClasses.ts | 45 +- .../src/rewrites/ExpandStrings.ts | 41 +- .../src/rewrites/FlattenStrings.ts | 26 +- .../src/rewrites/FlattenUnions.ts | 17 +- .../quicktype-core/src/rewrites/InferMaps.ts | 34 +- .../src/rewrites/ReplaceObjectType.ts | 24 +- .../src/rewrites/ResolveIntersections.ts | 108 ++- .../quicktype-core/src/support/Acronyms.ts | 16 +- packages/quicktype-core/src/support/Chance.ts | 84 +- .../quicktype-core/src/support/Comments.ts | 22 +- .../quicktype-core/src/support/Converters.ts | 10 +- .../quicktype-core/src/support/Strings.ts | 170 ++-- .../quicktype-core/src/support/Support.ts | 59 +- packages/quicktype-graphql-input/src/index.ts | 199 ++-- .../quicktype-typescript-input/src/index.ts | 19 +- src/CompressedJSONFromStream.ts | 21 +- src/GraphQLIntrospection.ts | 14 +- src/TypeSource.ts | 6 +- src/URLGrammar.ts | 12 +- src/index.ts | 286 +++--- 91 files changed, 6685 insertions(+), 5414 deletions(-) diff --git a/packages/quicktype-core/src/Annotation.ts b/packages/quicktype-core/src/Annotation.ts index 8a912f305..e6483462c 100644 --- a/packages/quicktype-core/src/Annotation.ts +++ b/packages/quicktype-core/src/Annotation.ts @@ -1,14 +1,14 @@ export class AnnotationData {} export class IssueAnnotationData extends AnnotationData { - constructor(readonly message: string) { + constructor (readonly message: string) { super(); } } export const anyTypeIssueAnnotation = new IssueAnnotationData( - "quicktype cannot infer this type because there is no data about it in the input." + "quicktype cannot infer this type because there is no data about it in the input.", ); export const nullTypeIssueAnnotation = new IssueAnnotationData( - "The only value for this in the input is null, which means you probably need a more complete input sample." + "The only value for this in the input is null, which means you probably need a more complete input sample.", ); diff --git a/packages/quicktype-core/src/ConvenienceRenderer.ts b/packages/quicktype-core/src/ConvenienceRenderer.ts index ec80df6f5..175db7e3e 100644 --- a/packages/quicktype-core/src/ConvenienceRenderer.ts +++ b/packages/quicktype-core/src/ConvenienceRenderer.ts @@ -6,24 +6,30 @@ import { mapFilter, mapSortBy, mapFilterMap, - mapSome + mapSome, } from "collection-utils"; -import { Type, ClassType, EnumType, UnionType, TypeKind, ClassProperty, MapType, ObjectType } from "./Type"; +import { type Type, type TypeKind, type ClassProperty} from "./Type"; +import { ClassType, EnumType, UnionType, MapType, ObjectType } from "./Type"; import { separateNamedTypes, nullableFromUnion, matchTypeExhaustive, isNamedType } from "./TypeUtils"; -import { Namespace, Name, Namer, FixedName, SimpleName, DependencyName, keywordNamespace } from "./Naming"; -import { Renderer, BlankLineConfig, RenderContext, ForEachPosition } from "./Renderer"; +import { type Name, type Namer} from "./Naming"; +import { Namespace, FixedName, SimpleName, DependencyName, keywordNamespace } from "./Naming"; +import { type BlankLineConfig, type RenderContext, type ForEachPosition } from "./Renderer"; +import { Renderer } from "./Renderer"; import { defined, panic, nonNull, assert } from "./support/Support"; import { trimEnd } from "./support/Strings"; -import { Sourcelike, sourcelikeToSource, serializeRenderResult } from "./Source"; +import { type Sourcelike} from "./Source"; +import { sourcelikeToSource, serializeRenderResult } from "./Source"; -import { declarationsForGraph, DeclarationIR, cycleBreakerTypesForGraph, Declaration } from "./DeclarationIR"; +import { type DeclarationIR, type Declaration } from "./DeclarationIR"; +import { declarationsForGraph, cycleBreakerTypesForGraph } from "./DeclarationIR"; import { TypeAttributeStoreView } from "./TypeGraph"; import { TypeAttributeKind } from "./attributes/TypeAttributes"; import { descriptionTypeAttributeKind, propertyDescriptionsTypeAttributeKind } from "./attributes/Description"; import { enumCaseNames, objectPropertyNames, unionMemberName, getAccessorName } from "./attributes/AccessorNames"; -import { transformationForType, followTargetType, Transformation } from "./Transformers"; -import { TargetLanguage } from "./TargetLanguage"; +import { type Transformation } from "./Transformers"; +import { transformationForType, followTargetType } from "./Transformers"; +import { type TargetLanguage } from "./TargetLanguage"; import { type Comment, isStringComment, type CommentOptions } from "./support/Comments"; const wordWrap: (s: string) => string = require("wordwrap")(90); @@ -41,7 +47,7 @@ const assignedEnumCaseNameOrder = 10; const unionMemberNameOrder = 40; -function splitDescription(descriptions: Iterable | undefined): string[] | undefined { +function splitDescription (descriptions: Iterable | undefined): string[] | undefined { if (descriptions === undefined) return undefined; const description = Array.from(descriptions).join("\n\n").trim(); if (description === "") return undefined; @@ -50,7 +56,9 @@ function splitDescription(descriptions: Iterable | undefined): string[] .map(l => l.trim()); } -export type ForbiddenWordsInfo = { names: (Name | string)[]; includeGlobalForbidden: boolean }; +export interface ForbiddenWordsInfo { + includeGlobalForbidden: boolean; names: Array; +} const assignedNameAttributeKind = new TypeAttributeKind("assignedName"); const assignedPropertyNamesAttributeKind = new TypeAttributeKind>("assignedPropertyNames"); @@ -59,37 +67,54 @@ const assignedCaseNamesAttributeKind = new TypeAttributeKind | undefined; + private _globalNamespace: Namespace | undefined; + private _nameStoreView: TypeAttributeStoreView | undefined; + private _propertyNamesStoreView: TypeAttributeStoreView> | undefined; + private _memberNamesStoreView: TypeAttributeStoreView> | undefined; + private _caseNamesStoreView: TypeAttributeStoreView> | undefined; + private _namesForTransformations: Map | undefined; private _namedTypeNamer: Namer | undefined; - // @ts-ignore: FIXME: Make this `Namer | undefined` + + // @ts-expect-error: FIXME: Make this `Namer | undefined` private _unionMemberNamer: Namer | null; - // @ts-ignore: FIXME: Make this `Namer | undefined` + + // @ts-expect-error: FIXME: Make this `Namer | undefined` private _enumCaseNamer: Namer | null; private _declarationIR: DeclarationIR | undefined; - private _namedTypes: ReadonlyArray | undefined; + + private _namedTypes: readonly Type[] | undefined; + private _namedObjects: Set | undefined; + private _namedEnums: Set | undefined; + private _namedUnions: Set | undefined; + private _haveUnions: boolean | undefined; + private _haveMaps: boolean | undefined; + private _haveOptionalProperties: boolean | undefined; + private _cycleBreakerTypes?: Set | undefined; private _alphabetizeProperties = false; - constructor(targetLanguage: TargetLanguage, renderContext: RenderContext) { + constructor (targetLanguage: TargetLanguage, renderContext: RenderContext) { super(targetLanguage, renderContext); } - get topLevels(): ReadonlyMap { + get topLevels (): ReadonlyMap { return this.typeGraph.topLevels; } @@ -100,7 +125,7 @@ export abstract class ConvenienceRenderer extends Renderer { * that can conflict with that, such as reserved keywords or common type * names. */ - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace (): string[] { return []; } @@ -114,95 +139,96 @@ export abstract class ConvenienceRenderer extends Renderer { * Note: That doesn't mean that the names in the global namespace will be * forbidden, too! */ - protected forbiddenForObjectProperties(_o: ObjectType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties (_o: ObjectType, _className: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: false }; } - protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { + protected forbiddenForUnionMembers (_u: UnionType, _unionName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: false }; } - protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { + protected forbiddenForEnumCases (_e: EnumType, _enumName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: false }; } - protected makeTopLevelDependencyNames(_t: Type, _topLevelName: Name): DependencyName[] { + protected makeTopLevelDependencyNames (_t: Type, _topLevelName: Name): DependencyName[] { return []; } - protected makeNamedTypeDependencyNames(_t: Type, _name: Name): DependencyName[] { + protected makeNamedTypeDependencyNames (_t: Type, _name: Name): DependencyName[] { return []; } - protected abstract makeNamedTypeNamer(): Namer; - protected abstract namerForObjectProperty(o: ObjectType, p: ClassProperty): Namer | null; - protected abstract makeUnionMemberNamer(): Namer | null; - protected abstract makeEnumCaseNamer(): Namer | null; - protected abstract emitSourceStructure(givenOutputFilename: string): void; + protected abstract makeNamedTypeNamer (): Namer; + protected abstract namerForObjectProperty (o: ObjectType, p: ClassProperty): Namer | null; + protected abstract makeUnionMemberNamer (): Namer | null; + protected abstract makeEnumCaseNamer (): Namer | null; + protected abstract emitSourceStructure (givenOutputFilename: string): void; - protected makeNameForTransformation(_xf: Transformation, _typeName: Name | undefined): Name | undefined { + protected makeNameForTransformation (_xf: Transformation, _typeName: Name | undefined): Name | undefined { return undefined; } - protected namedTypeToNameForTopLevel(type: Type): Type | undefined { + protected namedTypeToNameForTopLevel (type: Type): Type | undefined { if (isNamedType(type)) { return type; } + return undefined; } - protected get unionMembersInGlobalNamespace(): boolean { + protected get unionMembersInGlobalNamespace (): boolean { return false; } - protected get enumCasesInGlobalNamespace(): boolean { + protected get enumCasesInGlobalNamespace (): boolean { return false; } - protected get needsTypeDeclarationBeforeUse(): boolean { + protected get needsTypeDeclarationBeforeUse (): boolean { return false; } - protected canBeForwardDeclared(_t: Type): boolean { + protected canBeForwardDeclared (_t: Type): boolean { return panic("If needsTypeDeclarationBeforeUse returns true, canBeForwardDeclared must be implemented"); } - protected unionNeedsName(u: UnionType): boolean { + protected unionNeedsName (u: UnionType): boolean { return nullableFromUnion(u) === null; } - private get globalNamespace(): Namespace { + private get globalNamespace (): Namespace { return defined(this._globalNamespace); } - private get nameStoreView(): TypeAttributeStoreView { + private get nameStoreView (): TypeAttributeStoreView { return defined(this._nameStoreView); } - protected descriptionForType(t: Type): string[] | undefined { + protected descriptionForType (t: Type): string[] | undefined { let description = this.typeGraph.attributeStore.tryGet(descriptionTypeAttributeKind, t); return splitDescription(description); } - protected descriptionForClassProperty(o: ObjectType, name: string): string[] | undefined { + protected descriptionForClassProperty (o: ObjectType, name: string): string[] | undefined { const descriptions = this.typeGraph.attributeStore.tryGet(propertyDescriptionsTypeAttributeKind, o); if (descriptions === undefined) return undefined; return splitDescription(descriptions.get(name)); } - protected setUpNaming(): ReadonlySet { + protected setUpNaming (): ReadonlySet { this._nameStoreView = new TypeAttributeStoreView(this.typeGraph.attributeStore, assignedNameAttributeKind); this._propertyNamesStoreView = new TypeAttributeStoreView( this.typeGraph.attributeStore, - assignedPropertyNamesAttributeKind + assignedPropertyNamesAttributeKind, ); this._memberNamesStoreView = new TypeAttributeStoreView( this.typeGraph.attributeStore, - assignedMemberNamesAttributeKind + assignedMemberNamesAttributeKind, ); this._caseNamesStoreView = new TypeAttributeStoreView( this.typeGraph.attributeStore, - assignedCaseNamesAttributeKind + assignedCaseNamesAttributeKind, ); this._namesForTransformations = new Map(); @@ -218,40 +244,44 @@ export abstract class ConvenienceRenderer extends Renderer { for (const [name, t] of this.topLevels) { this.nameStoreView.setForTopLevel(name, this.addNameForTopLevel(t, name)); } + for (const o of objects) { const name = this.addNameForNamedType(o); this.addPropertyNames(o, name); } + for (const e of enums) { const name = this.addNameForNamedType(e); this.addEnumCaseNames(e, name); } + for (const u of namedUnions) { const name = this.addNameForNamedType(u); this.addUnionMemberNames(u, name); } + for (const t of this.typeGraph.allTypesUnordered()) { this.addNameForTransformation(t); } return setUnion( [this._globalForbiddenNamespace, this._globalNamespace], - this._otherForbiddenNamespaces.values() + this._otherForbiddenNamespaces.values(), ); } - private addDependenciesForNamedType(type: Type, named: Name): void { + private addDependenciesForNamedType (type: Type, named: Name): void { const dependencyNames = this.makeNamedTypeDependencyNames(type, named); for (const dn of dependencyNames) { this.globalNamespace.add(dn); } } - protected makeNameForTopLevel(_t: Type, givenName: string, _maybeNamedType: Type | undefined): Name { + protected makeNameForTopLevel (_t: Type, givenName: string, _maybeNamedType: Type | undefined): Name { return new SimpleName([givenName], defined(this._namedTypeNamer), topLevelNameOrder); } - private addNameForTopLevel(type: Type, givenName: string): Name { + private addNameForTopLevel (type: Type, givenName: string): Name { const maybeNamedType = this.namedTypeToNameForTopLevel(type); const name = this.makeNameForTopLevel(type, givenName, maybeNamedType); this.globalNamespace.add(name); @@ -268,17 +298,17 @@ export abstract class ConvenienceRenderer extends Renderer { return name; } - private makeNameForType(t: Type, namer: Namer, givenOrder: number, inferredOrder: number): Name { + private makeNameForType (t: Type, namer: Namer, givenOrder: number, inferredOrder: number): Name { const names = t.getNames(); const order = names.areInferred ? inferredOrder : givenOrder; return new SimpleName(names.proposedNames, namer, order); } - protected makeNameForNamedType(t: Type): Name { + protected makeNameForNamedType (t: Type): Name { return this.makeNameForType(t, defined(this._namedTypeNamer), givenNameOrder, inferredNameOrder); } - private addNameForNamedType(type: Type): Name { + private addNameForNamedType (type: Type): Name { const existing = this.nameStoreView.tryGet(type); if (existing !== undefined) return existing; @@ -290,11 +320,11 @@ export abstract class ConvenienceRenderer extends Renderer { return name; } - protected get typesWithNamedTransformations(): ReadonlyMap { + protected get typesWithNamedTransformations (): ReadonlyMap { return defined(this._namesForTransformations); } - protected nameForTransformation(t: Type): Name | undefined { + protected nameForTransformation (t: Type): Name | undefined { const xf = transformationForType(t); if (xf === undefined) return undefined; @@ -302,16 +332,17 @@ export abstract class ConvenienceRenderer extends Renderer { if (name === undefined) { return panic("No name for transformation"); } + return name; } - private addNameForTransformation(t: Type): void { + private addNameForTransformation (t: Type): void { const xf = transformationForType(t); if (xf === undefined) return; assert( defined(this._namesForTransformations).get(t) === undefined, - "Tried to give two names to the same transformation" + "Tried to give two names to the same transformation", ); const name = this.makeNameForTransformation(xf, this.nameStoreView.tryGet(xf.targetType)); @@ -321,10 +352,10 @@ export abstract class ConvenienceRenderer extends Renderer { defined(this._namesForTransformations).set(t, name); } - private processForbiddenWordsInfo( + private processForbiddenWordsInfo ( info: ForbiddenWordsInfo, - namespaceName: string - ): { forbiddenNames: ReadonlySet; forbiddenNamespaces: ReadonlySet } { + namespaceName: string, + ): { forbiddenNames: ReadonlySet, forbiddenNamespaces: ReadonlySet, } { const forbiddenNames: Name[] = []; const forbiddenStrings: string[] = []; for (const nameOrString of info.names) { @@ -334,15 +365,18 @@ export abstract class ConvenienceRenderer extends Renderer { forbiddenNames.push(nameOrString); } } + let namespace = defined(this._otherForbiddenNamespaces).get(namespaceName); if (forbiddenStrings.length > 0 && namespace === undefined) { namespace = keywordNamespace(namespaceName, forbiddenStrings); this._otherForbiddenNamespaces = defined(this._otherForbiddenNamespaces).set(namespaceName, namespace); } + let forbiddenNamespaces = new Set(); if (info.includeGlobalForbidden) { forbiddenNamespaces = forbiddenNamespaces.add(defined(this._globalForbiddenNamespace)); } + if (namespace !== undefined) { forbiddenNamespaces = forbiddenNamespaces.add(namespace); } @@ -350,12 +384,12 @@ export abstract class ConvenienceRenderer extends Renderer { return { forbiddenNames: new Set(forbiddenNames), forbiddenNamespaces }; } - protected makeNameForProperty( + protected makeNameForProperty ( o: ObjectType, _className: Name, p: ClassProperty, jsonName: string, - assignedName: string | undefined + assignedName: string | undefined, ): Name | undefined { const namer = this.namerForObjectProperty(o, p); if (namer === null) return undefined; @@ -374,20 +408,20 @@ export abstract class ConvenienceRenderer extends Renderer { return new SimpleName(names, namer, order); } - protected makePropertyDependencyNames( + protected makePropertyDependencyNames ( _o: ObjectType, _className: Name, _p: ClassProperty, _jsonName: string, - _name: Name + _name: Name, ): Name[] { return []; } - private addPropertyNames(o: ObjectType, className: Name): void { + private addPropertyNames (o: ObjectType, className: Name): void { const { forbiddenNames, forbiddenNamespaces } = this.processForbiddenWordsInfo( this.forbiddenForObjectProperties(o, className), - "forbidden-for-properties" + "forbidden-for-properties", ); let ns: Namespace | undefined; @@ -401,37 +435,41 @@ export abstract class ConvenienceRenderer extends Renderer { } else { name = this.makeNameForProperty(o, className, p, jsonName, assignedName); } + if (name === undefined) return undefined; if (ns === undefined) { ns = new Namespace(o.getCombinedName(), this.globalNamespace, forbiddenNamespaces, forbiddenNames); } + ns.add(name); for (const depName of this.makePropertyDependencyNames(o, className, p, jsonName, name)) { ns.add(depName); } + return name; }); defined(this._propertyNamesStoreView).set(o, names); } - protected makeNameForUnionMember(u: UnionType, unionName: Name, t: Type): Name { + protected makeNameForUnionMember (u: UnionType, unionName: Name, t: Type): Name { const [assignedName, isFixed] = unionMemberName(u, t, this.targetLanguage.name); if (isFixed) { return new FixedName(defined(assignedName)); } + return new DependencyName(nonNull(this._unionMemberNamer), unionMemberNameOrder, lookup => { if (assignedName !== undefined) return assignedName; return this.proposeUnionMemberName(u, unionName, t, lookup); }); } - private addUnionMemberNames(u: UnionType, unionName: Name): void { + private addUnionMemberNames (u: UnionType, unionName: Name): void { const memberNamer = this._unionMemberNamer; if (memberNamer === null) return; const { forbiddenNames, forbiddenNamespaces } = this.processForbiddenWordsInfo( this.forbiddenForUnionMembers(u, unionName), - "forbidden-for-union-members" + "forbidden-for-union-members", ); let ns: Namespace; @@ -440,19 +478,21 @@ export abstract class ConvenienceRenderer extends Renderer { } else { ns = new Namespace(u.getCombinedName(), this.globalNamespace, forbiddenNamespaces, forbiddenNames); } + let names = new Map(); for (const t of u.members) { const name = this.makeNameForUnionMember(u, unionName, followTargetType(t)); names.set(t, ns.add(name)); } + defined(this._memberNamesStoreView).set(u, names); } - protected makeNameForEnumCase( + protected makeNameForEnumCase ( e: EnumType, _enumName: Name, caseName: string, - assignedName: string | undefined + assignedName: string | undefined, ): Name { // FIXME: See the FIXME in `makeNameForProperty`. We do have global // enum cases, though (in Go), so this is actually useful already. @@ -463,12 +503,12 @@ export abstract class ConvenienceRenderer extends Renderer { } // FIXME: this is very similar to addPropertyNameds and addUnionMemberNames - private addEnumCaseNames(e: EnumType, enumName: Name): void { + private addEnumCaseNames (e: EnumType, enumName: Name): void { if (this._enumCaseNamer === null) return; const { forbiddenNames, forbiddenNamespaces } = this.processForbiddenWordsInfo( this.forbiddenForEnumCases(e, enumName), - "forbidden-for-enum-cases" + "forbidden-for-enum-cases", ); let ns: Namespace; @@ -477,6 +517,7 @@ export abstract class ConvenienceRenderer extends Renderer { } else { ns = new Namespace(e.getCombinedName(), this.globalNamespace, forbiddenNamespaces, forbiddenNames); } + let names = new Map(); const accessorNames = enumCaseNames(e, this.targetLanguage.name); for (const caseName of e.cases) { @@ -487,12 +528,14 @@ export abstract class ConvenienceRenderer extends Renderer { } else { name = this.makeNameForEnumCase(e, enumName, caseName, assignedName); } + names.set(caseName, ns.add(name)); } + defined(this._caseNamesStoreView).set(e, names); } - private childrenOfType(t: Type): ReadonlySet { + private childrenOfType (t: Type): ReadonlySet { const names = this.names; if (t instanceof ClassType) { const propertyNameds = defined(this._propertyNamesStoreView).get(t); @@ -503,52 +546,53 @@ export abstract class ConvenienceRenderer extends Renderer { const sortedMap = mapSortBy(filteredMap, (_, n) => defined(names.get(defined(propertyNameds.get(n))))); return new Set(sortedMap.values()); } + return t.getChildren(); } - protected get namedUnions(): ReadonlySet { + protected get namedUnions (): ReadonlySet { return defined(this._namedUnions); } - protected get haveNamedUnions(): boolean { + protected get haveNamedUnions (): boolean { return this.namedUnions.size > 0; } - protected get haveNamedTypes(): boolean { + protected get haveNamedTypes (): boolean { return defined(this._namedTypes).length > 0; } - protected get haveUnions(): boolean { + protected get haveUnions (): boolean { return defined(this._haveUnions); } - protected get haveMaps(): boolean { + protected get haveMaps (): boolean { return defined(this._haveMaps); } - protected get haveOptionalProperties(): boolean { + protected get haveOptionalProperties (): boolean { return defined(this._haveOptionalProperties); } // FIXME: Inconsistently named, though technically correct. Right now all enums are named, // but this should really be called `namedEnums`. - protected get enums(): ReadonlySet { + protected get enums (): ReadonlySet { return defined(this._namedEnums); } - protected get haveEnums(): boolean { + protected get haveEnums (): boolean { return this.enums.size > 0; } - protected proposedUnionMemberNameForTypeKind(_kind: TypeKind): string | null { + protected proposedUnionMemberNameForTypeKind (_kind: TypeKind): string | null { return null; } - protected proposeUnionMemberName( + protected proposeUnionMemberName ( _u: UnionType, _unionName: Name, fieldType: Type, - lookup: (n: Name) => string + lookup: (n: Name) => string, ): string { const simpleName = this.proposedUnionMemberNameForTypeKind(fieldType.kind); if (simpleName !== null) { @@ -573,49 +617,50 @@ export abstract class ConvenienceRenderer extends Renderer { objectType => { assert( this.targetLanguage.supportsFullObjectType, - "Object type should have been replaced in `replaceObjectType`" + "Object type should have been replaced in `replaceObjectType`", ); return lookup(this.nameForNamedType(objectType)); }, _enumType => "enum", _unionType => "union", - transformedType => transformedType.kind.replace("-", "_") + transformedType => transformedType.kind.replace("-", "_"), ); return typeNameForUnionMember(fieldType); } - protected nameForNamedType(t: Type): Name { + protected nameForNamedType (t: Type): Name { return this.nameStoreView.get(t); } - protected isForwardDeclaredType(t: Type): boolean { + protected isForwardDeclaredType (t: Type): boolean { return defined(this._declarationIR).forwardedTypes.has(t); } - protected isImplicitCycleBreaker(_t: Type): boolean { + protected isImplicitCycleBreaker (_t: Type): boolean { return panic("A renderer that invokes isCycleBreakerType must implement isImplicitCycleBreaker"); } - protected canBreakCycles(_t: Type): boolean { + protected canBreakCycles (_t: Type): boolean { return true; } - protected isCycleBreakerType(t: Type): boolean { + protected isCycleBreakerType (t: Type): boolean { if (this._cycleBreakerTypes === undefined) { this._cycleBreakerTypes = cycleBreakerTypesForGraph( this.typeGraph, s => this.isImplicitCycleBreaker(s), - s => this.canBreakCycles(s) + s => this.canBreakCycles(s), ); } + return this._cycleBreakerTypes.has(t); } - protected forEachTopLevel( + protected forEachTopLevel ( blankLocations: BlankLineConfig, f: (t: Type, name: Name, position: ForEachPosition) => void, - predicate?: (t: Type) => boolean + predicate?: (t: Type) => boolean, ): boolean { let topLevels: ReadonlyMap; if (predicate !== undefined) { @@ -623,39 +668,40 @@ export abstract class ConvenienceRenderer extends Renderer { } else { topLevels = this.topLevels; } + return this.forEachWithBlankLines(topLevels, blankLocations, (t, name, pos) => - f(t, this.nameStoreView.getForTopLevel(name), pos) + f(t, this.nameStoreView.getForTopLevel(name), pos), ); } - protected forEachDeclaration( + protected forEachDeclaration ( blankLocations: BlankLineConfig, - f: (decl: Declaration, position: ForEachPosition) => void + f: (decl: Declaration, position: ForEachPosition) => void, ) { this.forEachWithBlankLines( iterableEnumerate(defined(this._declarationIR).declarations), blankLocations, - (decl, _, pos) => f(decl, pos) + (decl, _, pos) => f(decl, pos), ); } - setAlphabetizeProperties(value: boolean): void { + setAlphabetizeProperties (value: boolean): void { this._alphabetizeProperties = value; } - protected getAlphabetizeProperties(): boolean { + protected getAlphabetizeProperties (): boolean { return this._alphabetizeProperties; } // Returns the number of properties defined for the specified object type. - protected propertyCount(o: ObjectType): number { + protected propertyCount (o: ObjectType): number { const propertyNames = defined(this._propertyNamesStoreView).get(o); return propertyNames.size; } - protected sortClassProperties( + protected sortClassProperties ( properties: ReadonlyMap, - propertyNames: ReadonlyMap + propertyNames: ReadonlyMap, ): ReadonlyMap { if (this._alphabetizeProperties) { return mapSortBy(properties, (_p: ClassProperty, jsonName: string) => { @@ -667,10 +713,10 @@ export abstract class ConvenienceRenderer extends Renderer { } } - protected forEachClassProperty( + protected forEachClassProperty ( o: ObjectType, blankLocations: BlankLineConfig, - f: (name: Name, jsonName: string, p: ClassProperty, position: ForEachPosition) => void + f: (name: Name, jsonName: string, p: ClassProperty, position: ForEachPosition) => void, ): void { const propertyNames = defined(this._propertyNamesStoreView).get(o); const sortedProperties = this.sortClassProperties(o.getProperties(), propertyNames); @@ -680,44 +726,45 @@ export abstract class ConvenienceRenderer extends Renderer { }); } - protected nameForUnionMember(u: UnionType, t: Type): Name { + protected nameForUnionMember (u: UnionType, t: Type): Name { return defined(defined(this._memberNamesStoreView).get(u).get(t)); } - protected nameForEnumCase(e: EnumType, caseName: string): Name { + protected nameForEnumCase (e: EnumType, caseName: string): Name { const caseNames = defined(this._caseNamesStoreView).get(e); return defined(caseNames.get(caseName)); } - protected forEachUnionMember( + protected forEachUnionMember ( u: UnionType, members: ReadonlySet | null, blankLocations: BlankLineConfig, sortOrder: ((n: Name, t: Type) => string) | null, - f: (name: Name, t: Type, position: ForEachPosition) => void + f: (name: Name, t: Type, position: ForEachPosition) => void, ): void { const iterateMembers = members === null ? u.members : members; if (sortOrder === null) { sortOrder = n => defined(this.names.get(n)); } + const memberNames = mapFilter(defined(this._memberNamesStoreView).get(u), (_, t) => iterateMembers.has(t)); const sortedMemberNames = mapSortBy(memberNames, sortOrder); this.forEachWithBlankLines(sortedMemberNames, blankLocations, f); } - protected forEachEnumCase( + protected forEachEnumCase ( e: EnumType, blankLocations: BlankLineConfig, - f: (name: Name, jsonName: string, position: ForEachPosition) => void + f: (name: Name, jsonName: string, position: ForEachPosition) => void, ): void { const caseNames = defined(this._caseNamesStoreView).get(e); const sortedCaseNames = mapSortBy(caseNames, n => defined(this.names.get(n))); this.forEachWithBlankLines(sortedCaseNames, blankLocations, f); } - protected forEachTransformation( + protected forEachTransformation ( blankLocations: BlankLineConfig, - f: (n: Name, t: Type, position: ForEachPosition) => void + f: (n: Name, t: Type, position: ForEachPosition) => void, ): void { this.forEachWithBlankLines(defined(this._namesForTransformations), blankLocations, f); } @@ -725,31 +772,31 @@ export abstract class ConvenienceRenderer extends Renderer { protected forEachSpecificNamedType( blankLocations: BlankLineConfig, types: Iterable<[any, T]>, - f: (t: T, name: Name, position: ForEachPosition) => void + f: (t: T, name: Name, position: ForEachPosition) => void, ): void { this.forEachWithBlankLines(types, blankLocations, (t, _, pos) => f(t, this.nameForNamedType(t), pos)); } - protected forEachObject( + protected forEachObject ( blankLocations: BlankLineConfig, f: - | ((c: ClassType, className: Name, position: ForEachPosition) => void) - | ((o: ObjectType, objectName: Name, position: ForEachPosition) => void) + | ((c: ClassType, className: Name, position: ForEachPosition) => void) + | ((o: ObjectType, objectName: Name, position: ForEachPosition) => void), ): void { // FIXME: This is ugly. this.forEachSpecificNamedType(blankLocations, defined(this._namedObjects).entries(), f as any); } - protected forEachEnum( + protected forEachEnum ( blankLocations: BlankLineConfig, - f: (u: EnumType, enumName: Name, position: ForEachPosition) => void + f: (u: EnumType, enumName: Name, position: ForEachPosition) => void, ): void { this.forEachSpecificNamedType(blankLocations, this.enums.entries(), f); } - protected forEachUnion( + protected forEachUnion ( blankLocations: BlankLineConfig, - f: (u: UnionType, unionName: Name, position: ForEachPosition) => void + f: (u: UnionType, unionName: Name, position: ForEachPosition) => void, ): void { this.forEachSpecificNamedType(blankLocations, this.namedUnions.entries(), f); } @@ -757,7 +804,7 @@ export abstract class ConvenienceRenderer extends Renderer { protected forEachUniqueUnion( blankLocations: BlankLineConfig, uniqueValue: (u: UnionType) => T, - f: (firstUnion: UnionType, value: T, position: ForEachPosition) => void + f: (firstUnion: UnionType, value: T, position: ForEachPosition) => void, ): void { const firstUnionByValue = new Map(); for (const u of this.namedUnions) { @@ -766,16 +813,17 @@ export abstract class ConvenienceRenderer extends Renderer { firstUnionByValue.set(v, u); } } + this.forEachWithBlankLines(firstUnionByValue, blankLocations, f); } - protected forEachNamedType( + protected forEachNamedType ( blankLocations: BlankLineConfig, objectFunc: - | ((c: ClassType, className: Name, position: ForEachPosition) => void) - | ((o: ObjectType, objectName: Name, position: ForEachPosition) => void), + | ((c: ClassType, className: Name, position: ForEachPosition) => void) + | ((o: ObjectType, objectName: Name, position: ForEachPosition) => void), enumFunc: (e: EnumType, enumName: Name, position: ForEachPosition) => void, - unionFunc: (u: UnionType, unionName: Name, position: ForEachPosition) => void + unionFunc: (u: UnionType, unionName: Name, position: ForEachPosition) => void, ): void { this.forEachWithBlankLines(defined(this._namedTypes).entries(), blankLocations, (t, _, pos) => { const name = this.nameForNamedType(t); @@ -796,15 +844,15 @@ export abstract class ConvenienceRenderer extends Renderer { // You should never have to use this to produce parts of your generated // code. If you need to modify a Name, for example to change its casing, // use `modifySource`. - protected sourcelikeToString(src: Sourcelike): string { + protected sourcelikeToString (src: Sourcelike): string { return serializeRenderResult(sourcelikeToSource(src), this.names, "").lines.join("\n"); } - protected get commentLineStart(): string { + protected get commentLineStart (): string { return "// "; } - protected emitComments(comments: Comment[]): void { + protected emitComments (comments: Comment[]): void { comments.forEach(comment => { if (isStringComment(comment)) { this.emitCommentLines([comment]); @@ -820,19 +868,20 @@ export abstract class ConvenienceRenderer extends Renderer { }); } - protected emitCommentLines( + protected emitCommentLines ( lines: Sourcelike[], { lineStart = this.commentLineStart, firstLineStart = lineStart, lineEnd, beforeComment, - afterComment - }: CommentOptions = {} + afterComment, + }: CommentOptions = {}, ): void { if (beforeComment !== undefined) { this.emitLine(beforeComment); } + let first = true; for (const line of lines) { let start = first ? firstLineStart : lineStart; @@ -848,24 +897,25 @@ export abstract class ConvenienceRenderer extends Renderer { this.emitLine(start, line); } } + if (afterComment !== undefined) { this.emitLine(afterComment); } } - protected emitDescription(description: Sourcelike[] | undefined): void { + protected emitDescription (description: Sourcelike[] | undefined): void { if (description === undefined) return; // FIXME: word-wrap this.emitDescriptionBlock(description); } - protected emitDescriptionBlock(lines: Sourcelike[]): void { + protected emitDescriptionBlock (lines: Sourcelike[]): void { this.emitCommentLines(lines); } - protected emitPropertyTable( + protected emitPropertyTable ( c: ClassType, - makePropertyRow: (name: Name, jsonName: string, p: ClassProperty) => Sourcelike[] + makePropertyRow: (name: Name, jsonName: string, p: ClassProperty) => Sourcelike[], ): void { let table: Sourcelike[][] = []; const emitTable = () => { @@ -880,12 +930,13 @@ export abstract class ConvenienceRenderer extends Renderer { emitTable(); this.emitDescription(description); } + table.push(makePropertyRow(name, jsonName, p)); }); emitTable(); } - private processGraph(): void { + private processGraph (): void { this._declarationIR = declarationsForGraph( this.typeGraph, this.needsTypeDeclarationBeforeUse ? t => this.canBeForwardDeclared(t) : undefined, @@ -894,8 +945,9 @@ export abstract class ConvenienceRenderer extends Renderer { if (t instanceof UnionType) { return this.unionNeedsName(t); } + return isNamedType(t); - } + }, ); const types = this.typeGraph.allTypesUnordered(); @@ -910,7 +962,7 @@ export abstract class ConvenienceRenderer extends Renderer { this._namedUnions = new Set(unions); } - protected emitSource(givenOutputFilename: string): void { + protected emitSource (givenOutputFilename: string): void { this.processGraph(); this.emitSourceStructure(givenOutputFilename); } @@ -920,11 +972,12 @@ export abstract class ConvenienceRenderer extends Renderer { const processed = new Set(); const queue = Array.from(this.typeGraph.topLevels.values()); - function visit(t: Type) { + function visit (t: Type) { if (visitedTypes.has(t)) return; for (const c of t.getChildren()) { queue.push(c); } + visitedTypes.add(t); processed.add(process(t)); } @@ -934,6 +987,7 @@ export abstract class ConvenienceRenderer extends Renderer { if (maybeType === undefined) { break; } + visit(maybeType); } diff --git a/packages/quicktype-core/src/CycleBreaker.ts b/packages/quicktype-core/src/CycleBreaker.ts index d3eba6321..586ae8f49 100644 --- a/packages/quicktype-core/src/CycleBreaker.ts +++ b/packages/quicktype-core/src/CycleBreaker.ts @@ -1,18 +1,19 @@ import { assert, panic } from "./support/Support"; -export function breakCycles(outEdges: number[][], chooseBreaker: (cycle: number[]) => [number, T]): [number, T][] { +export function breakCycles (outEdges: number[][], chooseBreaker: (cycle: number[]) => [number, T]): Array<[number, T]> { const numNodes = outEdges.length; const inEdges: number[][] = []; const inDegree: number[] = []; const outDegree: number[] = []; const done: boolean[] = []; - const results: [number, T][] = []; + const results: Array<[number, T]> = []; for (let i = 0; i < numNodes; i++) { inEdges.push([]); inDegree.push(0); outDegree.push(outEdges[i].length); done.push(false); } + for (let i = 0; i < numNodes; i++) { for (const n of outEdges[i]) { inEdges[n].push(i); @@ -27,7 +28,7 @@ export function breakCycles(outEdges: number[][], chooseBreaker: (cycle: numb } } - function removeNode(node: number): void { + function removeNode (node: number): void { for (const n of outEdges[node]) { assert(inDegree[n] > 0); inDegree[n] -= 1; @@ -50,10 +51,11 @@ export function breakCycles(outEdges: number[][], chooseBreaker: (cycle: numb for (;;) { const i = workList.pop(); if (i !== undefined) { - if (done[i] || (inDegree[i] === 0 && outDegree[i] === 0)) { + if (done[i] || inDegree[i] === 0 && outDegree[i] === 0) { done[i] = true; continue; } + assert(inDegree[i] === 0 || outDegree[i] === 0, "Can't have nodes in the worklist with in and out edges"); removeNode(i); @@ -82,6 +84,7 @@ export function breakCycles(outEdges: number[][], chooseBreaker: (cycle: numb if (maybeEdge === undefined) { return panic("Presumed cycle is not a cycle"); } + const maybeFirst = path.indexOf(maybeEdge); if (maybeFirst === undefined) { // No cycle yet, continue @@ -93,11 +96,12 @@ export function breakCycles(outEdges: number[][], chooseBreaker: (cycle: numb // We found a cycle - break it const cycle = path.slice(maybeFirst); const [breakNode, info] = chooseBreaker(cycle); - assert(cycle.indexOf(breakNode) >= 0, "Breaker chose an invalid node"); + assert(cycle.includes(breakNode), "Breaker chose an invalid node"); removeNode(breakNode); results.push([breakNode, info]); break; } + continue; } diff --git a/packages/quicktype-core/src/DateTime.ts b/packages/quicktype-core/src/DateTime.ts index 20d0340b8..899daa704 100644 --- a/packages/quicktype-core/src/DateTime.ts +++ b/packages/quicktype-core/src/DateTime.ts @@ -29,17 +29,17 @@ const DAYS = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; const TIME = /^(\d\d):(\d\d):(\d\d)(\.\d+)?(z|[+-]\d\d:\d\d)?$/i; export interface DateTimeRecognizer { - isDate(s: string): boolean; - isTime(s: string): boolean; - isDateTime(s: string): boolean; + isDate: (s: string) => boolean; + isDateTime: (s: string) => boolean; + isTime: (s: string) => boolean; } const DATE_TIME_SEPARATOR = /t|\s/i; export class DefaultDateTimeRecognizer implements DateTimeRecognizer { - isDate(str: string) { + isDate (str: string) { // full-date from http://tools.ietf.org/html/rfc3339#section-5.6 - const matches = str.match(DATE); + const matches = DATE.exec(str); if (matches === null) return false; const month = +matches[2]; @@ -47,8 +47,8 @@ export class DefaultDateTimeRecognizer implements DateTimeRecognizer { return month >= 1 && month <= 12 && day >= 1 && day <= DAYS[month]; } - isTime(str: string): boolean { - const matches = str.match(TIME); + isTime (str: string): boolean { + const matches = TIME.exec(str); if (matches === null) return false; const hour = +matches[1]; @@ -57,7 +57,7 @@ export class DefaultDateTimeRecognizer implements DateTimeRecognizer { return hour <= 23 && minute <= 59 && second <= 59; } - isDateTime(str: string): boolean { + isDateTime (str: string): boolean { // http://tools.ietf.org/html/rfc3339#section-5.6 const dateTime = str.split(DATE_TIME_SEPARATOR); return dateTime.length === 2 && this.isDate(dateTime[0]) && this.isTime(dateTime[1]); diff --git a/packages/quicktype-core/src/DeclarationIR.ts b/packages/quicktype-core/src/DeclarationIR.ts index 8b36dbd51..2a42f716f 100644 --- a/packages/quicktype-core/src/DeclarationIR.ts +++ b/packages/quicktype-core/src/DeclarationIR.ts @@ -1,7 +1,7 @@ import { setUnionInto, setFilter, iterableFirst, setSubtract, setIntersect } from "collection-utils"; -import { TypeGraph } from "./TypeGraph"; -import { Type } from "./Type"; +import { type TypeGraph } from "./TypeGraph"; +import { type Type } from "./Type"; import { panic, defined, assert } from "./support/Support"; import { Graph } from "./Graph"; import { messageError } from "./Messages"; @@ -14,41 +14,43 @@ export interface Declaration { } export class DeclarationIR { - readonly declarations: ReadonlyArray; + readonly declarations: readonly Declaration[]; - constructor(declarations: Iterable, readonly forwardedTypes: Set) { + constructor (declarations: Iterable, readonly forwardedTypes: Set) { this.declarations = Array.from(declarations); } } -function findBreaker( +function findBreaker ( t: Type, - path: ReadonlyArray, - canBreak: ((t: Type) => boolean) | undefined + path: readonly Type[], + canBreak: ((t: Type) => boolean) | undefined, ): Type | undefined { const index = path.indexOf(t); if (index < 0) return undefined; if (canBreak === undefined) { return path[index]; } + const potentialBreakers = path.slice(0, index + 1).reverse(); const maybeBreaker = potentialBreakers.find(canBreak); if (maybeBreaker === undefined) { return panic("Found a cycle that cannot be broken"); } + return maybeBreaker; } -export function cycleBreakerTypesForGraph( +export function cycleBreakerTypesForGraph ( graph: TypeGraph, isImplicitCycleBreaker: (t: Type) => boolean, - canBreakCycles: (t: Type) => boolean + canBreakCycles: (t: Type) => boolean, ): Set { const visitedTypes = new Set(); const cycleBreakerTypes = new Set(); const queue: Type[] = Array.from(graph.topLevels.values()); - function visit(t: Type, path: Type[]): void { + function visit (t: Type, path: Type[]): void { if (visitedTypes.has(t)) return; if (isImplicitCycleBreaker(t)) { @@ -83,11 +85,11 @@ export function cycleBreakerTypesForGraph( return cycleBreakerTypes; } -export function declarationsForGraph( +export function declarationsForGraph ( typeGraph: TypeGraph, canBeForwardDeclared: ((t: Type) => boolean) | undefined, childrenOfType: (t: Type) => ReadonlySet, - needsDeclaration: (t: Type) => boolean + needsDeclaration: (t: Type) => boolean, ): DeclarationIR { /* function nodeTitle(t: Type): string { @@ -108,9 +110,9 @@ export function declarationsForGraph( const forwardedTypes = new Set(); const visitedComponents = new Set>(); - function processGraph(graph: Graph, _writeComponents: boolean): void { + function processGraph (graph: Graph, _writeComponents: boolean): void { const componentsGraph = graph.stronglyConnectedComponents(); - function visitComponent(component: ReadonlySet): void { + function visitComponent (component: ReadonlySet): void { if (visitedComponents.has(component)) return; visitedComponents.add(component); @@ -147,6 +149,7 @@ export function declarationsForGraph( for (const t of declarationNeeded) { declarations.push({ kind: "define", type: t }); } + return; } @@ -160,9 +163,11 @@ export function declarationsForGraph( if (forwardDeclarable.size === 0) { return messageError("IRNoForwardDeclarableTypeInCycle", {}); } + for (const t of forwardDeclarable) { declarations.push({ kind: "forward", type: t }); } + setUnionInto(forwardedTypes, forwardDeclarable); const rest = setSubtract(component, forwardDeclarable); const restGraph = new Graph(rest, true, t => setIntersect(childrenOfType(t), rest)); @@ -170,6 +175,7 @@ export function declarationsForGraph( for (const t of forwardDeclarable) { declarations.push({ kind: "define", type: t }); } + return; } diff --git a/packages/quicktype-core/src/GatherNames.ts b/packages/quicktype-core/src/GatherNames.ts index 40d1f4b05..85bbeb5ca 100644 --- a/packages/quicktype-core/src/GatherNames.ts +++ b/packages/quicktype-core/src/GatherNames.ts @@ -1,8 +1,9 @@ import * as pluralize from "pluralize"; import { setUnion, setMap, setSortBy } from "collection-utils"; -import { TypeGraph } from "./TypeGraph"; -import { Type, ObjectType } from "./Type"; +import { type TypeGraph } from "./TypeGraph"; +import { type Type} from "./Type"; +import { ObjectType } from "./Type"; import { matchCompoundType, nullableFromUnion } from "./TypeUtils"; import { TypeNames, namesTypeAttributeKind, TooManyTypeNames, tooManyNamesThreshold } from "./attributes/TypeNames"; import { defined, panic, assert } from "./support/Support"; @@ -10,29 +11,32 @@ import { transformationForType } from "./Transformers"; class UniqueQueue { private readonly _present = new Set(); - private _queue: (T | undefined)[] = []; + + private _queue: Array = []; + private _front = 0; - get size(): number { + get size (): number { return this._queue.length - this._front; } - get isEmpty(): boolean { + get isEmpty (): boolean { return this.size <= 0; } - push(v: T): void { + push (v: T): void { if (this._present.has(v)) return; this._queue.push(v); this._present.add(v); } - unshift(): T { + unshift (): T { assert(!this.isEmpty, "Trying to unshift from an empty queue"); const v = this._queue[this._front]; if (v === undefined) { return panic("Value should have been present in queue"); } + this._queue[this._front] = undefined; this._front += 1; this._present.delete(v); @@ -82,8 +86,8 @@ class UniqueQueue { // step 1, and its alternatives to a union of its direct and ancestor // alternatives, gathered in steps 2 and 3. -export function gatherNames(graph: TypeGraph, destructive: boolean, debugPrint: boolean): void { - function setNames(t: Type, tn: TypeNames): void { +export function gatherNames (graph: TypeGraph, destructive: boolean, debugPrint: boolean): void { + function setNames (t: Type, tn: TypeNames): void { graph.attributeStore.set(namesTypeAttributeKind, t, tn); } @@ -99,7 +103,7 @@ export function gatherNames(graph: TypeGraph, destructive: boolean, debugPrint: // null means there are too many const namesForType = new Map | null>(); - function addNames(t: Type, names: ReadonlySet | null) { + function addNames (t: Type, names: ReadonlySet | null) { // Always use the type's given names if it has some if (t.hasNames) { const originalNames = t.getNames(); @@ -123,6 +127,7 @@ export function gatherNames(graph: TypeGraph, destructive: boolean, debugPrint: if (newNames !== null && newNames.size >= tooManyNamesThreshold) { newNames = null; } + namesForType.set(t, newNames); const transformation = transformationForType(t); @@ -173,7 +178,7 @@ export function gatherNames(graph: TypeGraph, destructive: boolean, debugPrint: for (const memberType of members) { addNames(memberType, names); } - } + }, ); } } @@ -193,9 +198,9 @@ export function gatherNames(graph: TypeGraph, destructive: boolean, debugPrint: const ancestorAlternativesForType = new Map | null>(); const pairsProcessed = new Map>(); - function addAlternatives( + function addAlternatives ( existing: ReadonlySet | undefined, - alternatives: string[] + alternatives: string[], ): ReadonlySet | undefined | null { if (alternatives.length === 0) { return existing; @@ -204,14 +209,16 @@ export function gatherNames(graph: TypeGraph, destructive: boolean, debugPrint: if (existing === undefined) { existing = new Set(); } + existing = setUnion(existing, alternatives); if (existing.size < tooManyNamesThreshold) { return existing; } + return null; } - function processType(ancestor: Type | undefined, t: Type, alternativeSuffix: string | undefined) { + function processType (ancestor: Type | undefined, t: Type, alternativeSuffix: string | undefined) { const names = defined(namesForType.get(t)); let processedEntry = pairsProcessed.get(ancestor); @@ -263,6 +270,7 @@ export function gatherNames(graph: TypeGraph, destructive: boolean, debugPrint: if (ancestorAlternatives !== undefined) { ancestorAlternativesForType.set(t, ancestorAlternatives); } + if (directAlternatives !== undefined) { directAlternativesForType.set(t, directAlternatives); } @@ -294,7 +302,7 @@ export function gatherNames(graph: TypeGraph, destructive: boolean, debugPrint: for (const memberType of members) { processType(ancestorForMembers, memberType, undefined); } - } + }, ); } } @@ -310,6 +318,7 @@ export function gatherNames(graph: TypeGraph, destructive: boolean, debugPrint: directAlternativesForType.set(t, null); continue; } + let alternatives = directAlternativesForType.get(t); if (alternatives === null) continue; if (alternatives === undefined) { @@ -318,7 +327,7 @@ export function gatherNames(graph: TypeGraph, destructive: boolean, debugPrint: alternatives = setUnion( alternatives, - setMap(names, name => `${name}_${t.kind}`) + setMap(names, name => `${name}_${t.kind}`), ); directAlternativesForType.set(t, alternatives); } @@ -343,6 +352,7 @@ export function gatherNames(graph: TypeGraph, destructive: boolean, debugPrint: } else { alternatives = new Set(); } + if (ancestorAlternatives !== null && ancestorAlternatives !== undefined) { alternatives = setUnion(alternatives, ancestorAlternatives); } diff --git a/packages/quicktype-core/src/Graph.ts b/packages/quicktype-core/src/Graph.ts index fcff0a56a..5bcf6ba87 100644 --- a/packages/quicktype-core/src/Graph.ts +++ b/packages/quicktype-core/src/Graph.ts @@ -2,7 +2,7 @@ import { setMap } from "collection-utils"; import { defined, repeated, assert, repeatedCall } from "./support/Support"; -function countComponentGraphNodes(components: number[][]): number { +function countComponentGraphNodes (components: number[][]): number { if (components.length === 0) return 0; let largest = -1; @@ -22,7 +22,7 @@ function countComponentGraphNodes(components: number[][]): number { } // https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm -function stronglyConnectedComponents(successors: number[][]): number[][] { +function stronglyConnectedComponents (successors: number[][]): number[][] { let index = 0; const stack: number[] = []; const numNodes = successors.length; @@ -31,7 +31,7 @@ function stronglyConnectedComponents(successors: number[][]): number[][] { const onStack: boolean[] = repeated(numNodes, false); const sccs: number[][] = []; - function strongconnect(v: number): void { + function strongconnect (v: number): void { // Set the depth index for v to the smallest unused index indexes[v] = index; lowLinks[v] = index; @@ -64,6 +64,7 @@ function stronglyConnectedComponents(successors: number[][]): number[][] { onStack[w] = false; scc.push(w); } while (w !== v); + sccs.push(scc); } } @@ -79,7 +80,7 @@ function stronglyConnectedComponents(successors: number[][]): number[][] { return sccs; } -function buildComponentOfNodeMap(successors: number[][], components: number[][]): number[] { +function buildComponentOfNodeMap (successors: number[][], components: number[][]): number[] { const numComponents = components.length; const numNodes = successors.length; @@ -92,10 +93,11 @@ function buildComponentOfNodeMap(successors: number[][], components: number[][]) componentOfNode[n] = c; } } + return componentOfNode; } -function buildMetaSuccessors(successors: number[][], components: number[][]): number[][] { +function buildMetaSuccessors (successors: number[][], components: number[][]): number[][] { const numComponents = components.length; const componentOfNode = buildComponentOfNodeMap(successors, components); const componentAdded: boolean[] = repeated(numComponents, false); @@ -125,7 +127,7 @@ function buildMetaSuccessors(successors: number[][], components: number[][]): nu return metaSuccessors; } -function invertEdges(successors: number[][]): number[][] { +function invertEdges (successors: number[][]): number[][] { const numNodes = successors.length; const predecessors: number[][] = repeatedCall(numNodes, () => []); @@ -138,7 +140,7 @@ function invertEdges(successors: number[][]): number[][] { return predecessors; } -function calculateInDegrees(successors: number[][]): number[] { +function calculateInDegrees (successors: number[][]): number[] { const numNodes = successors.length; const inDegrees: number[] = repeated(numNodes, 0); @@ -151,7 +153,7 @@ function calculateInDegrees(successors: number[][]): number[] { return inDegrees; } -function findRoots(successors: number[][]): number[] { +function findRoots (successors: number[][]): number[] { const numNodes = successors.length; const inDegrees = calculateInDegrees(successors); const roots: number[] = []; @@ -166,11 +168,13 @@ function findRoots(successors: number[][]): number[] { } export class Graph { - private readonly _nodes: ReadonlyArray; + private readonly _nodes: readonly T[]; + private readonly _indexByNode: ReadonlyMap; + private readonly _successors: number[][]; - constructor(nodes: Iterable, invertDirection: boolean, edges: number[][] | ((node: T) => ReadonlySet)) { + constructor (nodes: Iterable, invertDirection: boolean, edges: number[][] | ((node: T) => ReadonlySet)) { this._nodes = Array.from(nodes); this._indexByNode = new Map(this._nodes.map((n, i): [T, number] => [n, i])); let edgesArray: number[][]; @@ -183,24 +187,25 @@ export class Graph { if (invertDirection) { edgesArray = invertEdges(edgesArray); } + this._successors = edgesArray; } - get size(): number { + get size (): number { return this._nodes.length; } - get nodes(): ReadonlyArray { + get nodes (): readonly T[] { return this._nodes; } - findRoots(): ReadonlySet { + findRoots (): ReadonlySet { const roots = findRoots(this._successors); return new Set(roots.map(n => this._nodes[n])); } // The subgraph starting at `root` must be acyclic. - dfsTraversal(root: T, preOrder: boolean, process: (node: T) => void): void { + dfsTraversal (root: T, preOrder: boolean, process: (node: T) => void): void { const visited = repeated(this.size, false); const visit = (v: number): void => { @@ -223,17 +228,17 @@ export class Graph { visit(defined(this._indexByNode.get(root))); } - stronglyConnectedComponents(): Graph> { + stronglyConnectedComponents (): Graph> { const components = stronglyConnectedComponents(this._successors); const componentSuccessors = buildMetaSuccessors(this._successors, components); return new Graph( components.map(ns => setMap(ns, n => this._nodes[n])), false, - componentSuccessors + componentSuccessors, ); } - makeDot(includeNode: (n: T) => boolean, nodeLabel: (n: T) => string): string { + makeDot (includeNode: (n: T) => boolean, nodeLabel: (n: T) => string): string { const lines: string[] = []; lines.push("digraph G {"); lines.push(" ordering = out;"); diff --git a/packages/quicktype-core/src/GraphRewriting.ts b/packages/quicktype-core/src/GraphRewriting.ts index b3610ad80..e4c099fee 100644 --- a/packages/quicktype-core/src/GraphRewriting.ts +++ b/packages/quicktype-core/src/GraphRewriting.ts @@ -1,77 +1,82 @@ import { mapMap, EqualityMap } from "collection-utils"; -import { PrimitiveTypeKind, Type, ClassProperty, MaybeTypeIdentity } from "./Type"; +import { type PrimitiveTypeKind, type Type, type ClassProperty, type MaybeTypeIdentity } from "./Type"; import { combineTypeAttributesOfTypes } from "./TypeUtils"; import { - TypeGraph, - TypeRef, + type TypeGraph, + type TypeRef} from "./TypeGraph"; +import { derefTypeRef, typeAndAttributesForTypeRef, assertTypeRefGraph, typeRefIndex, - isTypeRef + isTypeRef, } from "./TypeGraph"; -import { TypeAttributes, emptyTypeAttributes, combineTypeAttributes } from "./attributes/TypeAttributes"; +import { type TypeAttributes} from "./attributes/TypeAttributes"; +import { emptyTypeAttributes, combineTypeAttributes } from "./attributes/TypeAttributes"; import { assert, panic, indentationString } from "./support/Support"; -import { TypeBuilder, StringTypeMapping } from "./TypeBuilder"; +import { type StringTypeMapping } from "./TypeBuilder"; +import { TypeBuilder } from "./TypeBuilder"; export interface TypeLookerUp { - lookupTypeRefs(typeRefs: TypeRef[], forwardingRef?: TypeRef): TypeRef | undefined; - reconstituteTypeRef(typeRef: TypeRef, attributes?: TypeAttributes, forwardingRef?: TypeRef): TypeRef; + lookupTypeRefs: (typeRefs: TypeRef[], forwardingRef?: TypeRef) => TypeRef | undefined; + reconstituteTypeRef: (typeRef: TypeRef, attributes?: TypeAttributes, forwardingRef?: TypeRef) => TypeRef; } export class TypeReconstituter { private _wasUsed = false; + private _typeRef: TypeRef | undefined = undefined; - constructor( + constructor ( private readonly _typeBuilder: TBuilder, private readonly _makeClassUnique: boolean, private readonly _typeAttributes: TypeAttributes, private readonly _forwardingRef: TypeRef | undefined, - private readonly _register: (tref: TypeRef) => void + private readonly _register: (tref: TypeRef) => void, ) {} - private builderForNewType(): TBuilder { + private builderForNewType (): TBuilder { assert(!this._wasUsed, "TypeReconstituter used more than once"); this._wasUsed = true; return this._typeBuilder; } - private builderForSetting(): TBuilder { + private builderForSetting (): TBuilder { assert(this._wasUsed && this._typeRef !== undefined, "Can't set type members before constructing a type"); return this._typeBuilder; } - getResult(): TypeRef { + getResult (): TypeRef { if (this._typeRef === undefined) { return panic("Type was not reconstituted"); } + return this._typeRef; } // FIXME: Do registration automatically. - private register(tref: TypeRef): void { + private register (tref: TypeRef): void { assert(this._typeRef === undefined, "Cannot register a type twice"); this._typeRef = tref; this._register(tref); } - private registerAndAddAttributes(tref: TypeRef): void { + private registerAndAddAttributes (tref: TypeRef): void { this._typeBuilder.addAttributes(tref, this._typeAttributes); this.register(tref); } - lookup(tref: TypeRef): TypeRef | undefined; - lookup(trefs: Iterable): ReadonlyArray | undefined; - lookup(trefs: TypeRef | Iterable): TypeRef | ReadonlyArray | undefined { + lookup (tref: TypeRef): TypeRef | undefined; + lookup (trefs: Iterable): readonly TypeRef[] | undefined; + lookup (trefs: TypeRef | Iterable): TypeRef | readonly TypeRef[] | undefined { assert(!this._wasUsed, "Cannot lookup constituents after building type"); if (isTypeRef(trefs)) { return this._typeBuilder.lookupTypeRefs([trefs], undefined, false); } else { const maybeRefs = Array.from(trefs).map(tref => this._typeBuilder.lookupTypeRefs([tref], undefined, false)); if (maybeRefs.some(tref => tref === undefined)) return undefined; - return maybeRefs as ReadonlyArray; + return maybeRefs as readonly TypeRef[]; } } @@ -85,12 +90,13 @@ export class TypeReconstituter { result.set(k, resultValues[i]); i += 1; } + return result; } - reconstitute(tref: TypeRef): TypeRef; - reconstitute(trefs: Iterable): ReadonlyArray; - reconstitute(trefs: TypeRef | Iterable): TypeRef | ReadonlyArray { + reconstitute (tref: TypeRef): TypeRef; + reconstitute (trefs: Iterable): readonly TypeRef[]; + reconstitute (trefs: TypeRef | Iterable): TypeRef | readonly TypeRef[] { assert(this._wasUsed, "Cannot reconstitute constituents before building type"); if (isTypeRef(trefs)) { return this._typeBuilder.reconstituteTypeRef(trefs); @@ -103,105 +109,106 @@ export class TypeReconstituter { return mapMap(trefs, tref => this._typeBuilder.reconstituteTypeRef(tref)); } - getPrimitiveType(kind: PrimitiveTypeKind): void { + getPrimitiveType (kind: PrimitiveTypeKind): void { this.register(this.builderForNewType().getPrimitiveType(kind, this._typeAttributes, this._forwardingRef)); } - getEnumType(cases: ReadonlySet): void { + getEnumType (cases: ReadonlySet): void { this.register(this.builderForNewType().getEnumType(this._typeAttributes, cases, this._forwardingRef)); } - getUniqueMapType(): void { + getUniqueMapType (): void { this.registerAndAddAttributes(this.builderForNewType().getUniqueMapType(this._forwardingRef)); } - getMapType(values: TypeRef): void { + getMapType (values: TypeRef): void { this.register(this.builderForNewType().getMapType(this._typeAttributes, values, this._forwardingRef)); } - getUniqueArrayType(): void { + getUniqueArrayType (): void { this.registerAndAddAttributes(this.builderForNewType().getUniqueArrayType(this._forwardingRef)); } - getArrayType(items: TypeRef): void { + getArrayType (items: TypeRef): void { this.register(this.builderForNewType().getArrayType(this._typeAttributes, items, this._forwardingRef)); } - setArrayItems(items: TypeRef): void { + setArrayItems (items: TypeRef): void { this.builderForSetting().setArrayItems(this.getResult(), items); } - makeClassProperty(tref: TypeRef, isOptional: boolean): ClassProperty { + makeClassProperty (tref: TypeRef, isOptional: boolean): ClassProperty { return this._typeBuilder.makeClassProperty(tref, isOptional); } - getObjectType(properties: ReadonlyMap, additionalProperties: TypeRef | undefined): void { + getObjectType (properties: ReadonlyMap, additionalProperties: TypeRef | undefined): void { this.register( this.builderForNewType().getUniqueObjectType( this._typeAttributes, properties, additionalProperties, - this._forwardingRef - ) + this._forwardingRef, + ), ); } - getUniqueObjectType( + getUniqueObjectType ( properties: ReadonlyMap | undefined, - additionalProperties: TypeRef | undefined + additionalProperties: TypeRef | undefined, ): void { this.register( this.builderForNewType().getUniqueObjectType( this._typeAttributes, properties, additionalProperties, - this._forwardingRef - ) + this._forwardingRef, + ), ); } - getClassType(properties: ReadonlyMap): void { + getClassType (properties: ReadonlyMap): void { if (this._makeClassUnique) { this.getUniqueClassType(false, properties); return; } + this.register(this.builderForNewType().getClassType(this._typeAttributes, properties, this._forwardingRef)); } - getUniqueClassType(isFixed: boolean, properties: ReadonlyMap | undefined): void { + getUniqueClassType (isFixed: boolean, properties: ReadonlyMap | undefined): void { this.register( - this.builderForNewType().getUniqueClassType(this._typeAttributes, isFixed, properties, this._forwardingRef) + this.builderForNewType().getUniqueClassType(this._typeAttributes, isFixed, properties, this._forwardingRef), ); } - setObjectProperties( + setObjectProperties ( properties: ReadonlyMap, - additionalProperties: TypeRef | undefined + additionalProperties: TypeRef | undefined, ): void { this.builderForSetting().setObjectProperties(this.getResult(), properties, additionalProperties); } - getUnionType(members: ReadonlySet): void { + getUnionType (members: ReadonlySet): void { this.register(this.builderForNewType().getUnionType(this._typeAttributes, members, this._forwardingRef)); } - getUniqueUnionType(): void { + getUniqueUnionType (): void { this.register( - this.builderForNewType().getUniqueUnionType(this._typeAttributes, undefined, this._forwardingRef) + this.builderForNewType().getUniqueUnionType(this._typeAttributes, undefined, this._forwardingRef), ); } - getIntersectionType(members: ReadonlySet): void { + getIntersectionType (members: ReadonlySet): void { this.register(this.builderForNewType().getIntersectionType(this._typeAttributes, members, this._forwardingRef)); } - getUniqueIntersectionType(members?: ReadonlySet): void { + getUniqueIntersectionType (members?: ReadonlySet): void { this.register( - this.builderForNewType().getUniqueIntersectionType(this._typeAttributes, members, this._forwardingRef) + this.builderForNewType().getUniqueIntersectionType(this._typeAttributes, members, this._forwardingRef), ); } - setSetOperationMembers(members: ReadonlySet): void { + setSetOperationMembers (members: ReadonlySet): void { this.builderForSetting().setSetOperationMembers(this.getResult(), members); } } @@ -210,14 +217,15 @@ export abstract class BaseGraphRewriteBuilder extends TypeBuilder implements Typ protected readonly reconstitutedTypes: Map = new Map(); private _lostTypeAttributes = false; + private _printIndent = 0; - constructor( + constructor ( readonly originalGraph: TypeGraph, stringTypeMapping: StringTypeMapping, alphabetizeProperties: boolean, graphHasProvenanceAttributes: boolean, - protected readonly debugPrint: boolean + protected readonly debugPrint: boolean, ) { super( originalGraph.serial + 1, @@ -225,13 +233,13 @@ export abstract class BaseGraphRewriteBuilder extends TypeBuilder implements Typ alphabetizeProperties, false, false, - graphHasProvenanceAttributes + graphHasProvenanceAttributes, ); } - withForwardingRef( + withForwardingRef ( maybeForwardingRef: TypeRef | undefined, - typeCreator: (forwardingRef: TypeRef) => TypeRef + typeCreator: (forwardingRef: TypeRef) => TypeRef, ): TypeRef { if (maybeForwardingRef !== undefined) { return typeCreator(maybeForwardingRef); @@ -243,62 +251,66 @@ export abstract class BaseGraphRewriteBuilder extends TypeBuilder implements Typ return actualRef; } - reconstituteType(t: Type, attributes?: TypeAttributes, forwardingRef?: TypeRef): TypeRef { + reconstituteType (t: Type, attributes?: TypeAttributes, forwardingRef?: TypeRef): TypeRef { return this.reconstituteTypeRef(t.typeRef, attributes, forwardingRef); } - abstract lookupTypeRefs(typeRefs: TypeRef[], forwardingRef?: TypeRef, replaceSet?: boolean): TypeRef | undefined; - protected abstract forceReconstituteTypeRef( + abstract lookupTypeRefs (typeRefs: TypeRef[], forwardingRef?: TypeRef, replaceSet?: boolean): TypeRef | undefined; + protected abstract forceReconstituteTypeRef ( originalRef: TypeRef, attributes?: TypeAttributes, maybeForwardingRef?: TypeRef ): TypeRef; - reconstituteTypeRef(originalRef: TypeRef, attributes?: TypeAttributes, maybeForwardingRef?: TypeRef): TypeRef { + reconstituteTypeRef (originalRef: TypeRef, attributes?: TypeAttributes, maybeForwardingRef?: TypeRef): TypeRef { const maybeRef = this.lookupTypeRefs([originalRef], maybeForwardingRef); if (maybeRef !== undefined) { if (attributes !== undefined) { this.addAttributes(maybeRef, attributes); } + return maybeRef; } + return this.forceReconstituteTypeRef(originalRef, attributes, maybeForwardingRef); } - reconstituteTypeAttributes(attributes: TypeAttributes): TypeAttributes { + reconstituteTypeAttributes (attributes: TypeAttributes): TypeAttributes { return mapMap(attributes, (v, a) => a.reconstitute(this, v)); } - protected assertTypeRefsToReconstitute(typeRefs: TypeRef[], forwardingRef?: TypeRef): void { + protected assertTypeRefsToReconstitute (typeRefs: TypeRef[], forwardingRef?: TypeRef): void { assert(typeRefs.length > 0, "Must have at least one type to reconstitute"); for (const originalRef of typeRefs) { assertTypeRefGraph(originalRef, this.originalGraph); } + if (forwardingRef !== undefined) { assertTypeRefGraph(forwardingRef, this.typeGraph); } } - protected changeDebugPrintIndent(delta: number): void { + protected changeDebugPrintIndent (delta: number): void { this._printIndent += delta; } - protected get debugPrintIndentation(): string { + protected get debugPrintIndentation (): string { return indentationString(this._printIndent); } - finish(): TypeGraph { + finish (): TypeGraph { for (const [name, t] of this.originalGraph.topLevels) { this.addTopLevel(name, this.reconstituteType(t)); } + return super.finish(); } - setLostTypeAttributes(): void { + setLostTypeAttributes (): void { this._lostTypeAttributes = true; } - get lostTypeAttributes(): boolean { + get lostTypeAttributes (): boolean { return this._lostTypeAttributes; } } @@ -306,20 +318,20 @@ export abstract class BaseGraphRewriteBuilder extends TypeBuilder implements Typ export class GraphRemapBuilder extends BaseGraphRewriteBuilder { private readonly _attributeSources: Map = new Map(); - constructor( + constructor ( originalGraph: TypeGraph, stringTypeMapping: StringTypeMapping, alphabetizeProperties: boolean, graphHasProvenanceAttributes: boolean, private readonly _map: ReadonlyMap, - debugPrintRemapping: boolean + debugPrintRemapping: boolean, ) { super( originalGraph, stringTypeMapping, alphabetizeProperties, graphHasProvenanceAttributes, - debugPrintRemapping + debugPrintRemapping, ); for (const [source, target] of _map) { @@ -328,26 +340,27 @@ export class GraphRemapBuilder extends BaseGraphRewriteBuilder { maybeSources = [target]; this._attributeSources.set(target, maybeSources); } + maybeSources.push(source); } } - protected makeIdentity(_maker: () => MaybeTypeIdentity): MaybeTypeIdentity { + protected makeIdentity (_maker: () => MaybeTypeIdentity): MaybeTypeIdentity { return undefined; } - private getMapTarget(tref: TypeRef): TypeRef { + private getMapTarget (tref: TypeRef): TypeRef { const maybeType = this._map.get(derefTypeRef(tref, this.originalGraph)); if (maybeType === undefined) return tref; assert(this._map.get(maybeType) === undefined, "We have a type that's remapped to a remapped type"); return maybeType.typeRef; } - protected addForwardingIntersection(_forwardingRef: TypeRef, _tref: TypeRef): TypeRef { + protected addForwardingIntersection (_forwardingRef: TypeRef, _tref: TypeRef): TypeRef { return panic("We can't add forwarding intersections when we're removing forwarding intersections"); } - lookupTypeRefs(typeRefs: TypeRef[], forwardingRef?: TypeRef): TypeRef | undefined { + lookupTypeRefs (typeRefs: TypeRef[], forwardingRef?: TypeRef): TypeRef | undefined { assert(forwardingRef === undefined, "We can't have a forwarding ref when we remap"); this.assertTypeRefsToReconstitute(typeRefs, forwardingRef); @@ -363,10 +376,10 @@ export class GraphRemapBuilder extends BaseGraphRewriteBuilder { return first; } - protected forceReconstituteTypeRef( + protected forceReconstituteTypeRef ( originalRef: TypeRef, attributes?: TypeAttributes, - maybeForwardingRef?: TypeRef + maybeForwardingRef?: TypeRef, ): TypeRef { originalRef = this.getMapTarget(originalRef); @@ -389,19 +402,21 @@ export class GraphRemapBuilder extends BaseGraphRewriteBuilder { if (attributes === undefined) { attributes = emptyTypeAttributes; } + if (attributeSources === undefined) { attributes = combineTypeAttributes( "union", attributes, - this.reconstituteTypeAttributes(originalAttributes) + this.reconstituteTypeAttributes(originalAttributes), ); } else { attributes = combineTypeAttributes( "union", attributes, - this.reconstituteTypeAttributes(combineTypeAttributesOfTypes("union", attributeSources)) + this.reconstituteTypeAttributes(combineTypeAttributesOfTypes("union", attributeSources)), ); } + const newAttributes = attributes; const reconstituter = new TypeReconstituter( @@ -415,7 +430,7 @@ export class GraphRemapBuilder extends BaseGraphRewriteBuilder { this.changeDebugPrintIndent(-1); console.log(`${this.debugPrintIndentation}reconstituted ${index} as ${typeRefIndex(tref)}`); } - } + }, ); originalType.reconstitute(reconstituter, this.canonicalOrder); return reconstituter.getResult(); @@ -425,9 +440,10 @@ export class GraphRemapBuilder extends BaseGraphRewriteBuilder { export class GraphRewriteBuilder extends BaseGraphRewriteBuilder { private readonly _setsToReplaceByMember: Map>; + private readonly _reconstitutedUnions: EqualityMap, TypeRef> = new EqualityMap(); - constructor( + constructor ( originalGraph: TypeGraph, stringTypeMapping: StringTypeMapping, alphabetizeProperties: boolean, @@ -438,14 +454,14 @@ export class GraphRewriteBuilder extends BaseGraphRewriteBuilder typesToReplace: ReadonlySet, builder: GraphRewriteBuilder, forwardingRef: TypeRef - ) => TypeRef + ) => TypeRef, ) { super( originalGraph, stringTypeMapping, alphabetizeProperties, graphHasProvenanceAttributes, - debugPrintReconstitution + debugPrintReconstitution, ); this._setsToReplaceByMember = new Map(); @@ -459,19 +475,19 @@ export class GraphRewriteBuilder extends BaseGraphRewriteBuilder } } - registerUnion(typeRefs: TypeRef[], reconstituted: TypeRef): void { + registerUnion (typeRefs: TypeRef[], reconstituted: TypeRef): void { const set = new Set(typeRefs); assert(!this._reconstitutedUnions.has(set), "Cannot register reconstituted set twice"); this._reconstitutedUnions.set(set, reconstituted); } - private replaceSet(typesToReplace: ReadonlySet, maybeForwardingRef: TypeRef | undefined): TypeRef { + private replaceSet (typesToReplace: ReadonlySet, maybeForwardingRef: TypeRef | undefined): TypeRef { return this.withForwardingRef(maybeForwardingRef, forwardingRef => { if (this.debugPrint) { console.log( `${this.debugPrintIndentation}replacing set ${Array.from(typesToReplace) .map(t => t.index.toString()) - .join(",")} as ${typeRefIndex(forwardingRef)}` + .join(",")} as ${typeRefIndex(forwardingRef)}`, ); this.changeDebugPrintIndent(1); } @@ -482,6 +498,7 @@ export class GraphRewriteBuilder extends BaseGraphRewriteBuilder this.reconstitutedTypes.set(index, forwardingRef); this._setsToReplaceByMember.delete(index); } + const result = this._replacer(typesToReplace, this, forwardingRef); assert(result === forwardingRef, "The forwarding ref got lost when replacing"); @@ -490,7 +507,7 @@ export class GraphRewriteBuilder extends BaseGraphRewriteBuilder console.log( `${this.debugPrintIndentation}replaced set ${Array.from(typesToReplace) .map(t => t.index.toString()) - .join(",")} as ${typeRefIndex(forwardingRef)}` + .join(",")} as ${typeRefIndex(forwardingRef)}`, ); } @@ -498,10 +515,10 @@ export class GraphRewriteBuilder extends BaseGraphRewriteBuilder }); } - protected forceReconstituteTypeRef( + protected forceReconstituteTypeRef ( originalRef: TypeRef, attributes?: TypeAttributes, - maybeForwardingRef?: TypeRef + maybeForwardingRef?: TypeRef, ): TypeRef { const [originalType, originalAttributes] = typeAndAttributesForTypeRef(originalRef, this.originalGraph); const index = typeRefIndex(originalRef); @@ -517,7 +534,7 @@ export class GraphRewriteBuilder extends BaseGraphRewriteBuilder attributes = combineTypeAttributes( "union", attributes, - this.reconstituteTypeAttributes(originalAttributes) + this.reconstituteTypeAttributes(originalAttributes), ); } @@ -558,7 +575,7 @@ export class GraphRewriteBuilder extends BaseGraphRewriteBuilder // If the union of these type refs have been, or are supposed to be, reconstituted to // one target type, return it. Otherwise return undefined. - lookupTypeRefs(typeRefs: TypeRef[], forwardingRef?: TypeRef, replaceSet = true): TypeRef | undefined { + lookupTypeRefs (typeRefs: TypeRef[], forwardingRef?: TypeRef, replaceSet = true): TypeRef | undefined { this.assertTypeRefsToReconstitute(typeRefs, forwardingRef); // Check whether we have already reconstituted them. That means ensuring @@ -572,6 +589,7 @@ export class GraphRewriteBuilder extends BaseGraphRewriteBuilder break; } } + if (allEqual) { return this.forwardIfNecessary(forwardingRef, maybeRef); } @@ -588,11 +606,13 @@ export class GraphRewriteBuilder extends BaseGraphRewriteBuilder if (maybeSet === undefined) { return undefined; } + for (let i = 1; i < typeRefs.length; i++) { if (this._setsToReplaceByMember.get(typeRefIndex(typeRefs[i])) !== maybeSet) { return undefined; } } + // Yes, this set is requested to be replaced, so do it. if (!replaceSet) return undefined; return this.replaceSet(maybeSet, forwardingRef); diff --git a/packages/quicktype-core/src/MakeTransformations.ts b/packages/quicktype-core/src/MakeTransformations.ts index 4e44d89f5..0b98b390f 100644 --- a/packages/quicktype-core/src/MakeTransformations.ts +++ b/packages/quicktype-core/src/MakeTransformations.ts @@ -1,21 +1,26 @@ import { setFilter, iterableFirst, mapMapEntries, withDefault, iterableSome, arraySortByInto } from "collection-utils"; -import { TypeGraph, TypeRef, typeRefIndex } from "./TypeGraph"; -import { TargetLanguage } from "./TargetLanguage"; +import { type TypeGraph, type TypeRef} from "./TypeGraph"; +import { typeRefIndex } from "./TypeGraph"; +import { type TargetLanguage } from "./TargetLanguage"; +import { + type TypeKind, + type Type, + type PrimitiveType, + type PrimitiveStringTypeKind, +} from "./Type"; import { UnionType, - TypeKind, EnumType, - Type, ArrayType, - PrimitiveType, isNumberTypeKind, isPrimitiveStringTypeKind, targetTypeKindForTransformedStringTypeKind, - PrimitiveStringTypeKind } from "./Type"; -import { GraphRewriteBuilder } from "./GraphRewriting"; +import { type GraphRewriteBuilder } from "./GraphRewriting"; import { defined, assert, panic } from "./support/Support"; +import { + type Transformer} from "./Transformers"; import { UnionInstantiationTransformer, DecodingChoiceTransformer, @@ -24,39 +29,40 @@ import { StringMatchTransformer, StringProducerTransformer, ChoiceTransformer, - Transformer, DecodingTransformer, ParseStringTransformer, ArrayDecodingTransformer, MinMaxLengthCheckTransformer, - MinMaxValueTransformer + MinMaxValueTransformer, } from "./Transformers"; -import { TypeAttributes, emptyTypeAttributes, combineTypeAttributes } from "./attributes/TypeAttributes"; +import { type TypeAttributes} from "./attributes/TypeAttributes"; +import { emptyTypeAttributes, combineTypeAttributes } from "./attributes/TypeAttributes"; import { StringTypes } from "./attributes/StringTypes"; -import { RunContext } from "./Run"; +import { type RunContext } from "./Run"; import { minMaxLengthForType, minMaxValueForType } from "./attributes/Constraints"; -function transformationAttributes( +function transformationAttributes ( graph: TypeGraph, reconstitutedTargetType: TypeRef, transformer: Transformer, - debugPrintTransformations: boolean + debugPrintTransformations: boolean, ): TypeAttributes { const transformation = new Transformation(graph, reconstitutedTargetType, transformer); if (debugPrintTransformations) { console.log(`transformation for ${typeRefIndex(reconstitutedTargetType)}:`); transformation.debugPrint(); - console.log(`reverse:`); + console.log("reverse:"); transformation.reverse.debugPrint(); } + return transformationTypeAttributeKind.makeAttributes(transformation); } -function makeEnumTransformer( +function makeEnumTransformer ( graph: TypeGraph, enumType: EnumType, stringType: TypeRef, - continuation?: Transformer + continuation?: Transformer, ): Transformer { const sortedCases = Array.from(enumType.cases).sort(); const caseTransformers = sortedCases.map( @@ -65,18 +71,18 @@ function makeEnumTransformer( graph, stringType, new StringProducerTransformer(graph, stringType, continuation, c), - c - ) + c, + ), ); return new ChoiceTransformer(graph, stringType, caseTransformers); } -function replaceUnion( +function replaceUnion ( union: UnionType, builder: GraphRewriteBuilder, forwardingRef: TypeRef, transformedTypes: Set, - debugPrintTransformations: boolean + debugPrintTransformations: boolean, ): TypeRef { const graph = builder.typeGraph; @@ -85,7 +91,7 @@ function replaceUnion( // Type attributes that we lost during reconstitution. let additionalAttributes = emptyTypeAttributes; - function reconstituteMember(t: Type): TypeRef { + function reconstituteMember (t: Type): TypeRef { // Special handling for some transformed string type kinds: The type in // the union must be the target type, so if one already exists, use that // one, otherwise make a new one. @@ -97,9 +103,11 @@ function replaceUnion( if (targetTypeMember !== undefined) { return builder.reconstituteType(targetTypeMember); } + return builder.getPrimitiveType(targetTypeKind); } } + return builder.reconstituteType(t); } @@ -115,16 +123,16 @@ function replaceUnion( ? builder.getUnionType(union.getAttributes(), reconstitutedMemberSet) : defined(iterableFirst(reconstitutedMemberSet)); - function memberForKind(kind: TypeKind) { + function memberForKind (kind: TypeKind) { return defined(reconstitutedMembersByKind.get(kind)); } - function consumer(memberTypeRef: TypeRef): Transformer | undefined { + function consumer (memberTypeRef: TypeRef): Transformer | undefined { if (!haveUnion) return undefined; return new UnionInstantiationTransformer(graph, memberTypeRef); } - function transformerForKind(kind: TypeKind) { + function transformerForKind (kind: TypeKind) { const member = union.findMember(kind); if (member === undefined) return undefined; const memberTypeRef = memberForKind(kind); @@ -132,20 +140,22 @@ function replaceUnion( } let maybeStringType: TypeRef | undefined = undefined; - function getStringType(): TypeRef { + function getStringType (): TypeRef { if (maybeStringType === undefined) { maybeStringType = builder.getStringType(emptyTypeAttributes, StringTypes.unrestricted); } + return maybeStringType; } - function transformerForStringType(t: Type): Transformer | undefined { + function transformerForStringType (t: Type): Transformer | undefined { const memberRef = memberForKind(t.kind); if (t.kind === "string") { const minMax = minMaxLengthForType(t); if (minMax === undefined) { return consumer(memberRef); } + const [min, max] = minMax; return new MinMaxLengthCheckTransformer(graph, getStringType(), consumer(memberRef), min, max); } else if (t instanceof EnumType && transformedTypes.has(t)) { @@ -169,8 +179,8 @@ function replaceUnion( new ChoiceTransformer( graph, getStringType(), - stringTypes.map(t => defined(transformerForStringType(t))) - ) + stringTypes.map(t => defined(transformerForStringType(t))), + ), ); } @@ -178,7 +188,7 @@ function replaceUnion( const transformerForMap = transformerForKind("map"); assert( transformerForClass === undefined || transformerForMap === undefined, - "Can't have both class and map in a transformed union" + "Can't have both class and map in a transformed union", ); const transformerForObject = transformerForClass !== undefined ? transformerForClass : transformerForMap; @@ -191,21 +201,21 @@ function replaceUnion( transformerForKind("bool"), transformerForString, transformerForKind("array"), - transformerForObject + transformerForObject, ); const attributes = transformationAttributes(graph, reconstitutedTargetType, transformer, debugPrintTransformations); return builder.getPrimitiveType( "any", combineTypeAttributes("union", attributes, additionalAttributes), - forwardingRef + forwardingRef, ); } -function replaceArray( +function replaceArray ( arrayType: ArrayType, builder: GraphRewriteBuilder, forwardingRef: TypeRef, - debugPrintTransformations: boolean + debugPrintTransformations: boolean, ): TypeRef { const anyType = builder.getPrimitiveType("any"); const anyArrayType = builder.getArrayType(emptyTypeAttributes, anyType); @@ -215,74 +225,74 @@ function replaceArray( anyArrayType, undefined, reconstitutedItems, - new DecodingTransformer(builder.typeGraph, anyType, undefined) + new DecodingTransformer(builder.typeGraph, anyType, undefined), ); const reconstitutedArray = builder.getArrayType( builder.reconstituteTypeAttributes(arrayType.getAttributes()), - reconstitutedItems + reconstitutedItems, ); const attributes = transformationAttributes( builder.typeGraph, reconstitutedArray, transformer, - debugPrintTransformations + debugPrintTransformations, ); return builder.getArrayType(attributes, anyType, forwardingRef); } -function replaceEnum( +function replaceEnum ( enumType: EnumType, builder: GraphRewriteBuilder, forwardingRef: TypeRef, - debugPrintTransformations: boolean + debugPrintTransformations: boolean, ): TypeRef { const stringType = builder.getStringType(emptyTypeAttributes, StringTypes.unrestricted); const transformer = new DecodingTransformer( builder.typeGraph, stringType, - makeEnumTransformer(builder.typeGraph, enumType, stringType) + makeEnumTransformer(builder.typeGraph, enumType, stringType), ); const reconstitutedEnum = builder.getEnumType(enumType.getAttributes(), enumType.cases); const attributes = transformationAttributes( builder.typeGraph, reconstitutedEnum, transformer, - debugPrintTransformations + debugPrintTransformations, ); return builder.getStringType(attributes, StringTypes.unrestricted, forwardingRef); } -function replaceNumber( +function replaceNumber ( t: PrimitiveType, builder: GraphRewriteBuilder, forwardingRef: TypeRef, - debugPrintTransformations: boolean + debugPrintTransformations: boolean, ): TypeRef { const stringType = builder.getStringType(emptyTypeAttributes, StringTypes.unrestricted); const [min, max] = defined(minMaxValueForType(t)); const transformer = new DecodingTransformer( builder.typeGraph, stringType, - new MinMaxValueTransformer(builder.typeGraph, stringType, undefined, min, max) + new MinMaxValueTransformer(builder.typeGraph, stringType, undefined, min, max), ); const reconstitutedAttributes = builder.reconstituteTypeAttributes(t.getAttributes()); const attributes = transformationAttributes( builder.typeGraph, builder.getPrimitiveType("double", reconstitutedAttributes, undefined), transformer, - debugPrintTransformations + debugPrintTransformations, ); return builder.getPrimitiveType("double", attributes, forwardingRef); } -function replaceString( +function replaceString ( t: PrimitiveType, builder: GraphRewriteBuilder, forwardingRef: TypeRef, - debugPrintTransformations: boolean + debugPrintTransformations: boolean, ): TypeRef { const [min, max] = defined(minMaxLengthForType(t)); const reconstitutedAttributes = builder.reconstituteTypeAttributes(t.getAttributes()); @@ -290,23 +300,23 @@ function replaceString( const transformer = new DecodingTransformer( builder.typeGraph, stringType, - new MinMaxLengthCheckTransformer(builder.typeGraph, stringType, undefined, min, max) + new MinMaxLengthCheckTransformer(builder.typeGraph, stringType, undefined, min, max), ); const attributes = transformationAttributes( builder.typeGraph, builder.getStringType(reconstitutedAttributes, undefined), transformer, - debugPrintTransformations + debugPrintTransformations, ); return builder.getStringType(attributes, StringTypes.unrestricted, forwardingRef); } -function replaceTransformedStringType( +function replaceTransformedStringType ( t: PrimitiveType, kind: PrimitiveStringTypeKind, builder: GraphRewriteBuilder, forwardingRef: TypeRef, - debugPrintTransformations: boolean + debugPrintTransformations: boolean, ): TypeRef { const reconstitutedAttributes = builder.reconstituteTypeAttributes(t.getAttributes()); const targetTypeKind = withDefault(targetTypeKindForTransformedStringTypeKind(kind), kind); @@ -314,18 +324,18 @@ function replaceTransformedStringType( const transformer = new DecodingTransformer( builder.typeGraph, stringType, - new ParseStringTransformer(builder.typeGraph, stringType, undefined) + new ParseStringTransformer(builder.typeGraph, stringType, undefined), ); const attributes = transformationAttributes( builder.typeGraph, builder.getPrimitiveType(targetTypeKind, reconstitutedAttributes), transformer, - debugPrintTransformations + debugPrintTransformations, ); return builder.getStringType(attributes, StringTypes.unrestricted, forwardingRef); } -export function makeTransformations(ctx: RunContext, graph: TypeGraph, targetLanguage: TargetLanguage): TypeGraph { +export function makeTransformations (ctx: RunContext, graph: TypeGraph, targetLanguage: TargetLanguage): TypeGraph { const transformedTypes = setFilter(graph.allTypesUnordered(), t => { if (targetLanguage.needsTransformerForType(t)) return true; if (!(t instanceof UnionType)) return false; @@ -334,36 +344,42 @@ export function makeTransformations(ctx: RunContext, graph: TypeGraph, targetLan return iterableSome(stringMembers, m => targetLanguage.needsTransformerForType(m)); }); - function replace( + function replace ( setOfOneUnion: ReadonlySet, builder: GraphRewriteBuilder, - forwardingRef: TypeRef + forwardingRef: TypeRef, ): TypeRef { const t = defined(iterableFirst(setOfOneUnion)); if (t instanceof UnionType) { return replaceUnion(t, builder, forwardingRef, transformedTypes, ctx.debugPrintTransformations); } + if (t instanceof ArrayType) { return replaceArray(t, builder, forwardingRef, ctx.debugPrintTransformations); } + if (t instanceof EnumType) { return replaceEnum(t, builder, forwardingRef, ctx.debugPrintTransformations); } + if (t.kind === "string") { return replaceString(t as PrimitiveType, builder, forwardingRef, ctx.debugPrintTransformations); } + if (isNumberTypeKind(t.kind)) { return replaceNumber(t as PrimitiveType, builder, forwardingRef, ctx.debugPrintTransformations); } + if (isPrimitiveStringTypeKind(t.kind)) { return replaceTransformedStringType( t as PrimitiveType, t.kind, builder, forwardingRef, - ctx.debugPrintTransformations + ctx.debugPrintTransformations, ); } + return panic(`Cannot make transformation for type ${t.kind}`); } @@ -374,6 +390,6 @@ export function makeTransformations(ctx: RunContext, graph: TypeGraph, targetLan false, groups, ctx.debugPrintReconstitution, - replace + replace, ); } diff --git a/packages/quicktype-core/src/MarkovChain.ts b/packages/quicktype-core/src/MarkovChain.ts index 1c1b730a6..85bd62b4d 100644 --- a/packages/quicktype-core/src/MarkovChain.ts +++ b/packages/quicktype-core/src/MarkovChain.ts @@ -3,25 +3,26 @@ import { encodedMarkovChain } from "./EncodedMarkovChain"; // This must be null, not undefined, because we read it from JSON. export type SubTrie = number | null | Trie; -export type Trie = { - count: number; +export interface Trie { arr: SubTrie[]; -}; + count: number; +} -export type MarkovChain = { - trie: Trie; +export interface MarkovChain { depth: number; -}; + trie: Trie; +} -function makeTrie(): Trie { +function makeTrie (): Trie { const arr: SubTrie[] = []; for (let i = 0; i < 128; i++) { arr.push(null); } + return { count: 0, arr }; } -function lookup(t: Trie, seq: string, i: number): Trie | number | undefined { +function lookup (t: Trie, seq: string, i: number): Trie | number | undefined { if (i >= seq.length) { return t; } @@ -35,6 +36,7 @@ function lookup(t: Trie, seq: string, i: number): Trie | number | undefined { if (n === null) { return undefined; } + if (typeof n === "object") { return lookup(n, seq, i + 1); } else { @@ -42,7 +44,7 @@ function lookup(t: Trie, seq: string, i: number): Trie | number | undefined { } } -function increment(t: Trie, seq: string, i: number): void { +function increment (t: Trie, seq: string, i: number): void { let first = seq.charCodeAt(i); if (first >= 128) { first = 0; @@ -52,12 +54,14 @@ function increment(t: Trie, seq: string, i: number): void { if (typeof t !== "object") { return panic("Malformed trie"); } + let n = t.arr[first]; if (n === null) { n = 0; } else if (typeof n === "object") { return panic("Malformed trie"); } + t.arr[first] = n + 1; t.count += 1; return; @@ -67,13 +71,15 @@ function increment(t: Trie, seq: string, i: number): void { if (st === null) { t.arr[first] = st = makeTrie(); } + if (typeof st !== "object") { return panic("Malformed trie"); } - return increment(st, seq, i + 1); + + increment(st, seq, i + 1); } -export function train(lines: string[], depth: number): MarkovChain { +export function train (lines: string[], depth: number): MarkovChain { const trie = makeTrie(); for (const l of lines) { for (let i = depth; i <= l.length; i++) { @@ -84,15 +90,16 @@ export function train(lines: string[], depth: number): MarkovChain { return { trie, depth }; } -export function load(): MarkovChain { +export function load (): MarkovChain { return JSON.parse(inflateBase64(encodedMarkovChain)); } -export function evaluateFull(mc: MarkovChain, word: string): [number, number[]] { +export function evaluateFull (mc: MarkovChain, word: string): [number, number[]] { const { trie, depth } = mc; if (word.length < depth) { return [1, []]; } + let p = 1; const scores: number[] = []; for (let i = depth; i <= word.length; i++) { @@ -100,38 +107,44 @@ export function evaluateFull(mc: MarkovChain, word: string): [number, number[]] if (typeof cp === "object") { return panic("Did we mess up the depth?"); } + if (cp === undefined) { cp = 0.0001; } + scores.push(cp); p = p * cp; } + return [Math.pow(p, 1 / (word.length - depth + 1)), scores]; } -export function evaluate(mc: MarkovChain, word: string): number { +export function evaluate (mc: MarkovChain, word: string): number { return evaluateFull(mc, word)[0]; } -function randomInt(lower: number, upper: number) { +function randomInt (lower: number, upper: number) { const range = upper - lower; return lower + Math.floor(Math.random() * range); } -export function generate(mc: MarkovChain, state: string, unseenWeight: number): string { +export function generate (mc: MarkovChain, state: string, unseenWeight: number): string { assert(state.length === mc.depth - 1, "State and chain length don't match up"); const t = lookup(mc.trie, state, 0); if (typeof t === "number") { return panic("Wrong depth?"); } + if (t === undefined) { return String.fromCharCode(randomInt(32, 127)); } - const counts = t.arr.map((x, i) => (x === null ? (i === 0 ? 0 : unseenWeight) : (x as number))); + + const counts = t.arr.map((x, i) => x === null ? i === 0 ? 0 : unseenWeight : (x as number)); let n = 0; for (const c of counts) { n += c; } + const r = randomInt(0, n); let sum = 0; for (let i = 0; i < counts.length; i++) { @@ -140,14 +153,15 @@ export function generate(mc: MarkovChain, state: string, unseenWeight: number): return String.fromCharCode(i); } } + return panic("We screwed up bookkeeping, or randomInt"); } -function testWord(mc: MarkovChain, word: string): void { +function testWord (mc: MarkovChain, word: string): void { console.log(`"${word}": ${evaluate(mc, word)}`); } -export function test(): void { +export function test (): void { const mc = load(); testWord(mc, "url"); @@ -171,6 +185,6 @@ export function test(): void { testWord( mc, - "\ud83d\udebe \ud83c\udd92 \ud83c\udd93 \ud83c\udd95 \ud83c\udd96 \ud83c\udd97 \ud83c\udd99 \ud83c\udfe7" + "\ud83d\udebe \ud83c\udd92 \ud83c\udd93 \ud83c\udd95 \ud83c\udd96 \ud83c\udd97 \ud83c\udd99 \ud83c\udfe7", ); } diff --git a/packages/quicktype-core/src/Messages.ts b/packages/quicktype-core/src/Messages.ts index d740163ec..082c3ce40 100644 --- a/packages/quicktype-core/src/Messages.ts +++ b/packages/quicktype-core/src/Messages.ts @@ -1,85 +1,85 @@ -import { StringMap } from "./support/Support"; -import { Ref } from "./input/JSONSchemaInput"; +import { type StringMap } from "./support/Support"; +import { type Ref } from "./input/JSONSchemaInput"; export type ErrorProperties = - | { kind: "InternalError"; properties: { message: string } } + | { kind: "InternalError", properties: { message: string, }, } // Misc | { - kind: "MiscJSONParseError"; - properties: { description: string; address: string; message: string }; - } - | { kind: "MiscReadError"; properties: { fileOrURL: string; message: string } } - | { kind: "MiscUnicodeHighSurrogateWithoutLowSurrogate"; properties: {} } - | { kind: "MiscInvalidMinMaxConstraint"; properties: { min: number; max: number } } + kind: "MiscJSONParseError", + properties: { address: string, description: string, message: string, }, + } + | { kind: "MiscReadError", properties: { fileOrURL: string, message: string, }, } + | { kind: "MiscUnicodeHighSurrogateWithoutLowSurrogate", properties: {}, } + | { kind: "MiscInvalidMinMaxConstraint", properties: { max: number, min: number, }, } // Inference - | { kind: "InferenceJSONReferenceNotRooted"; properties: { reference: string } } - | { kind: "InferenceJSONReferenceToUnion"; properties: { reference: string } } - | { kind: "InferenceJSONReferenceWrongProperty"; properties: { reference: string } } - | { kind: "InferenceJSONReferenceInvalidArrayIndex"; properties: { reference: string } } + | { kind: "InferenceJSONReferenceNotRooted", properties: { reference: string, }, } + | { kind: "InferenceJSONReferenceToUnion", properties: { reference: string, }, } + | { kind: "InferenceJSONReferenceWrongProperty", properties: { reference: string, }, } + | { kind: "InferenceJSONReferenceInvalidArrayIndex", properties: { reference: string, }, } // JSON Schema input - | { kind: "SchemaArrayIsInvalidSchema"; properties: { ref: Ref } } - | { kind: "SchemaNullIsInvalidSchema"; properties: { ref: Ref } } - | { kind: "SchemaRefMustBeString"; properties: { actual: string; ref: Ref } } - | { kind: "SchemaAdditionalTypesForbidRequired"; properties: { ref: Ref } } - | { kind: "SchemaNoTypeSpecified"; properties: { ref: Ref } } - | { kind: "SchemaInvalidType"; properties: { type: string; ref: Ref } } - | { kind: "SchemaFalseNotSupported"; properties: { ref: Ref } } - | { kind: "SchemaInvalidJSONSchemaType"; properties: { type: string; ref: Ref } } - | { kind: "SchemaRequiredMustBeStringOrStringArray"; properties: { actual: any; ref: Ref } } - | { kind: "SchemaRequiredElementMustBeString"; properties: { element: any; ref: Ref } } - | { kind: "SchemaTypeMustBeStringOrStringArray"; properties: { actual: any } } - | { kind: "SchemaTypeElementMustBeString"; properties: { element: any; ref: Ref } } - | { kind: "SchemaArrayItemsMustBeStringOrArray"; properties: { actual: any; ref: Ref } } - | { kind: "SchemaIDMustHaveAddress"; properties: { id: string; ref: Ref } } - | { kind: "SchemaWrongAccessorEntryArrayLength"; properties: { operation: string; ref: Ref } } + | { kind: "SchemaArrayIsInvalidSchema", properties: { ref: Ref, }, } + | { kind: "SchemaNullIsInvalidSchema", properties: { ref: Ref, }, } + | { kind: "SchemaRefMustBeString", properties: { actual: string, ref: Ref, }, } + | { kind: "SchemaAdditionalTypesForbidRequired", properties: { ref: Ref, }, } + | { kind: "SchemaNoTypeSpecified", properties: { ref: Ref, }, } + | { kind: "SchemaInvalidType", properties: { ref: Ref, type: string, }, } + | { kind: "SchemaFalseNotSupported", properties: { ref: Ref, }, } + | { kind: "SchemaInvalidJSONSchemaType", properties: { ref: Ref, type: string, }, } + | { kind: "SchemaRequiredMustBeStringOrStringArray", properties: { actual: any, ref: Ref, }, } + | { kind: "SchemaRequiredElementMustBeString", properties: { element: any, ref: Ref, }, } + | { kind: "SchemaTypeMustBeStringOrStringArray", properties: { actual: any, }, } + | { kind: "SchemaTypeElementMustBeString", properties: { element: any, ref: Ref, }, } + | { kind: "SchemaArrayItemsMustBeStringOrArray", properties: { actual: any, ref: Ref, }, } + | { kind: "SchemaIDMustHaveAddress", properties: { id: string, ref: Ref, }, } + | { kind: "SchemaWrongAccessorEntryArrayLength", properties: { operation: string, ref: Ref, }, } | { - kind: "SchemaSetOperationCasesIsNotArray"; - properties: { operation: string; cases: any; ref: Ref }; - } - | { kind: "SchemaMoreThanOneUnionMemberName"; properties: { names: string[] } } - | { kind: "SchemaCannotGetTypesFromBoolean"; properties: { ref: string } } - | { kind: "SchemaCannotIndexArrayWithNonNumber"; properties: { actual: string; ref: Ref } } - | { kind: "SchemaIndexNotInArray"; properties: { index: number; ref: Ref } } - | { kind: "SchemaKeyNotInObject"; properties: { key: string; ref: Ref } } - | { kind: "SchemaFetchError"; properties: { address: string; base: Ref } } - | { kind: "SchemaFetchErrorTopLevel"; properties: { address: string } } - | { kind: "SchemaFetchErrorAdditional"; properties: { address: string } } + kind: "SchemaSetOperationCasesIsNotArray", + properties: { cases: any, operation: string, ref: Ref, }, + } + | { kind: "SchemaMoreThanOneUnionMemberName", properties: { names: string[], }, } + | { kind: "SchemaCannotGetTypesFromBoolean", properties: { ref: string, }, } + | { kind: "SchemaCannotIndexArrayWithNonNumber", properties: { actual: string, ref: Ref, }, } + | { kind: "SchemaIndexNotInArray", properties: { index: number, ref: Ref, }, } + | { kind: "SchemaKeyNotInObject", properties: { key: string, ref: Ref, }, } + | { kind: "SchemaFetchError", properties: { address: string, base: Ref, }, } + | { kind: "SchemaFetchErrorTopLevel", properties: { address: string, }, } + | { kind: "SchemaFetchErrorAdditional", properties: { address: string, }, } // GraphQL input - | { kind: "GraphQLNoQueriesDefined"; properties: {} } + | { kind: "GraphQLNoQueriesDefined", properties: {}, } // Driver - | { kind: "DriverUnknownSourceLanguage"; properties: { lang: string } } - | { kind: "DriverUnknownOutputLanguage"; properties: { lang: string } } - | { kind: "DriverMoreThanOneInputGiven"; properties: { topLevel: string } } - | { kind: "DriverCannotInferNameForSchema"; properties: { uri: string } } - | { kind: "DriverNoGraphQLQueryGiven"; properties: {} } - | { kind: "DriverNoGraphQLSchemaInDir"; properties: { dir: string } } - | { kind: "DriverMoreThanOneGraphQLSchemaInDir"; properties: { dir: string } } - | { kind: "DriverSourceLangMustBeGraphQL"; properties: {} } - | { kind: "DriverGraphQLSchemaNeeded"; properties: {} } - | { kind: "DriverInputFileDoesNotExist"; properties: { filename: string } } - | { kind: "DriverCannotMixJSONWithOtherSamples"; properties: { dir: string } } - | { kind: "DriverCannotMixNonJSONInputs"; properties: { dir: string } } - | { kind: "DriverUnknownDebugOption"; properties: { option: string } } - | { kind: "DriverNoLanguageOrExtension"; properties: {} } - | { kind: "DriverCLIOptionParsingFailed"; properties: { message: string } } + | { kind: "DriverUnknownSourceLanguage", properties: { lang: string, }, } + | { kind: "DriverUnknownOutputLanguage", properties: { lang: string, }, } + | { kind: "DriverMoreThanOneInputGiven", properties: { topLevel: string, }, } + | { kind: "DriverCannotInferNameForSchema", properties: { uri: string, }, } + | { kind: "DriverNoGraphQLQueryGiven", properties: {}, } + | { kind: "DriverNoGraphQLSchemaInDir", properties: { dir: string, }, } + | { kind: "DriverMoreThanOneGraphQLSchemaInDir", properties: { dir: string, }, } + | { kind: "DriverSourceLangMustBeGraphQL", properties: {}, } + | { kind: "DriverGraphQLSchemaNeeded", properties: {}, } + | { kind: "DriverInputFileDoesNotExist", properties: { filename: string, }, } + | { kind: "DriverCannotMixJSONWithOtherSamples", properties: { dir: string, }, } + | { kind: "DriverCannotMixNonJSONInputs", properties: { dir: string, }, } + | { kind: "DriverUnknownDebugOption", properties: { option: string, }, } + | { kind: "DriverNoLanguageOrExtension", properties: {}, } + | { kind: "DriverCLIOptionParsingFailed", properties: { message: string, }, } // IR - | { kind: "IRNoForwardDeclarableTypeInCycle"; properties: {} } - | { kind: "IRTypeAttributesNotPropagated"; properties: { count: number; indexes: number[] } } - | { kind: "IRNoEmptyUnions"; properties: {} } + | { kind: "IRNoForwardDeclarableTypeInCycle", properties: {}, } + | { kind: "IRTypeAttributesNotPropagated", properties: { count: number, indexes: number[], }, } + | { kind: "IRNoEmptyUnions", properties: {}, } // Rendering - | { kind: "RendererUnknownOptionValue"; properties: { value: string; name: string } } + | { kind: "RendererUnknownOptionValue", properties: { name: string, value: string, }, } // TypeScript input - | { kind: "TypeScriptCompilerError"; properties: { message: string } }; + | { kind: "TypeScriptCompilerError", properties: { message: string, }, }; -export type ErrorKinds = ErrorProperties extends { kind: infer K } ? K : never; +export type ErrorKinds = ErrorProperties extends { kind: infer K, } ? K : never; type ErrorMessages = { readonly [K in ErrorKinds]: string }; @@ -106,7 +106,7 @@ const errorMessages: ErrorMessages = { "Can't have non-specified required properties but forbidden additionalTypes at ${ref}", SchemaNoTypeSpecified: "JSON Schema must specify at least one type at ${ref}", SchemaInvalidType: "Invalid type ${type} in JSON Schema at ${ref}", - SchemaFalseNotSupported: 'Schema "false" is not supported at ${ref}', + SchemaFalseNotSupported: "Schema \"false\" is not supported at ${ref}", SchemaInvalidJSONSchemaType: "Value of type ${type} is not valid JSON Schema at ${ref}", SchemaRequiredMustBeStringOrStringArray: "`required` must be string or array of strings, but is ${actual} at ${ref}", @@ -161,25 +161,25 @@ const errorMessages: ErrorMessages = { RendererUnknownOptionValue: "Unknown value ${value} for option ${name}", // TypeScript input - TypeScriptCompilerError: "TypeScript error: ${message}" + TypeScriptCompilerError: "TypeScript error: ${message}", }; -export type ErrorPropertiesForName = Extract extends { properties: infer P } +export type ErrorPropertiesForName = Extract extends { properties: infer P, } ? P : never; export class QuickTypeError extends Error { - constructor( + constructor ( readonly errorMessage: string, readonly messageName: string, userMessage: string, - readonly properties: StringMap + readonly properties: StringMap, ) { super(userMessage); } } -export function messageError(kind: N, properties: ErrorPropertiesForName): never { +export function messageError (kind: N, properties: ErrorPropertiesForName): never { const message = errorMessages[kind]; let userMessage: string = message; const propertiesMap = properties as StringMap; @@ -193,16 +193,17 @@ export function messageError(kind: N, properties: ErrorPro } else if (typeof value !== "string") { value = JSON.stringify(value); } + userMessage = userMessage.replace("${" + name + "}", value); } throw new QuickTypeError(message, kind, userMessage, propertiesMap); } -export function messageAssert( +export function messageAssert ( assertion: boolean, kind: N, - properties: ErrorPropertiesForName + properties: ErrorPropertiesForName, ): void { if (assertion) return; return messageError(kind, properties); diff --git a/packages/quicktype-core/src/Naming.ts b/packages/quicktype-core/src/Naming.ts index a8508ca51..819163748 100644 --- a/packages/quicktype-core/src/Naming.ts +++ b/packages/quicktype-core/src/Naming.ts @@ -10,22 +10,25 @@ import { setFilterMap, iterableFirst, iterableEvery, - mapMergeInto + mapMergeInto, } from "collection-utils"; import { defined, assert, panic } from "./support/Support"; export class Namespace { readonly forbiddenNamespaces: ReadonlySet; + readonly additionalForbidden: ReadonlySet; + private readonly _children = new Set(); + private readonly _members = new Set(); - constructor( + constructor ( _name: string, parent: Namespace | undefined, forbiddenNamespaces: Iterable, - additionalForbidden: Iterable + additionalForbidden: Iterable, ) { this.forbiddenNamespaces = new Set(forbiddenNamespaces); this.additionalForbidden = new Set(additionalForbidden); @@ -34,19 +37,19 @@ export class Namespace { } } - private addChild(child: Namespace): void { + private addChild (child: Namespace): void { this._children.add(child); } - get children(): ReadonlySet { + get children (): ReadonlySet { return this._children; } - get members(): ReadonlySet { + get members (): ReadonlySet { return this._members; } - get forbiddenNameds(): ReadonlySet { + get forbiddenNameds (): ReadonlySet { // FIXME: cache return setUnion(this.additionalForbidden, ...Array.from(this.forbiddenNamespaces).map(ns => ns.members)); } @@ -77,16 +80,16 @@ export type NameStyle = (rawName: string) => string; export class Namer { private readonly _prefixes: ReadonlySet; - constructor(readonly name: string, readonly nameStyle: NameStyle, prefixes: string[]) { + constructor (readonly name: string, readonly nameStyle: NameStyle, prefixes: string[]) { this._prefixes = new Set(prefixes); } // The namesIterable comes directly out of the context and will // be modified if we assign - assignNames( + assignNames ( names: ReadonlyMap, forbiddenNamesIterable: Iterable, - namesToAssignIterable: Iterable + namesToAssignIterable: Iterable, ): ReadonlyMap { const forbiddenNames = new Set(forbiddenNamesIterable); const namesToAssign = Array.from(namesToAssignIterable); @@ -105,7 +108,7 @@ export class Namer { proposedNames, proposed => !forbiddenNames.has(namingFunction.nameStyle(proposed)) && - namesToAssign.every(n => n === name || !n.proposeUnstyledNames(names).has(proposed)) + namesToAssign.every(n => n === name || !n.proposeUnstyledNames(names).has(proposed)), ); if (maybeUniqueName !== undefined) { const styledName = namingFunction.nameStyle(maybeUniqueName); @@ -135,6 +138,7 @@ export class Namer { nameToTry = `${originalName}_${suffixNumber.toString()}`; suffixNumber++; } + const styledName = name.namingFunction.nameStyle(nameToTry); const assigned = name.nameAssignments(forbiddenNames, styledName); if (assigned === null) continue; @@ -161,10 +165,10 @@ const funPrefixes = [ "Magenta", "Frisky", "Mischievous", - "Braggadocious" + "Braggadocious", ]; -export function funPrefixNamer(name: string, nameStyle: NameStyle): Namer { +export function funPrefixNamer (name: string, nameStyle: NameStyle): Namer { return new Namer(name, nameStyle, funPrefixes); } @@ -177,30 +181,30 @@ export abstract class Name { private readonly _associates = new Set(); // If a Named is fixed, the namingFunction is undefined. - constructor(private readonly _namingFunction: Namer | undefined, readonly order: number) {} + constructor (private readonly _namingFunction: Namer | undefined, readonly order: number) {} - addAssociate(associate: AssociatedName): void { + addAssociate (associate: AssociatedName): void { this._associates.add(associate); } - abstract get dependencies(): ReadonlyArray; + abstract get dependencies (): readonly Name[]; - isFixed(): this is FixedName { + isFixed (): this is FixedName { return this instanceof FixedName; } - get namingFunction(): Namer { + get namingFunction (): Namer { return defined(this._namingFunction); } // Must return at least one proposal. The proposals are considered in order. - abstract proposeUnstyledNames(names: ReadonlyMap): ReadonlySet; + abstract proposeUnstyledNames (names: ReadonlyMap): ReadonlySet; - firstProposedName(names: ReadonlyMap): string { + firstProposedName (names: ReadonlyMap): string { return defined(iterableFirst(this.proposeUnstyledNames(names))); } - nameAssignments(forbiddenNames: ReadonlySet, assignedName: string): ReadonlyMap | null { + nameAssignments (forbiddenNames: ReadonlySet, assignedName: string): ReadonlyMap | null { if (forbiddenNames.has(assignedName)) return null; const assignments = new Map([[this, assignedName]]); for (const an of this._associates) { @@ -208,31 +212,33 @@ export abstract class Name { if (forbiddenNames.has(associatedAssignedName)) { return null; } + assignments.set(an, associatedAssignedName); } + return assignments; } } // FIXME: FixedNameds should optionally be user-configurable export class FixedName extends Name { - constructor(private readonly _fixedName: string) { + constructor (private readonly _fixedName: string) { super(undefined, 0); } - get dependencies(): ReadonlyArray { + get dependencies (): readonly Name[] { return []; } - addAssociate(_: AssociatedName): never { + addAssociate (_: AssociatedName): never { return panic("Cannot add associates to fixed names"); } - get fixedName(): string { + get fixedName (): string { return this._fixedName; } - proposeUnstyledNames(_?: ReadonlyMap): ReadonlySet { + proposeUnstyledNames (_?: ReadonlyMap): ReadonlySet { return panic("Only fixedName should be called on FixedName."); } } @@ -240,30 +246,30 @@ export class FixedName extends Name { export class SimpleName extends Name { private readonly _unstyledNames: ReadonlySet; - constructor(unstyledNames: Iterable, namingFunction: Namer, order: number) { + constructor (unstyledNames: Iterable, namingFunction: Namer, order: number) { super(namingFunction, order); this._unstyledNames = new Set(unstyledNames); } - get dependencies(): ReadonlyArray { + get dependencies (): readonly Name[] { return []; } - proposeUnstyledNames(_?: ReadonlyMap): ReadonlySet { + proposeUnstyledNames (_?: ReadonlyMap): ReadonlySet { return this._unstyledNames; } } export class AssociatedName extends Name { - constructor(private readonly _sponsor: Name, order: number, readonly getName: (sponsorName: string) => string) { + constructor (private readonly _sponsor: Name, order: number, readonly getName: (sponsorName: string) => string) { super(undefined, order); } - get dependencies(): ReadonlyArray { + get dependencies (): readonly Name[] { return [this._sponsor]; } - proposeUnstyledNames(_?: ReadonlyMap): never { + proposeUnstyledNames (_?: ReadonlyMap): never { return panic("AssociatedName must be assigned via its sponsor"); } } @@ -271,10 +277,10 @@ export class AssociatedName extends Name { export class DependencyName extends Name { private readonly _dependencies: ReadonlySet; - constructor( + constructor ( namingFunction: Namer | undefined, order: number, - private readonly _proposeUnstyledName: (lookup: (n: Name) => string) => string + private readonly _proposeUnstyledName: (lookup: (n: Name) => string) => string, ) { super(namingFunction, order); const dependencies: Name[] = []; @@ -285,42 +291,45 @@ export class DependencyName extends Name { this._dependencies = new Set(dependencies); } - get dependencies(): ReadonlyArray { + get dependencies (): readonly Name[] { return Array.from(this._dependencies); } - proposeUnstyledNames(names: ReadonlyMap): ReadonlySet { + proposeUnstyledNames (names: ReadonlyMap): ReadonlySet { return new Set([ this._proposeUnstyledName(n => { assert(this._dependencies.has(n), "DependencyName proposer is not pure"); return defined(names.get(n)); - }) + }), ]); } } -export function keywordNamespace(name: string, keywords: string[]) { +export function keywordNamespace (name: string, keywords: string[]) { const ns = new Namespace(name, undefined, [], []); for (const kw of keywords) { ns.add(new FixedName(kw)); } + return ns; } -function allNamespacesRecursively(namespaces: Iterable): ReadonlySet { +function allNamespacesRecursively (namespaces: Iterable): ReadonlySet { return setUnion(namespaces, ...Array.from(setMap(namespaces, ns => allNamespacesRecursively(ns.children)))); } class NamingContext { private readonly _names: Map = new Map(); + private readonly _namedsForName: Map> = new Map(); + readonly namespaces: ReadonlySet; - constructor(rootNamespaces: Iterable) { + constructor (rootNamespaces: Iterable) { this.namespaces = allNamespacesRecursively(rootNamespaces); } - get names(): ReadonlyMap { + get names (): ReadonlyMap { return this._names; } @@ -329,7 +338,7 @@ class NamingContext { return named.dependencies.every((n: Name) => this._names.has(n)); }; - areForbiddensFullyNamed(namespace: Namespace): boolean { + areForbiddensFullyNamed (namespace: Namespace): boolean { return iterableEvery(namespace.forbiddenNameds, n => this._names.has(n)); } @@ -343,6 +352,7 @@ class NamingContext { return true; } } + return false; }; @@ -355,12 +365,13 @@ class NamingContext { namedsForName = new Set(); this._namedsForName.set(name, namedsForName); } + namedsForName.add(named); }; } // Naming algorithm -export function assignNames(rootNamespaces: Iterable): ReadonlyMap { +export function assignNames (rootNamespaces: Iterable): ReadonlyMap { const ctx = new NamingContext(rootNamespaces); // Assign all fixed names. @@ -404,7 +415,7 @@ export function assignNames(rootNamespaces: Iterable): ReadonlyMap n.namingFunction); for (const [namer, namedsForNamingFunction] of byNamingFunction) { const byProposed = setGroupBy(namedsForNamingFunction, n => - n.namingFunction.nameStyle(n.firstProposedName(ctx.names)) + n.namingFunction.nameStyle(n.firstProposedName(ctx.names)), ); for (const [, nameds] of byProposed) { // 3. Use each set's naming function to name its members. @@ -413,6 +424,7 @@ export function assignNames(rootNamespaces: Iterable): ReadonlyMap; +export interface RenderResult { names: ReadonlyMap; -}; + sources: ReadonlyMap; +} export type BlankLinePosition = "none" | "interposing" | "leading" | "leading-and-interposing"; export type BlankLineConfig = BlankLinePosition | [BlankLinePosition, number]; -function getBlankLineConfig(cfg: BlankLineConfig): { position: BlankLinePosition; count: number } { +function getBlankLineConfig (cfg: BlankLineConfig): { count: number, position: BlankLinePosition, } { if (Array.isArray(cfg)) { return { position: cfg[0], count: cfg[1] }; } + return { position: cfg, count: 1 }; } -function lineIndentation(line: string): { indent: number; text: string | null } { +function lineIndentation (line: string): { indent: number, text: string | null, } { const len = line.length; let indent = 0; for (let i = 0; i < len; i++) { @@ -36,102 +40,112 @@ function lineIndentation(line: string): { indent: number; text: string | null } return { indent, text: line.substring(i) }; } } + return { indent: 0, text: null }; } -export type RenderContext = { - typeGraph: TypeGraph; +export interface RenderContext { leadingComments?: Comment[]; -}; + typeGraph: TypeGraph; +} export type ForEachPosition = "first" | "last" | "middle" | "only"; class EmitContext { private _lastNewline?: NewlineSource; - // @ts-ignore: Initialized in startEmit, which is called from the constructor - private _emitted: Sourcelike[]; - // @ts-ignore: Initialized in startEmit, which is called from the constructor - private _currentEmitTarget: Sourcelike[]; - // @ts-ignore: Initialized in startEmit, which is called from the constructor + + // @ts-expect-error: Initialized in startEmit, which is called from the constructor + private readonly _emitted: Sourcelike[]; + + // @ts-expect-error: Initialized in startEmit, which is called from the constructor + private readonly _currentEmitTarget: Sourcelike[]; + + // @ts-expect-error: Initialized in startEmit, which is called from the constructor private _numBlankLinesNeeded: number; - // @ts-ignore: Initialized in startEmit, which is called from the constructor + + // @ts-expect-error: Initialized in startEmit, which is called from the constructor private _preventBlankLine: boolean; - constructor() { + constructor () { this._currentEmitTarget = this._emitted = []; this._numBlankLinesNeeded = 0; this._preventBlankLine = true; // no blank lines at start of file } - get isEmpty(): boolean { + get isEmpty (): boolean { return this._emitted.length === 0; } - get isNested(): boolean { + get isNested (): boolean { return this._emitted !== this._currentEmitTarget; } - get source(): Sourcelike[] { + get source (): Sourcelike[] { return this._emitted; } - private pushItem(item: Sourcelike): void { + private pushItem (item: Sourcelike): void { this._currentEmitTarget.push(item); this._preventBlankLine = false; } - emitNewline(): void { + emitNewline (): void { const nl = newline(); this.pushItem(nl); this._lastNewline = nl; } - emitItem(item: Sourcelike): void { + emitItem (item: Sourcelike): void { if (!this.isEmpty) { for (let i = 0; i < this._numBlankLinesNeeded; i++) { this.emitNewline(); } } + this._numBlankLinesNeeded = 0; this.pushItem(item); } - containsItem(item: Sourcelike): boolean { + containsItem (item: Sourcelike): boolean { const existingItem = this._currentEmitTarget.find((value: Sourcelike) => item === value); return existingItem !== undefined; } - ensureBlankLine(numBlankLines: number): void { + ensureBlankLine (numBlankLines: number): void { if (this._preventBlankLine) return; this._numBlankLinesNeeded = Math.max(this._numBlankLinesNeeded, numBlankLines); } - preventBlankLine(): void { + preventBlankLine (): void { this._numBlankLinesNeeded = 0; this._preventBlankLine = true; } - changeIndent(offset: number): void { + changeIndent (offset: number): void { if (this._lastNewline === undefined) { return panic("Cannot change indent for the first line"); } + this._lastNewline.indentationChange += offset; } } export abstract class Renderer { protected readonly typeGraph: TypeGraph; + protected readonly leadingComments: Comment[] | undefined; private _names: ReadonlyMap | undefined; - private _finishedFiles: Map; - private _finishedEmitContexts: Map; + + private readonly _finishedFiles: Map; + + private readonly _finishedEmitContexts: Map; private _emitContext: EmitContext; - constructor( + constructor ( protected readonly targetLanguage: TargetLanguage, - renderContext: RenderContext + renderContext: RenderContext, ) { this.typeGraph = renderContext.typeGraph; this.leadingComments = renderContext.leadingComments; @@ -141,19 +155,19 @@ export abstract class Renderer { this._emitContext = new EmitContext(); } - ensureBlankLine(numBlankLines = 1): void { + ensureBlankLine (numBlankLines = 1): void { this._emitContext.ensureBlankLine(numBlankLines); } - preventBlankLine(): void { + preventBlankLine (): void { this._emitContext.preventBlankLine(); } - emitItem(item: Sourcelike): void { + emitItem (item: Sourcelike): void { this._emitContext.emitItem(item); } - emitItemOnce(item: Sourcelike): boolean { + emitItemOnce (item: Sourcelike): boolean { if (this._emitContext.containsItem(item)) { return false; } @@ -162,7 +176,7 @@ export abstract class Renderer { return true; } - emitLineOnce(...lineParts: Sourcelike[]): void { + emitLineOnce (...lineParts: Sourcelike[]): void { let lineEmitted = true; if (lineParts.length === 1) { lineEmitted = this.emitItemOnce(lineParts[0]); @@ -175,16 +189,17 @@ export abstract class Renderer { } } - emitLine(...lineParts: Sourcelike[]): void { + emitLine (...lineParts: Sourcelike[]): void { if (lineParts.length === 1) { this._emitContext.emitItem(lineParts[0]); } else if (lineParts.length > 1) { this._emitContext.emitItem(lineParts); } + this._emitContext.emitNewline(); } - emitMultiline(linesString: string): void { + emitMultiline (linesString: string): void { const lines = linesString.split("\n"); const numLines = lines.length; if (numLines === 0) return; @@ -203,12 +218,13 @@ export abstract class Renderer { this._emitContext.emitNewline(); } } + if (currentIndent !== 0) { this.changeIndent(-currentIndent); } } - gatherSource(emitter: () => void): Sourcelike[] { + gatherSource (emitter: () => void): Sourcelike[] { const oldEmitContext = this._emitContext; this._emitContext = new EmitContext(); emitter(); @@ -218,19 +234,19 @@ export abstract class Renderer { return source; } - emitGatheredSource(items: Sourcelike[]): void { + emitGatheredSource (items: Sourcelike[]): void { for (const item of items) { this._emitContext.emitItem(item); } } - emitAnnotated(annotation: AnnotationData, emitter: () => void): void { + emitAnnotated (annotation: AnnotationData, emitter: () => void): void { const lines = this.gatherSource(emitter); const source = sourcelikeToSource(lines); this._emitContext.emitItem(annotated(annotation, source)); } - emitIssue(message: string, emitter: () => void): void { + emitIssue (message: string, emitter: () => void): void { this.emitAnnotated(new IssueAnnotationData(message), emitter); } @@ -241,7 +257,7 @@ export abstract class Renderer { this._emitContext.emitNewline(); }; - changeIndent(offset: number): void { + changeIndent (offset: number): void { this._emitContext.changeIndent(offset); } @@ -260,7 +276,7 @@ export abstract class Renderer { iterable: Iterable<[K, V]>, interposedBlankLines: number, leadingBlankLines: number, - emitter: (v: V, k: K, position: ForEachPosition) => void + emitter: (v: V, k: K, position: ForEachPosition) => void, ): boolean { let didEmit = false; this.iterableForEach(iterable, ([k, v], position) => { @@ -269,6 +285,7 @@ export abstract class Renderer { } else { this.ensureBlankLine(interposedBlankLines); } + emitter(v, k, position); didEmit = true; }); @@ -278,28 +295,28 @@ export abstract class Renderer { forEachWithBlankLines( iterable: Iterable<[K, V]>, blankLineConfig: BlankLineConfig, - emitter: (v: V, k: K, position: ForEachPosition) => void + emitter: (v: V, k: K, position: ForEachPosition) => void, ): boolean { const { position, count } = getBlankLineConfig(blankLineConfig); - const interposing = ["interposing", "leading-and-interposing"].indexOf(position) >= 0; - const leading = ["leading", "leading-and-interposing"].indexOf(position) >= 0; + const interposing = ["interposing", "leading-and-interposing"].includes(position); + const leading = ["leading", "leading-and-interposing"].includes(position); return this.forEach(iterable, interposing ? count : 0, leading ? count : 0, emitter); } - indent(fn: () => void): void { + indent (fn: () => void): void { this.changeIndent(1); fn(); this.changeIndent(-1); } - protected abstract setUpNaming(): Iterable; - protected abstract emitSource(givenOutputFilename: string): void; + protected abstract setUpNaming (): Iterable; + protected abstract emitSource (givenOutputFilename: string): void; - private assignNames(): ReadonlyMap { + private assignNames (): ReadonlyMap { return assignNames(this.setUpNaming()); } - protected initializeEmitContextForFilename(filename: string): void { + protected initializeEmitContextForFilename (filename: string): void { if (this._finishedEmitContexts.has(filename.toLowerCase())) { const existingEmitContext = this._finishedEmitContexts.get(filename.toLowerCase()); if (existingEmitContext !== undefined) { @@ -308,10 +325,10 @@ export abstract class Renderer { } } - protected finishFile(filename: string): void { + protected finishFile (filename: string): void { if (this._finishedFiles.has(filename)) { console.log( - `[WARNING] Tried to emit file ${filename} more than once. If performing multi-file output this warning can be safely ignored.` + `[WARNING] Tried to emit file ${filename} more than once. If performing multi-file output this warning can be safely ignored.`, ); } @@ -323,19 +340,21 @@ export abstract class Renderer { this._emitContext = new EmitContext(); } - render(givenOutputFilename: string): RenderResult { + render (givenOutputFilename: string): RenderResult { this._names = this.assignNames(); this.emitSource(givenOutputFilename); if (!this._emitContext.isEmpty) { this.finishFile(givenOutputFilename); } + return { sources: this._finishedFiles, names: this._names }; } - get names(): ReadonlyMap { + get names (): ReadonlyMap { if (this._names === undefined) { return panic("Names accessed before they were assigned"); } + return this._names; } } diff --git a/packages/quicktype-core/src/RendererOptions.ts b/packages/quicktype-core/src/RendererOptions.ts index 9ef964b42..f3fae9ffa 100644 --- a/packages/quicktype-core/src/RendererOptions.ts +++ b/packages/quicktype-core/src/RendererOptions.ts @@ -9,17 +9,17 @@ import { hasOwnProperty } from "collection-utils"; export type OptionKind = "primary" | "secondary"; export interface OptionDefinition { - name: string; - type: StringConstructor | BooleanConstructor; - kind?: OptionKind; - renderer?: boolean; alias?: string; - multiple?: boolean; defaultOption?: boolean; defaultValue?: any; - typeLabel?: string; description: string; + kind?: OptionKind; legalValues?: string[]; + multiple?: boolean; + name: string; + renderer?: boolean; + type: StringConstructor | BooleanConstructor; + typeLabel?: string; } /** @@ -29,21 +29,22 @@ export interface OptionDefinition { export abstract class Option { readonly definition: OptionDefinition; - constructor(definition: OptionDefinition) { + constructor (definition: OptionDefinition) { definition.renderer = true; this.definition = definition; assert(definition.kind !== undefined, "Renderer option kind must be defined"); } - getValue(values: { [name: string]: any }): T { + getValue (values: { [name: string]: any, }): T { const value = values[this.definition.name]; if (value === undefined) { return this.definition.defaultValue; } + return value; } - get cliDefinitions(): { display: OptionDefinition[]; actual: OptionDefinition[] } { + get cliDefinitions (): { actual: OptionDefinition[], display: OptionDefinition[], } { return { actual: [this.definition], display: [this.definition] }; } } @@ -51,14 +52,15 @@ export abstract class Option { export type OptionValueType = O extends Option ? T : never; export type OptionValues = { [P in keyof T]: OptionValueType }; -export function getOptionValues }>( +export function getOptionValues, }> ( options: T, - untypedOptionValues: { [name: string]: any } + untypedOptionValues: { [name: string]: any, }, ): OptionValues { - const optionValues: { [name: string]: any } = {}; + const optionValues: { [name: string]: any, } = {}; for (const name of Object.getOwnPropertyNames(options)) { optionValues[name] = options[name].getValue(untypedOptionValues); } + return optionValues as OptionValues; } @@ -72,32 +74,32 @@ export class BooleanOption extends Option { * @param defaultValue The default value. * @param kind Whether it's a primary or secondary option. */ - constructor(name: string, description: string, defaultValue: boolean, kind: OptionKind = "primary") { + constructor (name: string, description: string, defaultValue: boolean, kind: OptionKind = "primary") { super({ name, kind, type: Boolean, description, - defaultValue + defaultValue, }); } - get cliDefinitions(): { display: OptionDefinition[]; actual: OptionDefinition[] } { + get cliDefinitions (): { actual: OptionDefinition[], display: OptionDefinition[], } { const negated = Object.assign({}, this.definition, { name: `no-${this.definition.name}`, - defaultValue: !this.definition.defaultValue + defaultValue: !this.definition.defaultValue, }); const display = Object.assign({}, this.definition, { name: `[no-]${this.definition.name}`, - description: `${this.definition.description} (${this.definition.defaultValue ? "on" : "off"} by default)` + description: `${this.definition.description} (${this.definition.defaultValue ? "on" : "off"} by default)`, }); return { display: [display], - actual: [this.definition, negated] + actual: [this.definition, negated], }; } - getValue(values: { [name: string]: any }): boolean { + getValue (values: { [name: string]: any, }): boolean { let value = values[this.definition.name]; if (value === undefined) { value = this.definition.defaultValue; @@ -123,12 +125,12 @@ export class BooleanOption extends Option { } export class StringOption extends Option { - constructor( + constructor ( name: string, description: string, typeLabel: string, defaultValue: string, - kind: OptionKind = "primary" + kind: OptionKind = "primary", ) { const definition = { name, @@ -136,25 +138,26 @@ export class StringOption extends Option { type: String, description, typeLabel, - defaultValue + defaultValue, }; super(definition); } } export class EnumOption extends Option { - private readonly _values: { [name: string]: T }; + private readonly _values: { [name: string]: T, }; - constructor( + constructor ( name: string, description: string, - values: [string, T][], + values: Array<[string, T]>, defaultValue: string | undefined = undefined, - kind: OptionKind = "primary" + kind: OptionKind = "primary", ) { if (defaultValue === undefined) { defaultValue = values[0][0]; } + const definition = { name, kind, @@ -162,7 +165,7 @@ export class EnumOption extends Option { description, typeLabel: values.map(([n, _]) => n).join("|"), legalValues: values.map(([n, _]) => n), - defaultValue + defaultValue, }; super(definition); @@ -172,14 +175,16 @@ export class EnumOption extends Option { } } - getValue(values: { [name: string]: any }): T { + getValue (values: { [name: string]: any, }): T { let name: string = values[this.definition.name]; if (name === undefined) { name = this.definition.defaultValue; } + if (!hasOwnProperty(this._values, name)) { return messageError("RendererUnknownOptionValue", { value: name, name: this.definition.name }); } + return this._values[name]; } } diff --git a/packages/quicktype-core/src/Run.ts b/packages/quicktype-core/src/Run.ts index 195417cb9..1faaed8e6 100644 --- a/packages/quicktype-core/src/Run.ts +++ b/packages/quicktype-core/src/Run.ts @@ -1,13 +1,15 @@ import { mapFirst } from "collection-utils"; import * as targetLanguages from "./language/All"; -import { TargetLanguage, MultiFileRenderResult } from "./TargetLanguage"; -import { SerializedRenderResult, Annotation, Location, Span } from "./Source"; +import { type TargetLanguage, type MultiFileRenderResult } from "./TargetLanguage"; +import { type SerializedRenderResult, type Annotation, type Location, type Span } from "./Source"; import { assert } from "./support/Support"; import { combineClasses } from "./rewrites/CombineClasses"; import { inferMaps } from "./rewrites/InferMaps"; -import { TypeBuilder, StringTypeMapping } from "./TypeBuilder"; -import { TypeGraph, noneToAny, optionalToNullable, removeIndirectionIntersections } from "./TypeGraph"; +import { type StringTypeMapping } from "./TypeBuilder"; +import { TypeBuilder } from "./TypeBuilder"; +import { type TypeGraph} from "./TypeGraph"; +import { noneToAny, optionalToNullable, removeIndirectionIntersections } from "./TypeGraph"; import { initTypeNames } from "./attributes/TypeNames"; import { gatherNames } from "./GatherNames"; import { expandStrings } from "./rewrites/ExpandStrings"; @@ -18,26 +20,30 @@ import { messageError } from "./Messages"; import { InputData } from "./input/Inputs"; import { flattenStrings } from "./rewrites/FlattenStrings"; import { makeTransformations } from "./MakeTransformations"; -import { TransformedStringTypeKind } from "./Type"; +import { type TransformedStringTypeKind } from "./Type"; import { type Comment } from "./support/Comments"; -export function getTargetLanguage(nameOrInstance: string | TargetLanguage): TargetLanguage { +export function getTargetLanguage (nameOrInstance: string | TargetLanguage): TargetLanguage { if (typeof nameOrInstance === "object") { return nameOrInstance; } + const language = targetLanguages.languageNamed(nameOrInstance); if (language !== undefined) { return language; } + return messageError("DriverUnknownOutputLanguage", { lang: nameOrInstance }); } -export type RendererOptions = { [name: string]: string | boolean }; +export interface RendererOptions { + [name: string]: string | boolean; +} export interface InferenceFlag { description: string; - negationDescription: string; explanation: string; + negationDescription: string; order: number; stringType?: TransformedStringTypeKind; } @@ -48,14 +54,14 @@ export const inferenceFlagsObject = { description: "Detect maps", negationDescription: "Don't infer maps, always use classes", explanation: "Infer maps when object keys look like map keys.", - order: 1 + order: 1, }, /** Whether to infer enum types from JSON data */ inferEnums: { description: "Detect enums", negationDescription: "Don't infer enums, always use strings", explanation: "If string values occur within a relatively small domain,\ninfer them as enum values.", - order: 2 + order: 2, }, /** Whether to convert UUID strings to UUID objects */ inferUuids: { @@ -63,7 +69,7 @@ export const inferenceFlagsObject = { negationDescription: "Don't convert UUIDs to UUID objects", explanation: "Detect UUIDs like '123e4567-e89b-12d3-a456-426655440000' (partial support).", stringType: "uuid" as TransformedStringTypeKind, - order: 3 + order: 3, }, /** Whether to assume that JSON strings that look like dates are dates */ inferDateTimes: { @@ -71,24 +77,24 @@ export const inferenceFlagsObject = { negationDescription: "Don't infer dates or times", explanation: "Infer dates from strings (partial support).", stringType: "date-time" as TransformedStringTypeKind, - order: 4 + order: 4, }, /** Whether to convert stringified integers to integers */ inferIntegerStrings: { description: "Detect integers in strings", negationDescription: "Don't convert stringified integers to integers", - explanation: 'Automatically convert stringified integers to integers.\nFor example, "1" is converted to 1.', + explanation: "Automatically convert stringified integers to integers.\nFor example, \"1\" is converted to 1.", stringType: "integer-string" as TransformedStringTypeKind, - order: 5 + order: 5, }, /** Whether to convert stringified booleans to boolean values */ inferBooleanStrings: { description: "Detect booleans in strings", negationDescription: "Don't convert stringified booleans to booleans", explanation: - 'Automatically convert stringified booleans to booleans.\nFor example, "true" is converted to true.', + "Automatically convert stringified booleans to booleans.\nFor example, \"true\" is converted to true.", stringType: "bool-string" as TransformedStringTypeKind, - order: 6 + order: 6, }, /** Combine similar classes. This doesn't apply to classes from a schema, only from inference. */ combineClasses: { @@ -96,7 +102,7 @@ export const inferenceFlagsObject = { negationDescription: "Don't combine similar classes", explanation: "Combine classes with significantly overlapping properties,\ntreating contingent properties as nullable.", - order: 7 + order: 7, }, /** Whether to treat $ref as references within JSON */ ignoreJsonRefs: { @@ -104,8 +110,8 @@ export const inferenceFlagsObject = { negationDescription: "Treat $ref as a reference in JSON", explanation: "Like in JSON Schema, allow objects like\n'{ $ref: \"#/foo/bar\" }' to refer\nto another part of the input.", - order: 8 - } + order: 8, + }, }; export type InferenceFlagName = keyof typeof inferenceFlagsObject; export const inferenceFlagNames = Object.getOwnPropertyNames(inferenceFlagsObject) as InferenceFlagName[]; @@ -117,57 +123,57 @@ export type InferenceFlags = { [F in InferenceFlagName]: boolean }; * The options type for the main quicktype entry points, * `quicktypeMultiFile` and `quicktype`. */ -export type NonInferenceOptions = { - /** - * The target language for which to produce code. This can be either an instance of `TargetLanguage`, - * or a string specifying one of the names for quicktype's built-in target languages. For example, - * both `cs` and `csharp` will generate C#. - */ - lang: string | TargetLanguage; - /** The input data from which to produce types */ - inputData: InputData; - /** Put class properties in alphabetical order, instead of in the order found in the JSON */ - alphabetizeProperties: boolean; +export interface NonInferenceOptions { /** Make all class property optional */ allPropertiesOptional: boolean; + /** Put class properties in alphabetical order, instead of in the order found in the JSON */ + alphabetizeProperties: boolean; + /** Check that we're propagating all type attributes (unless we actually can't) */ + checkProvenance: boolean; /** - * Make top-levels classes from JSON fixed. That means even if two top-level classes are exactly - * the same, quicktype will still generate two separate types for them. - */ - fixedTopLevels: boolean; - /** Don't render output. This is mainly useful for benchmarking. */ - noRender: boolean; - /** If given, output these comments at the beginning of the main output file */ - leadingComments?: Comment[]; - /** Options for the target language's renderer */ - rendererOptions: RendererOptions; - /** String to use for one indentation level. If not given, use the target language's default. */ - indentation: string | undefined; - /** Name of the output file. Note that quicktype will not write that file, but you'll get its name - * back as a key in the resulting `Map`. + * Print name gathering debug information to the console. This might help to figure out why + * your types get weird names, but the output is quite arcane. */ - outputFilename: string; + debugPrintGatherNames: boolean; /** Print the type graph to the console at every processing step */ debugPrintGraph: boolean; - /** Check that we're propagating all type attributes (unless we actually can't) */ - checkProvenance: boolean; /** * Print type reconstitution debug information to the console. You'll only ever need this if * you're working deep inside quicktype-core. */ debugPrintReconstitution: boolean; - /** - * Print name gathering debug information to the console. This might help to figure out why - * your types get weird names, but the output is quite arcane. - */ - debugPrintGatherNames: boolean; - /** Print all transformations to the console prior to generating code */ - debugPrintTransformations: boolean; - /** Print the time it took for each pass to run */ - debugPrintTimes: boolean; /** Print schema resolving steps */ debugPrintSchemaResolving: boolean; -}; + /** Print the time it took for each pass to run */ + debugPrintTimes: boolean; + /** Print all transformations to the console prior to generating code */ + debugPrintTransformations: boolean; + /** + * Make top-levels classes from JSON fixed. That means even if two top-level classes are exactly + * the same, quicktype will still generate two separate types for them. + */ + fixedTopLevels: boolean; + /** String to use for one indentation level. If not given, use the target language's default. */ + indentation: string | undefined; + /** The input data from which to produce types */ + inputData: InputData; + /** + * The target language for which to produce code. This can be either an instance of `TargetLanguage`, + * or a string specifying one of the names for quicktype's built-in target languages. For example, + * both `cs` and `csharp` will generate C#. + */ + lang: string | TargetLanguage; + /** If given, output these comments at the beginning of the main output file */ + leadingComments?: Comment[]; + /** Don't render output. This is mainly useful for benchmarking. */ + noRender: boolean; + /** Name of the output file. Note that quicktype will not write that file, but you'll get its name + * back as a key in the resulting `Map`. + */ + outputFilename: string; + /** Options for the target language's renderer */ + rendererOptions: RendererOptions; +} export type Options = NonInferenceOptions & InferenceFlags; @@ -188,31 +194,32 @@ const defaultOptions: NonInferenceOptions = { debugPrintGatherNames: false, debugPrintTransformations: false, debugPrintTimes: false, - debugPrintSchemaResolving: false + debugPrintSchemaResolving: false, }; export interface RunContext { - stringTypeMapping: StringTypeMapping; debugPrintReconstitution: boolean; - debugPrintTransformations: boolean; debugPrintSchemaResolving: boolean; + debugPrintTransformations: boolean; + stringTypeMapping: StringTypeMapping; - timeSync(name: string, f: () => Promise): Promise; - time(name: string, f: () => T): T; + time: (name: string, f: () => T) => T; + timeSync: (name: string, f: () => Promise) => Promise; } interface GraphInputs { - targetLanguage: TargetLanguage; - stringTypeMapping: StringTypeMapping; conflateNumbers: boolean; + stringTypeMapping: StringTypeMapping; + targetLanguage: TargetLanguage; typeBuilder: TypeBuilder; } -function makeDefaultInferenceFlags(): InferenceFlags { +function makeDefaultInferenceFlags (): InferenceFlags { const flags = {} as InferenceFlags; for (const flag of inferenceFlagNames) { flags[flag] = true; } + return flags; } @@ -221,7 +228,7 @@ export const defaultInferenceFlags = makeDefaultInferenceFlags(); class Run implements RunContext { private readonly _options: Options; - constructor(options: Partial) { + constructor (options: Partial) { // We must not overwrite defaults with undefined values, which // we sometimes get. this._options = Object.assign({}, defaultOptions, defaultInferenceFlags); @@ -233,7 +240,7 @@ class Run implements RunContext { } } - get stringTypeMapping(): StringTypeMapping { + get stringTypeMapping (): StringTypeMapping { const targetLanguage = getTargetLanguage(this._options.lang); const mapping = new Map(targetLanguage.stringTypeMapping); for (const flag of inferenceFlagNames) { @@ -242,18 +249,19 @@ class Run implements RunContext { mapping.set(stringType, "string"); } } + return mapping; } - get debugPrintReconstitution(): boolean { + get debugPrintReconstitution (): boolean { return this._options.debugPrintReconstitution === true; } - get debugPrintTransformations(): boolean { + get debugPrintTransformations (): boolean { return this._options.debugPrintTransformations; } - get debugPrintSchemaResolving(): boolean { + get debugPrintSchemaResolving (): boolean { return this._options.debugPrintSchemaResolving; } @@ -264,6 +272,7 @@ class Run implements RunContext { if (this._options.debugPrintTimes) { console.log(`${name} took ${end - start}ms`); } + return result; } @@ -274,10 +283,11 @@ class Run implements RunContext { if (this._options.debugPrintTimes) { console.log(`${name} took ${end - start}ms`); } + return result; } - private makeGraphInputs(): GraphInputs { + private makeGraphInputs (): GraphInputs { const targetLanguage = getTargetLanguage(this._options.lang); const stringTypeMapping = this.stringTypeMapping; const conflateNumbers = !targetLanguage.supportsUnionsWithBothNumberTypes; @@ -287,13 +297,13 @@ class Run implements RunContext { this._options.alphabetizeProperties, this._options.allPropertiesOptional, this._options.checkProvenance, - false + false, ); return { targetLanguage, stringTypeMapping, conflateNumbers, typeBuilder }; } - private async makeGraph(allInputs: InputData): Promise { + private async makeGraph (allInputs: InputData): Promise { const graphInputs = this.makeGraphInputs(); await this.timeSync( @@ -304,14 +314,14 @@ class Run implements RunContext { graphInputs.typeBuilder, this._options.inferMaps, this._options.inferEnums, - this._options.fixedTopLevels - ) + this._options.fixedTopLevels, + ), ); return this.processGraph(allInputs, graphInputs); } - private makeGraphSync(allInputs: InputData): TypeGraph { + private makeGraphSync (allInputs: InputData): TypeGraph { const graphInputs = this.makeGraphInputs(); this.time("read input", () => @@ -320,14 +330,14 @@ class Run implements RunContext { graphInputs.typeBuilder, this._options.inferMaps, this._options.inferEnums, - this._options.fixedTopLevels - ) + this._options.fixedTopLevels, + ), ); return this.processGraph(allInputs, graphInputs); } - private processGraph(allInputs: InputData, graphInputs: GraphInputs): TypeGraph { + private processGraph (allInputs: InputData, graphInputs: GraphInputs): TypeGraph { const { targetLanguage, stringTypeMapping, conflateNumbers, typeBuilder } = graphInputs; let graph = typeBuilder.finish(); @@ -341,7 +351,7 @@ class Run implements RunContext { if (typeBuilder.didAddForwardingIntersection || !this._options.ignoreJsonRefs) { this.time( "remove indirection intersections", - () => (graph = removeIndirectionIntersections(graph, stringTypeMapping, debugPrintReconstitution)) + () => graph = removeIndirectionIntersections(graph, stringTypeMapping, debugPrintReconstitution), ); } @@ -354,24 +364,25 @@ class Run implements RunContext { this.time( "resolve intersections", () => - ([graph, intersectionsDone] = resolveIntersections( + [graph, intersectionsDone] = resolveIntersections( graph, stringTypeMapping, - debugPrintReconstitution - )) + debugPrintReconstitution, + ), ); } + if (!unionsDone) { this.time( "flatten unions", () => - ([graph, unionsDone] = flattenUnions( + [graph, unionsDone] = flattenUnions( graph, stringTypeMapping, conflateNumbers, true, - debugPrintReconstitution - )) + debugPrintReconstitution, + ), ); } @@ -384,31 +395,31 @@ class Run implements RunContext { this.time( "replace object type", () => - (graph = replaceObjectType( + graph = replaceObjectType( graph, stringTypeMapping, conflateNumbers, targetLanguage.supportsFullObjectType, - debugPrintReconstitution - )) + debugPrintReconstitution, + ), ); do { this.time( "flatten unions", () => - ([graph, unionsDone] = flattenUnions( + [graph, unionsDone] = flattenUnions( graph, stringTypeMapping, conflateNumbers, false, - debugPrintReconstitution - )) + debugPrintReconstitution, + ), ); } while (!unionsDone); if (this._options.combineClasses) { const combinedGraph = this.time("combine classes", () => - combineClasses(this, graph, this._options.alphabetizeProperties, true, false, debugPrintReconstitution) + combineClasses(this, graph, this._options.alphabetizeProperties, true, false, debugPrintReconstitution), ); if (combinedGraph === graph) { graph = combinedGraph; @@ -416,14 +427,14 @@ class Run implements RunContext { this.time( "combine classes cleanup", () => - (graph = combineClasses( + graph = combineClasses( this, combinedGraph, this._options.alphabetizeProperties, false, true, - debugPrintReconstitution - )) + debugPrintReconstitution, + ), ); } } @@ -431,59 +442,60 @@ class Run implements RunContext { if (this._options.inferMaps) { for (;;) { const newGraph = this.time("infer maps", () => - inferMaps(graph, stringTypeMapping, true, debugPrintReconstitution) + inferMaps(graph, stringTypeMapping, true, debugPrintReconstitution), ); if (newGraph === graph) { break; } + graph = newGraph; } } const enumInference = allInputs.needSchemaProcessing ? "all" : this._options.inferEnums ? "infer" : "none"; - this.time("expand strings", () => (graph = expandStrings(this, graph, enumInference))); + this.time("expand strings", () => graph = expandStrings(this, graph, enumInference)); this.time( "flatten unions", () => - ([graph, unionsDone] = flattenUnions( + [graph, unionsDone] = flattenUnions( graph, stringTypeMapping, conflateNumbers, false, - debugPrintReconstitution - )) + debugPrintReconstitution, + ), ); assert(unionsDone, "We should only have to flatten unions once after expanding strings"); if (allInputs.needSchemaProcessing) { this.time( "flatten strings", - () => (graph = flattenStrings(graph, stringTypeMapping, debugPrintReconstitution)) + () => graph = flattenStrings(graph, stringTypeMapping, debugPrintReconstitution), ); } - this.time("none to any", () => (graph = noneToAny(graph, stringTypeMapping, debugPrintReconstitution))); + this.time("none to any", () => graph = noneToAny(graph, stringTypeMapping, debugPrintReconstitution)); if (!targetLanguage.supportsOptionalClassProperties) { this.time( "optional to nullable", - () => (graph = optionalToNullable(graph, stringTypeMapping, debugPrintReconstitution)) + () => graph = optionalToNullable(graph, stringTypeMapping, debugPrintReconstitution), ); } - this.time("fixed point", () => (graph = graph.rewriteFixedPoint(false, debugPrintReconstitution))); + this.time("fixed point", () => graph = graph.rewriteFixedPoint(false, debugPrintReconstitution)); - this.time("make transformations", () => (graph = makeTransformations(this, graph, targetLanguage))); + this.time("make transformations", () => graph = makeTransformations(this, graph, targetLanguage)); this.time( "flatten unions", () => - ([graph, unionsDone] = flattenUnions( + [graph, unionsDone] = flattenUnions( graph, stringTypeMapping, conflateNumbers, false, - debugPrintReconstitution - )) + debugPrintReconstitution, + ), ); assert(unionsDone, "We should only have to flatten unions once after making transformations"); @@ -496,14 +508,15 @@ class Run implements RunContext { // is different from the one we started out with. this.time( "GC", - () => (graph = graph.garbageCollect(this._options.alphabetizeProperties, debugPrintReconstitution)) + () => graph = graph.garbageCollect(this._options.alphabetizeProperties, debugPrintReconstitution), ); if (this._options.debugPrintGraph) { console.log("\n# gather names"); } + this.time("gather names", () => - gatherNames(graph, !allInputs.needSchemaProcessing, this._options.debugPrintGatherNames) + gatherNames(graph, !allInputs.needSchemaProcessing, this._options.debugPrintGatherNames), ); if (this._options.debugPrintGraph) { graph.printGraph(); @@ -512,20 +525,20 @@ class Run implements RunContext { return graph; } - private makeSimpleTextResult(lines: string[]): MultiFileRenderResult { - return new Map([[this._options.outputFilename, { lines, annotations: [] }]] as [ + private makeSimpleTextResult (lines: string[]): MultiFileRenderResult { + return new Map([[this._options.outputFilename, { lines, annotations: [] }]] as Array<[ string, SerializedRenderResult - ][]); + ]>); } - private preRun(): MultiFileRenderResult | [InputData, TargetLanguage] { + private preRun (): MultiFileRenderResult | [InputData, TargetLanguage] { // FIXME: This makes quicktype not quite reentrant initTypeNames(); const targetLanguage = getTargetLanguage(this._options.lang); const inputData = this._options.inputData; - const needIR = inputData.needIR || targetLanguage.names.indexOf("schema") < 0; + const needIR = inputData.needIR || !targetLanguage.names.includes("schema"); const schemaString = needIR ? undefined : inputData.singleStringSchemaSource(); if (schemaString !== undefined) { @@ -538,7 +551,7 @@ class Run implements RunContext { return [inputData, targetLanguage]; } - async run(): Promise { + async run (): Promise { const preRunResult = this.preRun(); if (!Array.isArray(preRunResult)) { return preRunResult; @@ -551,7 +564,7 @@ class Run implements RunContext { return this.renderGraph(targetLanguage, graph); } - runSync(): MultiFileRenderResult { + runSync (): MultiFileRenderResult { const preRunResult = this.preRun(); if (!Array.isArray(preRunResult)) { return preRunResult; @@ -564,7 +577,7 @@ class Run implements RunContext { return this.renderGraph(targetLanguage, graph); } - private renderGraph(targetLanguage: TargetLanguage, graph: TypeGraph): MultiFileRenderResult { + private renderGraph (targetLanguage: TargetLanguage, graph: TypeGraph): MultiFileRenderResult { if (this._options.noRender) { return this.makeSimpleTextResult(["Done.", ""]); } @@ -575,7 +588,7 @@ class Run implements RunContext { this._options.alphabetizeProperties, this._options.leadingComments, this._options.rendererOptions, - this._options.indentation + this._options.indentation, ); } } @@ -586,19 +599,19 @@ class Run implements RunContext { * @param options Partial options. For options that are not defined, the * defaults will be used. */ -export async function quicktypeMultiFile(options: Partial): Promise { +export async function quicktypeMultiFile (options: Partial): Promise { return await new Run(options).run(); } -export function quicktypeMultiFileSync(options: Partial): MultiFileRenderResult { +export function quicktypeMultiFileSync (options: Partial): MultiFileRenderResult { return new Run(options).runSync(); } -function offsetLocation(loc: Location, lineOffset: number): Location { +function offsetLocation (loc: Location, lineOffset: number): Location { return { line: loc.line + lineOffset, column: loc.column }; } -function offsetSpan(span: Span, lineOffset: number): Span { +function offsetSpan (span: Span, lineOffset: number): Span { return { start: offsetLocation(span.start, lineOffset), end: offsetLocation(span.end, lineOffset) }; } @@ -607,23 +620,26 @@ function offsetSpan(span: Span, lineOffset: number): Span { * are concatenated and prefixed with a `//`-style comment giving the * filename. */ -export function combineRenderResults(result: MultiFileRenderResult): SerializedRenderResult { +export function combineRenderResults (result: MultiFileRenderResult): SerializedRenderResult { if (result.size <= 1) { const first = mapFirst(result); if (first === undefined) { return { lines: [], annotations: [] }; } + return first; } + let lines: string[] = []; let annotations: Annotation[] = []; for (const [filename, srr] of result) { const offset = lines.length + 2; lines = lines.concat([`// ${filename}`, ""], srr.lines); annotations = annotations.concat( - srr.annotations.map(ann => ({ annotation: ann.annotation, span: offsetSpan(ann.span, offset) })) + srr.annotations.map(ann => ({ annotation: ann.annotation, span: offsetSpan(ann.span, offset) })), ); } + return { lines, annotations }; } @@ -635,7 +651,7 @@ export function combineRenderResults(result: MultiFileRenderResult): SerializedR * @param options Partial options. For options that are not defined, the * defaults will be used. */ -export async function quicktype(options: Partial): Promise { +export async function quicktype (options: Partial): Promise { const result = await quicktypeMultiFile(options); return combineRenderResults(result); } diff --git a/packages/quicktype-core/src/Source.ts b/packages/quicktype-core/src/Source.ts index 6898480af..235ac9264 100644 --- a/packages/quicktype-core/src/Source.ts +++ b/packages/quicktype-core/src/Source.ts @@ -1,6 +1,6 @@ import { arrayIntercalate, iterableMax, withDefault } from "collection-utils"; -import { AnnotationData } from "./Annotation"; +import { type AnnotationData } from "./Annotation"; import { Name } from "./Naming"; import { defined, assertNever, panic, assert } from "./support/Support"; import { repeatString } from "./support/Strings"; @@ -20,28 +20,28 @@ export interface TextSource { } export interface NewlineSource { - kind: "newline"; // Number of indentation levels (not spaces!) to change - // the rest of the source by. Positive numbers mean - // indent more, negative mean indent less. The most - // common value will be zero, for no change in - // indentation. +// the rest of the source by. Positive numbers mean +// indent more, negative mean indent less. The most +// common value will be zero, for no change in +// indentation. indentationChange: number; + kind: "newline"; } export interface SequenceSource { kind: "sequence"; - sequence: ReadonlyArray; + sequence: readonly Source[]; } export interface TableSource { kind: "table"; - table: ReadonlyArray>; + table: ReadonlyArray; } export interface AnnotatedSource { - kind: "annotated"; annotation: AnnotationData; + kind: "annotated"; source: Source; } @@ -56,73 +56,78 @@ export interface ModifiedSource { source: Source; } -export function newline(): NewlineSource { +export function newline (): NewlineSource { // We're returning a new object instead of using a singleton // here because `Renderer` will modify `indentationChange`. return { kind: "newline", indentationChange: 0 }; } export type Sourcelike = Source | string | Name | SourcelikeArray; -export interface SourcelikeArray extends Array {} +export type SourcelikeArray = Sourcelike[]; -export function sourcelikeToSource(sl: Sourcelike): Source { +export function sourcelikeToSource (sl: Sourcelike): Source { if (sl instanceof Array) { return { kind: "sequence", - sequence: sl.map(sourcelikeToSource) + sequence: sl.map(sourcelikeToSource), }; } + if (typeof sl === "string") { const lines = sl.split("\n"); if (lines.length === 1) { return { kind: "text", text: sl }; } + return { kind: "sequence", sequence: arrayIntercalate( newline(), - lines.map((l: string) => ({ kind: "text", text: l } as Source)) - ) + lines.map((l: string) => ({ kind: "text", text: l } as Source)), + ), }; } + if (sl instanceof Name) { return { kind: "name", named: sl }; } + return sl; } -export function annotated(annotation: AnnotationData, sl: Sourcelike): Source { +export function annotated (annotation: AnnotationData, sl: Sourcelike): Source { return { kind: "annotated", annotation, - source: sourcelikeToSource(sl) + source: sourcelikeToSource(sl), }; } -export function maybeAnnotated(doAnnotate: boolean, annotation: AnnotationData, sl: Sourcelike): Sourcelike { +export function maybeAnnotated (doAnnotate: boolean, annotation: AnnotationData, sl: Sourcelike): Sourcelike { if (!doAnnotate) { return sl; } + return annotated(annotation, sl); } -export function modifySource(modifier: (serialized: string) => string, sl: Sourcelike): Sourcelike { +export function modifySource (modifier: (serialized: string) => string, sl: Sourcelike): Sourcelike { return { kind: "modified", modifier, - source: sourcelikeToSource(sl) + source: sourcelikeToSource(sl), }; } export interface Location { + column: number; // Both of these are zero-based. line: number; - column: number; } export interface Span { - start: Location; end: Location; + start: Location; } export interface Annotation { @@ -131,11 +136,11 @@ export interface Annotation { } export interface SerializedRenderResult { + annotations: readonly Annotation[]; lines: string[]; - annotations: ReadonlyArray; } -function sourceLineLength(source: Source, names: ReadonlyMap): number { +function sourceLineLength (source: Source, names: ReadonlyMap): number { switch (source.kind) { case "text": return source.text.length; @@ -158,10 +163,10 @@ function sourceLineLength(source: Source, names: ReadonlyMap): num } } -export function serializeRenderResult( +export function serializeRenderResult ( rootSource: Source, names: ReadonlyMap, - indentation: string + indentation: string, ): SerializedRenderResult { let indent = 0; let indentNeeded = 0; @@ -170,28 +175,28 @@ export function serializeRenderResult( let currentLine: string[] = []; const annotations: Annotation[] = []; - function indentIfNeeded(): void { + function indentIfNeeded (): void { if (indentNeeded === 0) return; currentLine.push(repeatString(indentation, indentNeeded)); indentNeeded = 0; } - function flattenCurrentLine(): string { + function flattenCurrentLine (): string { const str = currentLine.join(""); currentLine = [str]; return str; } - function currentLocation(): Location { + function currentLocation (): Location { return { line: lines.length, column: flattenCurrentLine().length }; } - function finishLine(): void { + function finishLine (): void { lines.push(flattenCurrentLine()); currentLine = []; } - function serializeToStringArray(source: Source): void { + function serializeToStringArray (source: Source): void { switch (source.kind) { case "text": indentIfNeeded(); @@ -206,6 +211,7 @@ export function serializeRenderResult( for (const s of source.sequence) { serializeToStringArray(s); } + break; case "table": const t = source.table; @@ -218,6 +224,7 @@ export function serializeRenderResult( for (let i = 0; i < numColumns; i++) { columnWidths.push(defined(iterableMax(widths.map(l => withDefault(l[i], 0))))); } + for (let y = 0; y < numRows; y++) { indentIfNeeded(); const row = defined(t[y]); @@ -231,11 +238,13 @@ export function serializeRenderResult( currentLine.push(repeatString(" ", colWidth - srcWidth)); } } + if (y < numRows - 1) { finishLine(); indentNeeded = indent; } } + break; case "annotated": const start = currentLocation(); @@ -264,31 +273,34 @@ export function serializeRenderResult( return { lines, annotations: annotations }; } -export type MultiWord = { - source: Sourcelike; +export interface MultiWord { needsParens: boolean; -}; + source: Sourcelike; +} -export function singleWord(...source: Sourcelike[]): MultiWord { +export function singleWord (...source: Sourcelike[]): MultiWord { return { source, needsParens: false }; } -export function multiWord(separator: Sourcelike, ...words: Sourcelike[]): MultiWord { +export function multiWord (separator: Sourcelike, ...words: Sourcelike[]): MultiWord { assert(words.length > 0, "Zero words is not multiple"); if (words.length === 1) { return singleWord(words[0]); } + const items: Sourcelike[] = []; for (let i = 0; i < words.length; i++) { if (i > 0) items.push(separator); items.push(words[i]); } + return { source: items, needsParens: true }; } -export function parenIfNeeded({ source, needsParens }: MultiWord): Sourcelike { +export function parenIfNeeded ({ source, needsParens }: MultiWord): Sourcelike { if (needsParens) { return ["(", source, ")"]; } + return source; } diff --git a/packages/quicktype-core/src/TargetLanguage.ts b/packages/quicktype-core/src/TargetLanguage.ts index f1c3a90bf..4d9dbce50 100644 --- a/packages/quicktype-core/src/TargetLanguage.ts +++ b/packages/quicktype-core/src/TargetLanguage.ts @@ -1,92 +1,97 @@ import { mapMap } from "collection-utils"; -import { TypeGraph } from "./TypeGraph"; -import { Renderer, RenderContext } from "./Renderer"; -import { OptionDefinition, Option } from "./RendererOptions"; -import { serializeRenderResult, SerializedRenderResult } from "./Source"; -import { StringTypeMapping } from "./TypeBuilder"; +import { type TypeGraph } from "./TypeGraph"; +import { type Renderer, type RenderContext } from "./Renderer"; +import { type OptionDefinition, type Option } from "./RendererOptions"; +import { type SerializedRenderResult } from "./Source"; +import { serializeRenderResult } from "./Source"; +import { type StringTypeMapping } from "./TypeBuilder"; import { defined } from "./support/Support"; -import { ConvenienceRenderer } from "./ConvenienceRenderer"; -import { Type } from "./Type"; -import { DateTimeRecognizer, DefaultDateTimeRecognizer } from "./DateTime"; +import { type ConvenienceRenderer } from "./ConvenienceRenderer"; +import { type Type } from "./Type"; +import { type DateTimeRecognizer} from "./DateTime"; +import { DefaultDateTimeRecognizer } from "./DateTime"; import { type Comment } from "./support/Comments"; export type MultiFileRenderResult = ReadonlyMap; export abstract class TargetLanguage { - constructor( + constructor ( readonly displayName: string, readonly names: string[], - readonly extension: string + readonly extension: string, ) {} - protected abstract getOptions(): Option[]; + protected abstract getOptions (): Array>; - get optionDefinitions(): OptionDefinition[] { + get optionDefinitions (): OptionDefinition[] { return this.getOptions().map(o => o.definition); } - get cliOptionDefinitions(): { display: OptionDefinition[]; actual: OptionDefinition[] } { + get cliOptionDefinitions (): { actual: OptionDefinition[], display: OptionDefinition[], } { let actual: OptionDefinition[] = []; let display: OptionDefinition[] = []; for (const { cliDefinitions } of this.getOptions()) { actual = actual.concat(cliDefinitions.actual); display = display.concat(cliDefinitions.display); } + return { actual, display }; } - get name(): string { + get name (): string { return defined(this.names[0]); } - protected abstract makeRenderer(renderContext: RenderContext, optionValues: { [name: string]: any }): Renderer; + protected abstract makeRenderer (renderContext: RenderContext, optionValues: { [name: string]: any, }): Renderer; - renderGraphAndSerialize( + renderGraphAndSerialize ( typeGraph: TypeGraph, givenOutputFilename: string, alphabetizeProperties: boolean, leadingComments: Comment[] | undefined, - rendererOptions: { [name: string]: any }, - indentation?: string + rendererOptions: { [name: string]: any, }, + indentation?: string, ): MultiFileRenderResult { if (indentation === undefined) { indentation = this.defaultIndentation; } + const renderContext = { typeGraph, leadingComments }; const renderer = this.makeRenderer(renderContext, rendererOptions); if ((renderer as any).setAlphabetizeProperties !== undefined) { (renderer as ConvenienceRenderer).setAlphabetizeProperties(alphabetizeProperties); } + const renderResult = renderer.render(givenOutputFilename); return mapMap(renderResult.sources, s => serializeRenderResult(s, renderResult.names, defined(indentation))); } - protected get defaultIndentation(): string { + protected get defaultIndentation (): string { return " "; } - get stringTypeMapping(): StringTypeMapping { + get stringTypeMapping (): StringTypeMapping { return new Map(); } - get supportsOptionalClassProperties(): boolean { + get supportsOptionalClassProperties (): boolean { return false; } - get supportsUnionsWithBothNumberTypes(): boolean { + get supportsUnionsWithBothNumberTypes (): boolean { return false; } - get supportsFullObjectType(): boolean { + get supportsFullObjectType (): boolean { return false; } - needsTransformerForType(_t: Type): boolean { + needsTransformerForType (_t: Type): boolean { return false; } - get dateTimeRecognizer(): DateTimeRecognizer { + get dateTimeRecognizer (): DateTimeRecognizer { return new DefaultDateTimeRecognizer(); } } diff --git a/packages/quicktype-core/src/Transformers.ts b/packages/quicktype-core/src/Transformers.ts index e64752358..0b978b771 100644 --- a/packages/quicktype-core/src/Transformers.ts +++ b/packages/quicktype-core/src/Transformers.ts @@ -6,143 +6,146 @@ import { addHashCode, definedMapWithDefault, arraySortByInto, - hashString + hashString, } from "collection-utils"; -import { UnionType, Type, EnumType, PrimitiveType, TypeKind } from "./Type"; +import { type Type, type TypeKind } from "./Type"; +import { UnionType, EnumType, PrimitiveType } from "./Type"; import { TypeAttributeKind } from "./attributes/TypeAttributes"; import { panic, assert, indentationString } from "./support/Support"; -import { BaseGraphRewriteBuilder } from "./GraphRewriting"; -import { TypeRef, derefTypeRef, TypeGraph } from "./TypeGraph"; +import { type BaseGraphRewriteBuilder } from "./GraphRewriting"; +import { type TypeRef, type TypeGraph } from "./TypeGraph"; +import { derefTypeRef } from "./TypeGraph"; -function debugStringForType(t: Type): string { +function debugStringForType (t: Type): string { const target = followTargetType(t); if (t === target) { return t.kind; } + return `${t.kind} (${target.kind})`; } -function getNumberOfNodes(xfer: Transformer | undefined): number { +function getNumberOfNodes (xfer: Transformer | undefined): number { return definedMapWithDefault(xfer, 0, x => x.getNumberOfNodes()); } export abstract class Transformer { - constructor(readonly kind: string, protected readonly graph: TypeGraph, readonly sourceTypeRef: TypeRef) {} + constructor (readonly kind: string, protected readonly graph: TypeGraph, readonly sourceTypeRef: TypeRef) {} - get sourceType(): Type { + get sourceType (): Type { return derefTypeRef(this.sourceTypeRef, this.graph); } /** This must return a newly constructed set. */ - getChildren(): Set { + getChildren (): Set { return new Set([this.sourceType]); } - getNumberOfNodes(): number { + getNumberOfNodes (): number { return 1; } - abstract get canFail(): boolean; + abstract get canFail (): boolean; - abstract reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer; + abstract reverse (targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer; abstract reconstitute(builder: TBuilder): Transformer; - equals(other: any): boolean { + equals (other: any): boolean { if (!(other instanceof Transformer)) return false; return this.sourceTypeRef === other.sourceTypeRef; } - hashCode(): number { + hashCode (): number { return hashCodeOf(this.sourceTypeRef); } - protected debugDescription(): string { + protected debugDescription (): string { return `${debugStringForType(this.sourceType)} -> ${this.kind}`; } - protected debugPrintContinuations(_indent: number): void { + protected debugPrintContinuations (_indent: number): void { return; } - debugPrint(indent: number): void { + debugPrint (indent: number): void { console.log(indentationString(indent) + this.debugDescription()); this.debugPrintContinuations(indent + 1); } } export abstract class ProducerTransformer extends Transformer { - constructor(kind: string, graph: TypeGraph, sourceTypeRef: TypeRef, readonly consumer: Transformer | undefined) { + constructor (kind: string, graph: TypeGraph, sourceTypeRef: TypeRef, readonly consumer: Transformer | undefined) { super(kind, graph, sourceTypeRef); } - getChildren(): Set { + getChildren (): Set { const children = super.getChildren(); if (this.consumer === undefined) return children; return setUnionInto(children, this.consumer.getChildren()); } - getNumberOfNodes(): number { + getNumberOfNodes (): number { return super.getNumberOfNodes() + getNumberOfNodes(this.consumer); } - equals(other: any): boolean { + equals (other: any): boolean { if (!super.equals(other)) return false; if (!(other instanceof ProducerTransformer)) return false; return areEqual(this.consumer, other.consumer); } - hashCode(): number { + hashCode (): number { const h = super.hashCode(); return addHashCode(h, hashCodeOf(this.consumer)); } - protected debugPrintContinuations(indent: number): void { + protected debugPrintContinuations (indent: number): void { if (this.consumer === undefined) return; this.consumer.debugPrint(indent); } } export abstract class MatchTransformer extends Transformer { - constructor(kind: string, graph: TypeGraph, sourceTypeRef: TypeRef, readonly transformer: Transformer) { + constructor (kind: string, graph: TypeGraph, sourceTypeRef: TypeRef, readonly transformer: Transformer) { super(kind, graph, sourceTypeRef); } - getChildren(): Set { + getChildren (): Set { return setUnionInto(super.getChildren(), this.transformer.getChildren()); } - getNumberOfNodes(): number { + getNumberOfNodes (): number { return super.getNumberOfNodes() + this.transformer.getNumberOfNodes(); } - equals(other: any): boolean { + equals (other: any): boolean { if (!super.equals(other)) return false; if (!(other instanceof MatchTransformer)) return false; return this.transformer.equals(other.transformer); } - hashCode(): number { + hashCode (): number { const h = super.hashCode(); return addHashCode(h, this.transformer.hashCode()); } - protected debugPrintContinuations(indent: number): void { + protected debugPrintContinuations (indent: number): void { this.transformer.debugPrint(indent); } } export class DecodingTransformer extends ProducerTransformer { - constructor(graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined) { + constructor (graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined) { super("decode", graph, sourceTypeRef, consumer); } - get canFail(): boolean { + get canFail (): boolean { return false; } - reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + reverse (targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { if (continuationTransformer !== undefined) { return panic("Reversing a decoding transformer cannot have a continuation"); } @@ -152,7 +155,7 @@ export class DecodingTransformer extends ProducerTransformer { } else { return this.consumer.reverse( targetTypeRef, - new EncodingTransformer(this.graph, this.consumer.sourceTypeRef) + new EncodingTransformer(this.graph, this.consumer.sourceTypeRef), ); } } @@ -161,26 +164,26 @@ export class DecodingTransformer extends ProducerTransformer { return new DecodingTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), - definedMap(this.consumer, xfer => xfer.reconstitute(builder)) + definedMap(this.consumer, xfer => xfer.reconstitute(builder)), ); } - equals(other: any): boolean { + equals (other: any): boolean { if (!super.equals(other)) return false; return other instanceof DecodingTransformer; } } export class EncodingTransformer extends Transformer { - constructor(graph: TypeGraph, sourceTypeRef: TypeRef) { + constructor (graph: TypeGraph, sourceTypeRef: TypeRef) { super("encode", graph, sourceTypeRef); } - get canFail(): boolean { + get canFail (): boolean { return false; } - reverse(_targetTypeRef: TypeRef, _continuationTransformer: Transformer | undefined): Transformer { + reverse (_targetTypeRef: TypeRef, _continuationTransformer: Transformer | undefined): Transformer { return panic("Can't reverse encoding transformer"); } @@ -188,7 +191,7 @@ export class EncodingTransformer extends Transformer { return new EncodingTransformer(builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef)); } - equals(other: any): boolean { + equals (other: any): boolean { if (!super.equals(other)) return false; if (!(other instanceof EncodingTransformer)) return false; return true; @@ -196,35 +199,35 @@ export class EncodingTransformer extends Transformer { } export class ArrayDecodingTransformer extends ProducerTransformer { - constructor( + constructor ( graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined, private readonly _itemTargetTypeRef: TypeRef, - readonly itemTransformer: Transformer + readonly itemTransformer: Transformer, ) { super("decode-array", graph, sourceTypeRef, consumer); } - getChildren(): Set { + getChildren (): Set { const children = super.getChildren(); children.add(this.itemTargetType); return setUnionInto(children, this.itemTransformer.getChildren()); } - getNumberOfNodes(): number { + getNumberOfNodes (): number { return super.getNumberOfNodes() + this.itemTransformer.getNumberOfNodes(); } - get canFail(): boolean { + get canFail (): boolean { return false; } - get itemTargetType(): Type { + get itemTargetType (): Type { return derefTypeRef(this._itemTargetTypeRef, this.graph); } - reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + reverse (targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { if (continuationTransformer !== undefined) { return panic("Reversing a decoding transformer cannot have a continuation"); } @@ -236,7 +239,7 @@ export class ArrayDecodingTransformer extends ProducerTransformer { this.graph, targetTypeRef, this.itemTransformer.sourceTypeRef, - itemTransformer + itemTransformer, ); } else { return this.consumer.reverse( @@ -245,8 +248,8 @@ export class ArrayDecodingTransformer extends ProducerTransformer { this.graph, this.consumer.sourceTypeRef, this.itemTransformer.sourceTypeRef, - itemTransformer - ) + itemTransformer, + ), ); } } @@ -257,59 +260,59 @@ export class ArrayDecodingTransformer extends ProducerTransformer { builder.reconstituteTypeRef(this.sourceTypeRef), definedMap(this.consumer, xfer => xfer.reconstitute(builder)), builder.reconstituteTypeRef(this._itemTargetTypeRef), - this.itemTransformer.reconstitute(builder) + this.itemTransformer.reconstitute(builder), ); } - hashCode(): number { + hashCode (): number { let h = super.hashCode(); h = addHashCode(h, hashCodeOf(this._itemTargetTypeRef)); h = addHashCode(h, this.itemTransformer.hashCode()); return h; } - equals(other: any): boolean { + equals (other: any): boolean { if (!super.equals(other)) return false; if (!(other instanceof ArrayDecodingTransformer)) return false; if (!areEqual(this._itemTargetTypeRef, other._itemTargetTypeRef)) return false; return this.itemTransformer.equals(other.itemTransformer); } - protected debugPrintContinuations(indent: number): void { + protected debugPrintContinuations (indent: number): void { this.itemTransformer.debugPrint(indent); super.debugPrintContinuations(indent); } } export class ArrayEncodingTransformer extends Transformer { - constructor( + constructor ( graph: TypeGraph, sourceTypeRef: TypeRef, private readonly _itemTargetTypeRef: TypeRef, - readonly itemTransformer: Transformer + readonly itemTransformer: Transformer, ) { super("encode-array", graph, sourceTypeRef); } - getChildren(): Set { + getChildren (): Set { const children = super.getChildren(); children.add(this.itemTargetType); return setUnionInto(children, this.itemTransformer.getChildren()); } - getNumberOfNodes(): number { + getNumberOfNodes (): number { return super.getNumberOfNodes() + this.itemTransformer.getNumberOfNodes(); } - get canFail(): boolean { + get canFail (): boolean { return false; } - get itemTargetType(): Type { + get itemTargetType (): Type { return derefTypeRef(this._itemTargetTypeRef, this.graph); } - reverse(_targetTypeRef: TypeRef, _continuationTransformer: Transformer | undefined): Transformer { + reverse (_targetTypeRef: TypeRef, _continuationTransformer: Transformer | undefined): Transformer { return panic("Can't reverse array encoding transformer"); } @@ -318,56 +321,58 @@ export class ArrayEncodingTransformer extends Transformer { builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), builder.reconstituteTypeRef(this._itemTargetTypeRef), - this.itemTransformer.reconstitute(builder) + this.itemTransformer.reconstitute(builder), ); } - hashCode(): number { + hashCode (): number { let h = super.hashCode(); h = addHashCode(h, hashCodeOf(this._itemTargetTypeRef)); return addHashCode(h, this.itemTransformer.hashCode()); } - equals(other: any): boolean { + equals (other: any): boolean { if (!super.equals(other)) return false; if (!(other instanceof ArrayEncodingTransformer)) return false; if (!areEqual(this._itemTargetTypeRef, other._itemTargetTypeRef)) return false; return this.itemTransformer.equals(other.itemTransformer); } - protected debugPrintContinuations(indent: number): void { + protected debugPrintContinuations (indent: number): void { this.itemTransformer.debugPrint(indent); super.debugPrintContinuations(indent); } } export class ChoiceTransformer extends Transformer { - constructor(graph: TypeGraph, sourceTypeRef: TypeRef, public readonly transformers: ReadonlyArray) { + constructor (graph: TypeGraph, sourceTypeRef: TypeRef, public readonly transformers: readonly Transformer[]) { super("choice", graph, sourceTypeRef); assert(transformers.length > 0, "Choice must have at least one transformer"); } - getChildren(): Set { + getChildren (): Set { let children = super.getChildren(); for (const xfer of this.transformers) { setUnionInto(children, xfer.getChildren()); } + return children; } - getNumberOfNodes(): number { + getNumberOfNodes (): number { let n = 0; for (const xfer of this.transformers) { n += xfer.getNumberOfNodes(); } + return super.getNumberOfNodes() + n; } - get canFail(): boolean { + get canFail (): boolean { return this.transformers.some(xfer => xfer.canFail); } - reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + reverse (targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { const transformers = this.transformers.map(xfer => xfer.reverse(targetTypeRef, continuationTransformer)); if (transformers.every(xfer => xfer instanceof UnionMemberMatchTransformer)) { const memberMatchers = transformers as UnionMemberMatchTransformer[]; @@ -378,10 +383,11 @@ export class ChoiceTransformer extends Transformer { this.graph, targetTypeRef, new ChoiceTransformer(this.graph, subTransformers[0].sourceTypeRef, subTransformers), - first.memberTypeRef + first.memberTypeRef, ); } } + return new ChoiceTransformer(this.graph, targetTypeRef, transformers); } @@ -389,22 +395,22 @@ export class ChoiceTransformer extends Transformer { return new ChoiceTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), - this.transformers.map(xfer => xfer.reconstitute(builder)) + this.transformers.map(xfer => xfer.reconstitute(builder)), ); } - equals(other: any): boolean { + equals (other: any): boolean { if (!super.equals(other)) return false; if (!(other instanceof ChoiceTransformer)) return false; return areEqual(this.transformers, other.transformers); } - hashCode(): number { + hashCode (): number { const h = super.hashCode(); return addHashCode(h, hashCodeOf(this.transformers)); } - protected debugPrintContinuations(indent: number): void { + protected debugPrintContinuations (indent: number): void { for (const xfer of this.transformers) { xfer.debugPrint(indent); } @@ -412,7 +418,7 @@ export class ChoiceTransformer extends Transformer { } export class DecodingChoiceTransformer extends Transformer { - constructor( + constructor ( graph: TypeGraph, sourceTypeRef: TypeRef, readonly nullTransformer: Transformer | undefined, @@ -421,14 +427,14 @@ export class DecodingChoiceTransformer extends Transformer { readonly boolTransformer: Transformer | undefined, readonly stringTransformer: Transformer | undefined, readonly arrayTransformer: Transformer | undefined, - readonly objectTransformer: Transformer | undefined + readonly objectTransformer: Transformer | undefined, ) { super("decoding-choice", graph, sourceTypeRef); } - get transformers(): ReadonlyArray { + get transformers (): readonly Transformer[] { const transformers: Transformer[] = []; - function add(xfer: Transformer | undefined) { + function add (xfer: Transformer | undefined) { if (xfer === undefined) return; transformers.push(xfer); } @@ -444,36 +450,38 @@ export class DecodingChoiceTransformer extends Transformer { return transformers; } - getChildren(): Set { + getChildren (): Set { let children = super.getChildren(); for (const xfer of this.transformers) { setUnionInto(children, xfer.getChildren()); } + return children; } - getNumberOfNodes(): number { + getNumberOfNodes (): number { let n = super.getNumberOfNodes(); for (const xfer of this.transformers) { n += getNumberOfNodes(xfer); } + return n; } - get canFail(): boolean { + get canFail (): boolean { return false; } - reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + reverse (targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { assert( continuationTransformer === undefined, - "Reversing a decoding transformer can't have a target transformer" + "Reversing a decoding transformer can't have a target transformer", ); let transformers = new Map(); let memberMatchTransformers = new Map(); - function addCase(reversed: Transformer) { + function addCase (reversed: Transformer) { if (reversed instanceof UnionMemberMatchTransformer) { const memberType = reversed.memberType; let arr = memberMatchTransformers.get(memberType); @@ -481,6 +489,7 @@ export class DecodingChoiceTransformer extends Transformer { arr = []; memberMatchTransformers.set(memberType, arr); } + arr.push(reversed); } else { const kind = reversed.sourceType.kind; @@ -489,19 +498,21 @@ export class DecodingChoiceTransformer extends Transformer { arr = []; transformers.set(kind, arr); } + arr.push(reversed); } } - function reverseAndAdd(transformer: Transformer) { + function reverseAndAdd (transformer: Transformer) { const reversed = transformer.reverse(targetTypeRef, undefined); - let cases: ReadonlyArray = []; + let cases: readonly Transformer[] = []; // Flatten nested ChoiceTransformers if (reversed instanceof ChoiceTransformer) { cases = reversed.transformers; } else { cases = [reversed]; } + for (const xfer of cases) { addCase(xfer); } @@ -514,7 +525,7 @@ export class DecodingChoiceTransformer extends Transformer { // If there are non-failing transformers, we ignore the ones that can fail and // just pick the "simplest" non-failing one, being the one with the least number // of nodes. - function filter(xfers: Transformer[]): Transformer[] { + function filter (xfers: Transformer[]): Transformer[] { assert(xfers.length > 0, "Must have at least one transformer"); const nonfailing = xfers.filter(xfer => { @@ -533,7 +544,7 @@ export class DecodingChoiceTransformer extends Transformer { const smallest = arraySortByInto( nonfailing.map(x => [x.getNumberOfNodes(), x] as [number, Transformer]), - ([c, _]) => c + ([c, _]) => c, )[0][1]; return [smallest]; } @@ -552,7 +563,7 @@ export class DecodingChoiceTransformer extends Transformer { } reconstitute(builder: TBuilder): Transformer { - function reconstitute(xf: Transformer | undefined) { + function reconstitute (xf: Transformer | undefined) { if (xf === undefined) return undefined; return xf.reconstitute(builder); } @@ -566,11 +577,11 @@ export class DecodingChoiceTransformer extends Transformer { reconstitute(this.boolTransformer), reconstitute(this.stringTransformer), reconstitute(this.arrayTransformer), - reconstitute(this.objectTransformer) + reconstitute(this.objectTransformer), ); } - equals(other: any): boolean { + equals (other: any): boolean { if (!super.equals(other)) return false; if (!(other instanceof DecodingChoiceTransformer)) return false; if (!areEqual(this.nullTransformer, other.nullTransformer)) return false; @@ -583,7 +594,7 @@ export class DecodingChoiceTransformer extends Transformer { return true; } - hashCode(): number { + hashCode (): number { let h = super.hashCode(); h = addHashCode(h, hashCodeOf(this.nullTransformer)); h = addHashCode(h, hashCodeOf(this.integerTransformer)); @@ -595,7 +606,7 @@ export class DecodingChoiceTransformer extends Transformer { return h; } - protected debugPrintContinuations(indent: number): void { + protected debugPrintContinuations (indent: number): void { for (const xfer of this.transformers) { xfer.debugPrint(indent); } @@ -603,31 +614,32 @@ export class DecodingChoiceTransformer extends Transformer { } export class UnionMemberMatchTransformer extends MatchTransformer { - constructor(graph: TypeGraph, sourceTypeRef: TypeRef, transformer: Transformer, readonly memberTypeRef: TypeRef) { + constructor (graph: TypeGraph, sourceTypeRef: TypeRef, transformer: Transformer, readonly memberTypeRef: TypeRef) { super("union-member-match", graph, sourceTypeRef, transformer); } - get sourceType(): UnionType { + get sourceType (): UnionType { const t = derefTypeRef(this.sourceTypeRef, this.graph); if (!(t instanceof UnionType)) { return panic("The source of a union member match transformer must be a union type"); } + return t; } - get canFail(): boolean { + get canFail (): boolean { return true; } - get memberType(): Type { + get memberType (): Type { return derefTypeRef(this.memberTypeRef, this.graph); } - getChildren(): Set { + getChildren (): Set { return super.getChildren().add(this.memberType); } - reverse(_targetTypeRef: TypeRef, _continuationTransformer: Transformer | undefined): Transformer { + reverse (_targetTypeRef: TypeRef, _continuationTransformer: Transformer | undefined): Transformer { return panic("Can't reverse union member match transformer"); } @@ -636,22 +648,22 @@ export class UnionMemberMatchTransformer extends MatchTransformer { builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), this.transformer.reconstitute(builder), - builder.reconstituteTypeRef(this.memberTypeRef) + builder.reconstituteTypeRef(this.memberTypeRef), ); } - equals(other: any): boolean { + equals (other: any): boolean { if (!super.equals(other)) return false; if (!(other instanceof UnionMemberMatchTransformer)) return false; return this.memberTypeRef === other.memberTypeRef; } - hashCode(): number { + hashCode (): number { const h = super.hashCode(); return addHashCode(h, hashCodeOf(this.memberTypeRef)); } - protected debugDescription(): string { + protected debugDescription (): string { return `${super.debugDescription()} - member: ${debugStringForType(this.memberType)}`; } } @@ -660,31 +672,32 @@ export class UnionMemberMatchTransformer extends MatchTransformer { * This matches strings and enum cases. */ export class StringMatchTransformer extends MatchTransformer { - constructor(graph: TypeGraph, sourceTypeRef: TypeRef, transformer: Transformer, readonly stringCase: string) { + constructor (graph: TypeGraph, sourceTypeRef: TypeRef, transformer: Transformer, readonly stringCase: string) { super("string-match", graph, sourceTypeRef, transformer); } - get sourceType(): EnumType | PrimitiveType { + get sourceType (): EnumType | PrimitiveType { const t = derefTypeRef(this.sourceTypeRef, this.graph); if (!(t instanceof EnumType) && !(t instanceof PrimitiveType && t.kind === "string")) { return panic("The source of a string match transformer must be an enum or string type"); } + return t; } - get canFail(): boolean { + get canFail (): boolean { return true; } - reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + reverse (targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { return this.transformer.reverse( targetTypeRef, new StringProducerTransformer( this.graph, this.transformer.sourceTypeRef, continuationTransformer, - this.stringCase - ) + this.stringCase, + ), ); } @@ -693,36 +706,36 @@ export class StringMatchTransformer extends MatchTransformer { builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), this.transformer.reconstitute(builder), - this.stringCase + this.stringCase, ); } - equals(other: any): boolean { + equals (other: any): boolean { if (!super.equals(other)) return false; if (!(other instanceof StringMatchTransformer)) return false; return this.stringCase !== other.stringCase; } - hashCode(): number { + hashCode (): number { const h = super.hashCode(); return addHashCode(h, hashString(this.stringCase)); } - protected debugDescription(): string { + protected debugDescription (): string { return `${super.debugDescription()} - case: ${this.stringCase}`; } } export class UnionInstantiationTransformer extends Transformer { - constructor(graph: TypeGraph, sourceTypeRef: TypeRef) { + constructor (graph: TypeGraph, sourceTypeRef: TypeRef) { super("union-instantiation", graph, sourceTypeRef); } - get canFail(): boolean { + get canFail (): boolean { return false; } - reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + reverse (targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { if (continuationTransformer === undefined) { return panic("Union instantiation transformer reverse must have a continuation"); } @@ -734,7 +747,7 @@ export class UnionInstantiationTransformer extends Transformer { return new UnionInstantiationTransformer(builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef)); } - equals(other: any): boolean { + equals (other: any): boolean { if (!super.equals(other)) return false; return other instanceof UnionInstantiationTransformer; } @@ -744,15 +757,15 @@ export class UnionInstantiationTransformer extends Transformer { * Produces a string or an enum case. */ export class StringProducerTransformer extends ProducerTransformer { - constructor(graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined, readonly result: string) { + constructor (graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined, readonly result: string) { super("string-producer", graph, sourceTypeRef, consumer); } - get canFail(): boolean { + get canFail (): boolean { return false; } - reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + reverse (targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { if (continuationTransformer === undefined) { return panic("Reversing a string producer transformer must have a continuation"); } @@ -766,8 +779,8 @@ export class StringProducerTransformer extends ProducerTransformer { this.graph, this.consumer.sourceTypeRef, continuationTransformer, - this.result - ) + this.result, + ), ); } } @@ -777,42 +790,42 @@ export class StringProducerTransformer extends ProducerTransformer { builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), definedMap(this.consumer, xfer => xfer.reconstitute(builder)), - this.result + this.result, ); } - equals(other: any): boolean { + equals (other: any): boolean { if (!super.equals(other)) return false; if (!(other instanceof StringProducerTransformer)) return false; return this.result === other.result; } - hashCode(): number { + hashCode (): number { const h = super.hashCode(); return addHashCode(h, hashCodeOf(this.consumer)); } - protected debugDescription(): string { + protected debugDescription (): string { return `${super.debugDescription()} - result: ${this.result}`; } } export class ParseStringTransformer extends ProducerTransformer { - constructor(graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined) { + constructor (graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined) { super("parse-string", graph, sourceTypeRef, consumer); } - get canFail(): boolean { + get canFail (): boolean { return true; } - reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + reverse (targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { if (this.consumer === undefined) { return new StringifyTransformer(this.graph, targetTypeRef, continuationTransformer); } else { return this.consumer.reverse( targetTypeRef, - new StringifyTransformer(this.graph, this.consumer.sourceTypeRef, continuationTransformer) + new StringifyTransformer(this.graph, this.consumer.sourceTypeRef, continuationTransformer), ); } } @@ -821,32 +834,32 @@ export class ParseStringTransformer extends ProducerTransformer { return new ParseStringTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), - definedMap(this.consumer, xfer => xfer.reconstitute(builder)) + definedMap(this.consumer, xfer => xfer.reconstitute(builder)), ); } - equals(other: any): boolean { + equals (other: any): boolean { if (!super.equals(other)) return false; return other instanceof ParseStringTransformer; } } export class StringifyTransformer extends ProducerTransformer { - constructor(graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined) { + constructor (graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined) { super("stringify", graph, sourceTypeRef, consumer); } - get canFail(): boolean { + get canFail (): boolean { return false; } - reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + reverse (targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { if (this.consumer === undefined) { return new ParseStringTransformer(this.graph, targetTypeRef, continuationTransformer); } else { return this.consumer.reverse( targetTypeRef, - new ParseStringTransformer(this.graph, this.consumer.sourceTypeRef, continuationTransformer) + new ParseStringTransformer(this.graph, this.consumer.sourceTypeRef, continuationTransformer), ); } } @@ -855,39 +868,39 @@ export class StringifyTransformer extends ProducerTransformer { return new StringifyTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), - definedMap(this.consumer, xfer => xfer.reconstitute(builder)) + definedMap(this.consumer, xfer => xfer.reconstitute(builder)), ); } - equals(other: any): boolean { + equals (other: any): boolean { if (!super.equals(other)) return false; return other instanceof StringifyTransformer; } } export class MinMaxLengthCheckTransformer extends ProducerTransformer { - constructor( + constructor ( graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined, readonly minLength: number | undefined, - readonly maxLength: number | undefined + readonly maxLength: number | undefined, ) { super("min-max-length-check", graph, sourceTypeRef, consumer); } - get canFail(): boolean { + get canFail (): boolean { return true; } - reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + reverse (targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { if (this.consumer === undefined) { return new MinMaxLengthCheckTransformer( this.graph, targetTypeRef, continuationTransformer, this.minLength, - this.maxLength + this.maxLength, ); } else { return this.consumer.reverse( @@ -897,8 +910,8 @@ export class MinMaxLengthCheckTransformer extends ProducerTransformer { this.consumer.sourceTypeRef, continuationTransformer, this.minLength, - this.maxLength - ) + this.maxLength, + ), ); } } @@ -909,11 +922,11 @@ export class MinMaxLengthCheckTransformer extends ProducerTransformer { builder.reconstituteTypeRef(this.sourceTypeRef), definedMap(this.consumer, xfer => xfer.reconstitute(builder)), this.minLength, - this.maxLength + this.maxLength, ); } - equals(other: any): boolean { + equals (other: any): boolean { if (!super.equals(other)) return false; return ( other instanceof MinMaxLengthCheckTransformer && @@ -924,28 +937,28 @@ export class MinMaxLengthCheckTransformer extends ProducerTransformer { } export class MinMaxValueTransformer extends ProducerTransformer { - constructor( + constructor ( graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined, readonly minimum: number | undefined, - readonly maximum: number | undefined + readonly maximum: number | undefined, ) { super("min-max-value-check", graph, sourceTypeRef, consumer); } - get canFail(): boolean { + get canFail (): boolean { return true; } - reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + reverse (targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { if (this.consumer === undefined) { return new MinMaxValueTransformer( this.graph, targetTypeRef, continuationTransformer, this.minimum, - this.maximum + this.maximum, ); } else { return this.consumer.reverse( @@ -955,8 +968,8 @@ export class MinMaxValueTransformer extends ProducerTransformer { this.consumer.sourceTypeRef, continuationTransformer, this.minimum, - this.maximum - ) + this.maximum, + ), ); } } @@ -967,11 +980,11 @@ export class MinMaxValueTransformer extends ProducerTransformer { builder.reconstituteTypeRef(this.sourceTypeRef), definedMap(this.consumer, xfer => xfer.reconstitute(builder)), this.minimum, - this.maximum + this.maximum, ); } - equals(other: any): boolean { + equals (other: any): boolean { if (!super.equals(other)) return false; return ( other instanceof MinMaxValueTransformer && this.minimum === other.minimum && this.maximum === other.maximum @@ -980,29 +993,29 @@ export class MinMaxValueTransformer extends ProducerTransformer { } export class Transformation { - constructor( + constructor ( private readonly _graph: TypeGraph, private readonly _targetTypeRef: TypeRef, - readonly transformer: Transformer + readonly transformer: Transformer, ) {} - get sourceType(): Type { + get sourceType (): Type { return this.transformer.sourceType; } - get targetType(): Type { + get targetType (): Type { return derefTypeRef(this._targetTypeRef, this._graph); } - get reverse(): Transformation { + get reverse (): Transformation { return new Transformation( this._graph, this.transformer.sourceTypeRef, - this.transformer.reverse(this._targetTypeRef, undefined) + this.transformer.reverse(this._targetTypeRef, undefined), ); } - getChildren(): Set { + getChildren (): Set { return this.transformer.getChildren().add(this.targetType); } @@ -1010,41 +1023,41 @@ export class Transformation { return new Transformation( builder.typeGraph, builder.reconstituteTypeRef(this._targetTypeRef), - this.transformer.reconstitute(builder) + this.transformer.reconstitute(builder), ); } - equals(other: any): boolean { + equals (other: any): boolean { if (!(other instanceof Transformation)) return false; return this._targetTypeRef === other._targetTypeRef && this.transformer.equals(other.transformer); } - hashCode(): number { + hashCode (): number { let h = hashCodeOf(this._targetTypeRef); h = addHashCode(h, this.transformer.hashCode()); return h; } - debugPrint(): void { + debugPrint (): void { this.transformer.debugPrint(0); console.log(`-> ${debugStringForType(this.targetType)}`); } } class TransformationTypeAttributeKind extends TypeAttributeKind { - constructor() { + constructor () { super("transformation"); } - appliesToTypeKind(_kind: TypeKind): boolean { + appliesToTypeKind (_kind: TypeKind): boolean { return true; } - get inIdentity(): boolean { + get inIdentity (): boolean { return true; } - children(xf: Transformation): Set { + children (xf: Transformation): Set { return xf.getChildren(); } @@ -1052,18 +1065,18 @@ class TransformationTypeAttributeKind extends TypeAttributeKind return xf.reconstitute(builder); } - stringify(_: Transformation): string { + stringify (_: Transformation): string { return "transformation"; } } export const transformationTypeAttributeKind: TypeAttributeKind = new TransformationTypeAttributeKind(); -export function transformationForType(t: Type): Transformation | undefined { +export function transformationForType (t: Type): Transformation | undefined { return transformationTypeAttributeKind.tryGetInAttributes(t.getAttributes()); } -export function followTargetType(t: Type): Type { +export function followTargetType (t: Type): Type { for (;;) { const xf = transformationForType(t); if (xf === undefined) return t; diff --git a/packages/quicktype-core/src/Type.ts b/packages/quicktype-core/src/Type.ts index 7a16f06d3..6c6542e08 100644 --- a/packages/quicktype-core/src/Type.ts +++ b/packages/quicktype-core/src/Type.ts @@ -18,15 +18,17 @@ import { hashCodeInit, addHashCode, hasOwnProperty, - mapFromObject + mapFromObject, } from "collection-utils"; import { defined, panic, assert } from "./support/Support"; -import { TypeReconstituter, BaseGraphRewriteBuilder } from "./GraphRewriting"; -import { TypeNames, namesTypeAttributeKind } from "./attributes/TypeNames"; -import { TypeAttributes } from "./attributes/TypeAttributes"; +import { type TypeReconstituter, type BaseGraphRewriteBuilder } from "./GraphRewriting"; +import { type TypeNames} from "./attributes/TypeNames"; +import { namesTypeAttributeKind } from "./attributes/TypeNames"; +import { type TypeAttributes } from "./attributes/TypeAttributes"; import { messageAssert } from "./Messages"; -import { TypeRef, attributesForTypeRef, derefTypeRef, TypeGraph, typeRefIndex } from "./TypeGraph"; +import { type TypeRef, type TypeGraph} from "./TypeGraph"; +import { attributesForTypeRef, derefTypeRef, typeRefIndex } from "./TypeGraph"; import { uriInferenceAttributesProducer } from "./attributes/URIAttributes"; /** @@ -37,11 +39,11 @@ import { uriInferenceAttributesProducer } from "./attributes/URIAttributes"; * For transformed type kinds that map to an existing primitive type, `primitive` * must specify that type kind. */ -export type TransformedStringTypeTargets = { +export interface TransformedStringTypeTargets { + attributesProducer?: (s: string) => TypeAttributes; jsonSchema: string; primitive: PrimitiveNonStringTypeKind | undefined; - attributesProducer?: (s: string) => TypeAttributes; -}; +} /** * All the transformed string type kinds and the JSON Schema formats and @@ -56,13 +58,13 @@ const transformedStringTypeTargetTypeKinds = { uuid: { jsonSchema: "uuid", primitive: undefined }, uri: { jsonSchema: "uri", primitive: undefined, attributesProducer: uriInferenceAttributesProducer }, "integer-string": { jsonSchema: "integer", primitive: "integer" } as TransformedStringTypeTargets, - "bool-string": { jsonSchema: "boolean", primitive: "bool" } as TransformedStringTypeTargets + "bool-string": { jsonSchema: "boolean", primitive: "bool" } as TransformedStringTypeTargets, }; export const transformedStringTypeTargetTypeKindsMap = mapFromObject( transformedStringTypeTargetTypeKinds as { - [kind: string]: TransformedStringTypeTargets; - } + [kind: string]: TransformedStringTypeTargets, + }, ); export type TransformedStringTypeKind = keyof typeof transformedStringTypeTargetTypeKinds; @@ -74,32 +76,32 @@ export type TypeKind = PrimitiveTypeKind | NamedTypeKind | "array" | "object" | export type ObjectTypeKind = "object" | "map" | "class"; export const transformedStringTypeKinds = new Set( - Object.getOwnPropertyNames(transformedStringTypeTargetTypeKinds) + Object.getOwnPropertyNames(transformedStringTypeTargetTypeKinds), ) as ReadonlySet; -export function isPrimitiveStringTypeKind(kind: string): kind is PrimitiveStringTypeKind { +export function isPrimitiveStringTypeKind (kind: string): kind is PrimitiveStringTypeKind { return kind === "string" || hasOwnProperty(transformedStringTypeTargetTypeKinds, kind); } -export function targetTypeKindForTransformedStringTypeKind( - kind: PrimitiveStringTypeKind +export function targetTypeKindForTransformedStringTypeKind ( + kind: PrimitiveStringTypeKind, ): PrimitiveNonStringTypeKind | undefined { const target = transformedStringTypeTargetTypeKindsMap.get(kind); if (target === undefined) return undefined; return target.primitive; } -export function isNumberTypeKind(kind: TypeKind): kind is "integer" | "double" { +export function isNumberTypeKind (kind: TypeKind): kind is "integer" | "double" { return kind === "integer" || kind === "double"; } -export function isPrimitiveTypeKind(kind: TypeKind): kind is PrimitiveTypeKind { +export function isPrimitiveTypeKind (kind: TypeKind): kind is PrimitiveTypeKind { if (isPrimitiveStringTypeKind(kind)) return true; if (isNumberTypeKind(kind)) return true; return kind === "none" || kind === "any" || kind === "null" || kind === "bool"; } -function triviallyStructurallyCompatible(x: Type, y: Type): boolean { +function triviallyStructurallyCompatible (x: Type, y: Type): boolean { if (x.index === y.index) return true; if (x.kind === "none" || y.kind === "none") return true; return false; @@ -108,16 +110,17 @@ function triviallyStructurallyCompatible(x: Type, y: Type): boolean { export class TypeIdentity { private readonly _hashCode: number; - constructor(private readonly _kind: TypeKind, private readonly _components: ReadonlyArray) { + constructor (private readonly _kind: TypeKind, private readonly _components: readonly any[]) { let h = hashCodeInit; h = addHashCode(h, hashCodeOf(this._kind)); for (const c of _components) { h = addHashCode(h, hashCodeOf(c)); } + this._hashCode = h; } - equals(other: any): boolean { + equals (other: any): boolean { if (!(other instanceof TypeIdentity)) return false; if (this._kind !== other._kind) return false; const n = this._components.length; @@ -125,10 +128,11 @@ export class TypeIdentity { for (let i = 0; i < n; i++) { if (!areEqual(this._components[i], other._components[i])) return false; } + return true; } - hashCode(): number { + hashCode (): number { return this._hashCode; } } @@ -139,72 +143,73 @@ export type MaybeTypeIdentity = TypeIdentity | undefined; export abstract class Type { abstract readonly kind: TypeKind; - constructor(readonly typeRef: TypeRef, protected readonly graph: TypeGraph) {} + constructor (readonly typeRef: TypeRef, protected readonly graph: TypeGraph) {} - get index(): number { + get index (): number { return typeRefIndex(this.typeRef); } // This must return a newly allocated set - abstract getNonAttributeChildren(): Set; + abstract getNonAttributeChildren (): Set; - getChildren(): ReadonlySet { + getChildren (): ReadonlySet { let result = this.getNonAttributeChildren(); for (const [k, v] of this.getAttributes()) { if (k.children === undefined) continue; setUnionInto(result, k.children(v)); } + return result; } - getAttributes(): TypeAttributes { + getAttributes (): TypeAttributes { return attributesForTypeRef(this.typeRef, this.graph); } - get hasNames(): boolean { + get hasNames (): boolean { return namesTypeAttributeKind.tryGetInAttributes(this.getAttributes()) !== undefined; } - getNames(): TypeNames { + getNames (): TypeNames { return defined(namesTypeAttributeKind.tryGetInAttributes(this.getAttributes())); } - getCombinedName(): string { + getCombinedName (): string { return this.getNames().combinedName; } - abstract get isNullable(): boolean; + abstract get isNullable (): boolean; // FIXME: Remove `isPrimitive` - abstract isPrimitive(): this is PrimitiveType; - abstract get identity(): MaybeTypeIdentity; + abstract isPrimitive (): this is PrimitiveType; + abstract get identity (): MaybeTypeIdentity; abstract reconstitute( builder: TypeReconstituter, canonicalOrder: boolean ): void; - get debugPrintKind(): string { + get debugPrintKind (): string { return this.kind; } - equals(other: any): boolean { + equals (other: any): boolean { if (!(other instanceof Type)) return false; return this.typeRef === other.typeRef; } - hashCode(): number { + hashCode (): number { return hashCodeOf(this.typeRef); } // This will only ever be called when `this` and `other` are not // equal, but `this.kind === other.kind`. - protected abstract structuralEqualityStep( + protected abstract structuralEqualityStep ( other: Type, conflateNumbers: boolean, queue: (a: Type, b: Type) => boolean ): boolean; - structurallyCompatible(other: Type, conflateNumbers = false): boolean { - function kindsCompatible(kind1: TypeKind, kind2: TypeKind): boolean { + structurallyCompatible (other: Type, conflateNumbers = false): boolean { + function kindsCompatible (kind1: TypeKind, kind2: TypeKind): boolean { if (kind1 === kind2) return true; if (!conflateNumbers) return false; if (kind1 === "integer") return kind2 === "double"; @@ -215,11 +220,11 @@ export abstract class Type { if (triviallyStructurallyCompatible(this, other)) return true; if (!kindsCompatible(this.kind, other.kind)) return false; - const workList: [Type, Type][] = [[this, other]]; + const workList: Array<[Type, Type]> = [[this, other]]; // This contains a set of pairs which are the type pairs // we have already determined to be equal. We can't just // do comparison recursively because types can have cycles. - const done: [number, number][] = []; + const done: Array<[number, number]> = []; let failed: boolean; const queue = (x: Type, y: Type): boolean => { @@ -228,6 +233,7 @@ export abstract class Type { failed = true; return false; } + workList.push([x, y]); return true; }; @@ -249,6 +255,7 @@ export abstract class Type { break; } } + if (found) continue; done.push([ai, bi]); } @@ -261,11 +268,11 @@ export abstract class Type { return true; } - getParentTypes(): ReadonlySet { + getParentTypes (): ReadonlySet { return this.graph.getParentsOfType(this); } - getAncestorsNotInSet(set: ReadonlySet): ReadonlySet { + getAncestorsNotInSet (set: ReadonlySet): ReadonlySet { const workList: Type[] = [this]; const processed = new Set(); const ancestors = new Set(); @@ -287,41 +294,42 @@ export abstract class Type { } } } + return ancestors; } } -function hasUniqueIdentityAttributes(attributes: TypeAttributes): boolean { +function hasUniqueIdentityAttributes (attributes: TypeAttributes): boolean { return mapSome(attributes, (v, ta) => ta.requiresUniqueIdentity(v)); } -function identityAttributes(attributes: TypeAttributes): TypeAttributes { +function identityAttributes (attributes: TypeAttributes): TypeAttributes { return mapFilter(attributes, (_, kind) => kind.inIdentity); } -export function primitiveTypeIdentity(kind: PrimitiveTypeKind, attributes: TypeAttributes): MaybeTypeIdentity { +export function primitiveTypeIdentity (kind: PrimitiveTypeKind, attributes: TypeAttributes): MaybeTypeIdentity { if (hasUniqueIdentityAttributes(attributes)) return undefined; return new TypeIdentity(kind, [identityAttributes(attributes)]); } export class PrimitiveType extends Type { - constructor(typeRef: TypeRef, graph: TypeGraph, public readonly kind: PrimitiveTypeKind) { + constructor (typeRef: TypeRef, graph: TypeGraph, public readonly kind: PrimitiveTypeKind) { super(typeRef, graph); } - get isNullable(): boolean { + get isNullable (): boolean { return this.kind === "null" || this.kind === "any" || this.kind === "none"; } - isPrimitive(): this is PrimitiveType { + isPrimitive (): this is PrimitiveType { return true; } - getNonAttributeChildren(): Set { + getNonAttributeChildren (): Set { return new Set(); } - get identity(): MaybeTypeIdentity { + get identity (): MaybeTypeIdentity { return primitiveTypeIdentity(this.kind, this.getAttributes()); } @@ -329,16 +337,16 @@ export class PrimitiveType extends Type { builder.getPrimitiveType(this.kind); } - protected structuralEqualityStep( + protected structuralEqualityStep ( _other: Type, _conflateNumbers: boolean, - _queue: (a: Type, b: Type) => boolean + _queue: (a: Type, b: Type) => boolean, ): boolean { return true; } } -export function arrayTypeIdentity(attributes: TypeAttributes, itemsRef: TypeRef): MaybeTypeIdentity { +export function arrayTypeIdentity (attributes: TypeAttributes, itemsRef: TypeRef): MaybeTypeIdentity { if (hasUniqueIdentityAttributes(attributes)) return undefined; return new TypeIdentity("array", [identityAttributes(attributes), itemsRef]); } @@ -346,41 +354,43 @@ export function arrayTypeIdentity(attributes: TypeAttributes, itemsRef: TypeRef) export class ArrayType extends Type { public readonly kind = "array"; - constructor(typeRef: TypeRef, graph: TypeGraph, private _itemsRef?: TypeRef) { + constructor (typeRef: TypeRef, graph: TypeGraph, private _itemsRef?: TypeRef) { super(typeRef, graph); } - setItems(itemsRef: TypeRef) { + setItems (itemsRef: TypeRef) { if (this._itemsRef !== undefined) { return panic("Can only set array items once"); } + this._itemsRef = itemsRef; } - private getItemsRef(): TypeRef { + private getItemsRef (): TypeRef { if (this._itemsRef === undefined) { return panic("Array items accessed before they were set"); } + return this._itemsRef; } - get items(): Type { + get items (): Type { return derefTypeRef(this.getItemsRef(), this.graph); } - getNonAttributeChildren(): Set { + getNonAttributeChildren (): Set { return new Set([this.items]); } - get isNullable(): boolean { + get isNullable (): boolean { return false; } - isPrimitive(): this is PrimitiveType { + isPrimitive (): this is PrimitiveType { return false; } - get identity(): MaybeTypeIdentity { + get identity (): MaybeTypeIdentity { return arrayTypeIdentity(this.getAttributes(), this.getItemsRef()); } @@ -395,76 +405,77 @@ export class ArrayType extends Type { } } - protected structuralEqualityStep( + protected structuralEqualityStep ( other: ArrayType, _conflateNumbers: boolean, - queue: (a: Type, b: Type) => boolean + queue: (a: Type, b: Type) => boolean, ): boolean { return queue(this.items, other.items); } } export class GenericClassProperty { - constructor(readonly typeData: T, readonly isOptional: boolean) {} + constructor (readonly typeData: T, readonly isOptional: boolean) {} - equals(other: any): boolean { + equals (other: any): boolean { if (!(other instanceof GenericClassProperty)) { return false; } + return areEqual(this.typeData, other.typeData) && this.isOptional === other.isOptional; } - hashCode(): number { + hashCode (): number { return hashCodeOf(this.typeData) + (this.isOptional ? 17 : 23); } } export class ClassProperty extends GenericClassProperty { - constructor(typeRef: TypeRef, readonly graph: TypeGraph, isOptional: boolean) { + constructor (typeRef: TypeRef, readonly graph: TypeGraph, isOptional: boolean) { super(typeRef, isOptional); } - get typeRef(): TypeRef { + get typeRef (): TypeRef { return this.typeData; } - get type(): Type { + get type (): Type { return derefTypeRef(this.typeRef, this.graph); } } -function objectTypeIdentify( +function objectTypeIdentify ( kind: ObjectTypeKind, attributes: TypeAttributes, properties: ReadonlyMap, - additionalPropertiesRef: TypeRef | undefined + additionalPropertiesRef: TypeRef | undefined, ): MaybeTypeIdentity { if (hasUniqueIdentityAttributes(attributes)) return undefined; return new TypeIdentity(kind, [identityAttributes(attributes), properties, additionalPropertiesRef]); } -export function classTypeIdentity( +export function classTypeIdentity ( attributes: TypeAttributes, - properties: ReadonlyMap + properties: ReadonlyMap, ): MaybeTypeIdentity { return objectTypeIdentify("class", attributes, properties, undefined); } -export function mapTypeIdentify( +export function mapTypeIdentify ( attributes: TypeAttributes, - additionalPropertiesRef: TypeRef | undefined + additionalPropertiesRef: TypeRef | undefined, ): MaybeTypeIdentity { return objectTypeIdentify("map", attributes, new Map(), additionalPropertiesRef); } export class ObjectType extends Type { - constructor( + constructor ( typeRef: TypeRef, graph: TypeGraph, public readonly kind: ObjectTypeKind, readonly isFixed: boolean, private _properties: ReadonlyMap | undefined, - private _additionalPropertiesRef: TypeRef | undefined + private _additionalPropertiesRef: TypeRef | undefined, ) { super(typeRef, graph); @@ -472,6 +483,7 @@ export class ObjectType extends Type { if (_properties !== undefined) { assert(_properties.size === 0); } + assert(!isFixed); } else if (kind === "class") { assert(_additionalPropertiesRef === undefined); @@ -480,7 +492,7 @@ export class ObjectType extends Type { } } - setProperties(properties: ReadonlyMap, additionalPropertiesRef: TypeRef | undefined) { + setProperties (properties: ReadonlyMap, additionalPropertiesRef: TypeRef | undefined) { assert(this._properties === undefined, "Tried to set object properties twice"); if (this instanceof MapType) { @@ -495,49 +507,50 @@ export class ObjectType extends Type { this._additionalPropertiesRef = additionalPropertiesRef; } - getProperties(): ReadonlyMap { + getProperties (): ReadonlyMap { return defined(this._properties); } - getSortedProperties(): ReadonlyMap { + getSortedProperties (): ReadonlyMap { return mapSortByKey(this.getProperties()); } - private getAdditionalPropertiesRef(): TypeRef | undefined { + private getAdditionalPropertiesRef (): TypeRef | undefined { assert(this._properties !== undefined, "Properties are not set yet"); return this._additionalPropertiesRef; } - getAdditionalProperties(): Type | undefined { + getAdditionalProperties (): Type | undefined { const tref = this.getAdditionalPropertiesRef(); if (tref === undefined) return undefined; return derefTypeRef(tref, this.graph); } - getNonAttributeChildren(): Set { + getNonAttributeChildren (): Set { const types = mapSortToArray(this.getProperties(), (_, k) => k).map(([_, p]) => p.type); const additionalProperties = this.getAdditionalProperties(); if (additionalProperties !== undefined) { types.push(additionalProperties); } + return new Set(types); } - get isNullable(): boolean { + get isNullable (): boolean { return false; } - isPrimitive(): this is PrimitiveType { + isPrimitive (): this is PrimitiveType { return false; } - get identity(): MaybeTypeIdentity { + get identity (): MaybeTypeIdentity { if (this.isFixed) return undefined; return objectTypeIdentify( this.kind, this.getAttributes(), this.getProperties(), - this.getAdditionalPropertiesRef() + this.getAdditionalPropertiesRef(), ); } @@ -552,7 +565,7 @@ export class ObjectType extends Type { (maybeAdditionalProperties !== undefined || this._additionalPropertiesRef === undefined) ) { const properties = mapMap(propertiesInNewOrder, (cp, n) => - builder.makeClassProperty(defined(maybePropertyTypes.get(n)), cp.isOptional) + builder.makeClassProperty(defined(maybePropertyTypes.get(n)), cp.isOptional), ); switch (this.kind) { @@ -569,6 +582,7 @@ export class ObjectType extends Type { } else { builder.getClassType(properties); } + break; default: return panic(`Invalid object type kind ${this.kind}`); @@ -591,17 +605,17 @@ export class ObjectType extends Type { const reconstitutedTypes = mapMap(sortedProperties, cp => builder.reconstitute(cp.typeRef)); const properties = mapMap(propertiesInNewOrder, (cp, n) => - builder.makeClassProperty(defined(reconstitutedTypes.get(n)), cp.isOptional) + builder.makeClassProperty(defined(reconstitutedTypes.get(n)), cp.isOptional), ); const additionalProperties = definedMap(this._additionalPropertiesRef, r => builder.reconstitute(r)); builder.setObjectProperties(properties, additionalProperties); } } - protected structuralEqualityStep( + protected structuralEqualityStep ( other: ObjectType, _conflateNumbers: boolean, - queue: (a: Type, b: Type) => boolean + queue: (a: Type, b: Type) => boolean, ): boolean { const pa = this.getProperties(); const pb = other.getProperties(); @@ -614,46 +628,47 @@ export class ObjectType extends Type { return false; } } + if (failed) return false; const thisAdditionalProperties = this.getAdditionalProperties(); const otherAdditionalProperties = other.getAdditionalProperties(); - if ((thisAdditionalProperties === undefined) !== (otherAdditionalProperties === undefined)) return false; + if (thisAdditionalProperties === undefined !== (otherAdditionalProperties === undefined)) return false; if (thisAdditionalProperties === undefined || otherAdditionalProperties === undefined) return true; return queue(thisAdditionalProperties, otherAdditionalProperties); } } export class ClassType extends ObjectType { - constructor( + constructor ( typeRef: TypeRef, graph: TypeGraph, isFixed: boolean, - properties: ReadonlyMap | undefined + properties: ReadonlyMap | undefined, ) { super(typeRef, graph, "class", isFixed, properties, undefined); } } export class MapType extends ObjectType { - constructor(typeRef: TypeRef, graph: TypeGraph, valuesRef: TypeRef | undefined) { + constructor (typeRef: TypeRef, graph: TypeGraph, valuesRef: TypeRef | undefined) { super( typeRef, graph, "map", false, definedMap(valuesRef, () => new Map()), - valuesRef + valuesRef, ); } // FIXME: Remove and use `getAdditionalProperties()` instead. - get values(): Type { + get values (): Type { return defined(this.getAdditionalProperties()); } } -export function enumTypeIdentity(attributes: TypeAttributes, cases: ReadonlySet): MaybeTypeIdentity { +export function enumTypeIdentity (attributes: TypeAttributes, cases: ReadonlySet): MaybeTypeIdentity { if (hasUniqueIdentityAttributes(attributes)) return undefined; return new TypeIdentity("enum", [identityAttributes(attributes), cases]); } @@ -661,23 +676,23 @@ export function enumTypeIdentity(attributes: TypeAttributes, cases: ReadonlySet< export class EnumType extends Type { public readonly kind = "enum"; - constructor(typeRef: TypeRef, graph: TypeGraph, readonly cases: ReadonlySet) { + constructor (typeRef: TypeRef, graph: TypeGraph, readonly cases: ReadonlySet) { super(typeRef, graph); } - get isNullable(): boolean { + get isNullable (): boolean { return false; } - isPrimitive(): this is PrimitiveType { + isPrimitive (): this is PrimitiveType { return false; } - get identity(): MaybeTypeIdentity { + get identity (): MaybeTypeIdentity { return enumTypeIdentity(this.getAttributes(), this.cases); } - getNonAttributeChildren(): Set { + getNonAttributeChildren (): Set { return new Set(); } @@ -685,20 +700,20 @@ export class EnumType extends Type { builder.getEnumType(this.cases); } - protected structuralEqualityStep( + protected structuralEqualityStep ( other: EnumType, _conflateNumbers: boolean, - _queue: (a: Type, b: Type) => void + _queue: (a: Type, b: Type) => void, ): boolean { return areEqual(this.cases, other.cases); } } -export function setOperationCasesEqual( +export function setOperationCasesEqual ( typesA: Iterable, typesB: Iterable, conflateNumbers: boolean, - membersEqual: (a: Type, b: Type) => boolean + membersEqual: (a: Type, b: Type) => boolean, ): boolean { const ma = toReadonlySet(typesA); const mb = toReadonlySet(typesB); @@ -708,83 +723,87 @@ export function setOperationCasesEqual( if (tb !== undefined) { if (membersEqual(ta, tb)) return true; } + if (conflateNumbers) { if (ta.kind === "integer" && iterableSome(mb, t => t.kind === "double")) return true; if (ta.kind === "double" && iterableSome(mb, t => t.kind === "integer")) return true; } + return false; }); } -export function setOperationTypeIdentity( +export function setOperationTypeIdentity ( kind: TypeKind, attributes: TypeAttributes, - memberRefs: ReadonlySet + memberRefs: ReadonlySet, ): MaybeTypeIdentity { if (hasUniqueIdentityAttributes(attributes)) return undefined; return new TypeIdentity(kind, [identityAttributes(attributes), memberRefs]); } -export function unionTypeIdentity(attributes: TypeAttributes, memberRefs: ReadonlySet): MaybeTypeIdentity { +export function unionTypeIdentity (attributes: TypeAttributes, memberRefs: ReadonlySet): MaybeTypeIdentity { return setOperationTypeIdentity("union", attributes, memberRefs); } -export function intersectionTypeIdentity( +export function intersectionTypeIdentity ( attributes: TypeAttributes, - memberRefs: ReadonlySet + memberRefs: ReadonlySet, ): MaybeTypeIdentity { return setOperationTypeIdentity("intersection", attributes, memberRefs); } export abstract class SetOperationType extends Type { - constructor( + constructor ( typeRef: TypeRef, graph: TypeGraph, public readonly kind: TypeKind, - private _memberRefs?: ReadonlySet + private _memberRefs?: ReadonlySet, ) { super(typeRef, graph); } - setMembers(memberRefs: ReadonlySet): void { + setMembers (memberRefs: ReadonlySet): void { if (this._memberRefs !== undefined) { return panic("Can only set map members once"); } + this._memberRefs = memberRefs; } - protected getMemberRefs(): ReadonlySet { + protected getMemberRefs (): ReadonlySet { if (this._memberRefs === undefined) { return panic("Map members accessed before they were set"); } + return this._memberRefs; } - get members(): ReadonlySet { + get members (): ReadonlySet { return setMap(this.getMemberRefs(), tref => derefTypeRef(tref, this.graph)); } - get sortedMembers(): ReadonlySet { + get sortedMembers (): ReadonlySet { return this.getNonAttributeChildren(); } - getNonAttributeChildren(): Set { + getNonAttributeChildren (): Set { // FIXME: We're assuming no two members of the same kind. return setSortBy(this.members, t => t.kind); } - isPrimitive(): this is PrimitiveType { + isPrimitive (): this is PrimitiveType { return false; } - get identity(): MaybeTypeIdentity { + get identity (): MaybeTypeIdentity { return setOperationTypeIdentity(this.kind, this.getAttributes(), this.getMemberRefs()); } protected reconstituteSetOperation( builder: TypeReconstituter, canonicalOrder: boolean, - getType: (members: ReadonlySet | undefined) => void + getType: (members: ReadonlySet | undefined) => void, ): void { const sortedMemberRefs = mapMap(this.sortedMembers.entries(), t => t.typeRef); const membersInOrder = canonicalOrder ? this.sortedMembers : this.members; @@ -798,21 +817,21 @@ export abstract class SetOperationType extends Type { } } - protected structuralEqualityStep( + protected structuralEqualityStep ( other: SetOperationType, conflateNumbers: boolean, - queue: (a: Type, b: Type) => boolean + queue: (a: Type, b: Type) => boolean, ): boolean { return setOperationCasesEqual(this.members, other.members, conflateNumbers, queue); } } export class IntersectionType extends SetOperationType { - constructor(typeRef: TypeRef, graph: TypeGraph, memberRefs?: ReadonlySet) { + constructor (typeRef: TypeRef, graph: TypeGraph, memberRefs?: ReadonlySet) { super(typeRef, graph, "intersection", memberRefs); } - get isNullable(): boolean { + get isNullable (): boolean { return panic("isNullable not implemented for IntersectionType"); } @@ -828,31 +847,31 @@ export class IntersectionType extends SetOperationType { } export class UnionType extends SetOperationType { - constructor(typeRef: TypeRef, graph: TypeGraph, memberRefs?: ReadonlySet) { + constructor (typeRef: TypeRef, graph: TypeGraph, memberRefs?: ReadonlySet) { super(typeRef, graph, "union", memberRefs); if (memberRefs !== undefined) { messageAssert(memberRefs.size > 0, "IRNoEmptyUnions", {}); } } - setMembers(memberRefs: ReadonlySet): void { + setMembers (memberRefs: ReadonlySet): void { messageAssert(memberRefs.size > 0, "IRNoEmptyUnions", {}); super.setMembers(memberRefs); } - get stringTypeMembers(): ReadonlySet { + get stringTypeMembers (): ReadonlySet { return setFilter(this.members, t => isPrimitiveStringTypeKind(t.kind) || t.kind === "enum"); } - findMember(kind: TypeKind): Type | undefined { + findMember (kind: TypeKind): Type | undefined { return iterableFind(this.members, t => t.kind === kind); } - get isNullable(): boolean { + get isNullable (): boolean { return this.findMember("null") !== undefined; } - get isCanonical(): boolean { + get isCanonical (): boolean { const members = this.members; if (members.size <= 1) return false; const kinds = setMap(members, t => t.kind); diff --git a/packages/quicktype-core/src/TypeBuilder.ts b/packages/quicktype-core/src/TypeBuilder.ts index d7d0a4b59..55d521857 100644 --- a/packages/quicktype-core/src/TypeBuilder.ts +++ b/packages/quicktype-core/src/TypeBuilder.ts @@ -8,19 +8,25 @@ import { areEqual, setUnionManyInto, definedMap, - withDefault + withDefault, } from "collection-utils"; import { - PrimitiveTypeKind, - Type, + type PrimitiveTypeKind, + type Type, + type PrimitiveStringTypeKind, + type MaybeTypeIdentity, + type TypeIdentity, + type TransformedStringTypeKind, + type TypeKind, +} from "./Type"; +import { PrimitiveType, EnumType, MapType, ArrayType, ClassType, UnionType, - PrimitiveStringTypeKind, ClassProperty, IntersectionType, ObjectType, @@ -31,19 +37,17 @@ import { classTypeIdentity, unionTypeIdentity, intersectionTypeIdentity, - MaybeTypeIdentity, - TypeIdentity, - TransformedStringTypeKind, isPrimitiveStringTypeKind, transformedStringTypeKinds, - TypeKind } from "./Type"; -import { TypeGraph, TypeRef, makeTypeRef, derefTypeRef, typeRefIndex, assertTypeRefGraph } from "./TypeGraph"; +import { type TypeRef} from "./TypeGraph"; +import { TypeGraph, makeTypeRef, derefTypeRef, typeRefIndex, assertTypeRefGraph } from "./TypeGraph"; +import { + type TypeAttributes} from "./attributes/TypeAttributes"; import { - TypeAttributes, combineTypeAttributes, TypeAttributeKind, - emptyTypeAttributes + emptyTypeAttributes, } from "./attributes/TypeAttributes"; import { defined, assert, panic } from "./support/Support"; import { stringTypesTypeAttributeKind, StringTypes } from "./attributes/StringTypes"; @@ -51,23 +55,23 @@ import { stringTypesTypeAttributeKind, StringTypes } from "./attributes/StringTy // FIXME: Don't infer provenance. All original types should be present in // non-inferred form in the final graph. class ProvenanceTypeAttributeKind extends TypeAttributeKind> { - constructor() { + constructor () { super("provenance"); } - appliesToTypeKind(_kind: TypeKind): boolean { + appliesToTypeKind (_kind: TypeKind): boolean { return true; } - combine(arr: Set[]): Set { + combine (arr: Array>): Set { return setUnionManyInto(new Set(), arr); } - makeInferred(p: Set): Set { + makeInferred (p: Set): Set { return p; } - stringify(p: Set): string { + stringify (p: Set): string { return Array.from(p) .sort() .map(i => i.toString()) @@ -79,7 +83,7 @@ export const provenanceTypeAttributeKind: TypeAttributeKind> = new P export type StringTypeMapping = ReadonlyMap; -export function stringTypeMappingGet(stm: StringTypeMapping, kind: TransformedStringTypeKind): PrimitiveStringTypeKind { +export function stringTypeMappingGet (stm: StringTypeMapping, kind: TransformedStringTypeKind): PrimitiveStringTypeKind { const mapped = stm.get(kind); if (mapped === undefined) return "string"; return mapped; @@ -87,14 +91,15 @@ export function stringTypeMappingGet(stm: StringTypeMapping, kind: TransformedSt let noStringTypeMapping: StringTypeMapping | undefined; -export function getNoStringTypeMapping(): StringTypeMapping { +export function getNoStringTypeMapping (): StringTypeMapping { if (noStringTypeMapping === undefined) { noStringTypeMapping = new Map( Array.from(transformedStringTypeKinds).map( - k => [k, k] as [TransformedStringTypeKind, PrimitiveStringTypeKind] - ) + k => [k, k] as [TransformedStringTypeKind, PrimitiveStringTypeKind], + ), ); } + return noStringTypeMapping; } @@ -102,37 +107,39 @@ export class TypeBuilder { readonly typeGraph: TypeGraph; protected readonly topLevels: Map = new Map(); - protected readonly types: (Type | undefined)[] = []; + + protected readonly types: Array = []; + private readonly typeAttributes: TypeAttributes[] = []; private _addedForwardingIntersection = false; - constructor( + constructor ( typeGraphSerial: number, private readonly _stringTypeMapping: StringTypeMapping, readonly canonicalOrder: boolean, private readonly _allPropertiesOptional: boolean, private readonly _addProvenanceAttributes: boolean, - inheritsProvenanceAttributes: boolean + inheritsProvenanceAttributes: boolean, ) { assert( !_addProvenanceAttributes || !inheritsProvenanceAttributes, - "We can't both inherit as well as add provenance" + "We can't both inherit as well as add provenance", ); this.typeGraph = new TypeGraph(this, typeGraphSerial, _addProvenanceAttributes || inheritsProvenanceAttributes); } - addTopLevel(name: string, tref: TypeRef): void { + addTopLevel (name: string, tref: TypeRef): void { // assert(t.typeGraph === this.typeGraph, "Adding top-level to wrong type graph"); assert(!this.topLevels.has(name), "Trying to add top-level with existing name"); assert( this.types[typeRefIndex(tref)] !== undefined, - "Trying to add a top-level type that doesn't exist (yet?)" + "Trying to add a top-level type that doesn't exist (yet?)", ); this.topLevels.set(name, tref); } - reserveTypeRef(): TypeRef { + reserveTypeRef (): TypeRef { const index = this.types.length; // console.log(`reserving ${index}`); this.types.push(undefined); @@ -144,25 +151,26 @@ export class TypeBuilder { return tref; } - private assertTypeRefGraph(tref: TypeRef | undefined): void { + private assertTypeRefGraph (tref: TypeRef | undefined): void { if (tref === undefined) return; assertTypeRefGraph(tref, this.typeGraph); } - private assertTypeRefSetGraph(trefs: ReadonlySet | undefined): void { + private assertTypeRefSetGraph (trefs: ReadonlySet | undefined): void { if (trefs === undefined) return; trefs.forEach(tref => this.assertTypeRefGraph(tref)); } - private filterTypeAttributes(t: Type, attributes: TypeAttributes): TypeAttributes { + private filterTypeAttributes (t: Type, attributes: TypeAttributes): TypeAttributes { const filtered = mapFilter(attributes, (_, k) => k.appliesToTypeKind(t.kind)); if (attributes.size !== filtered.size) { this.setLostTypeAttributes(); } + return filtered; } - private commitType(tref: TypeRef, t: Type): void { + private commitType (tref: TypeRef, t: Type): void { this.assertTypeRefGraph(tref); const index = typeRefIndex(tref); // const name = names !== undefined ? ` ${names.combinedName}` : ""; @@ -175,37 +183,40 @@ export class TypeBuilder { protected addType( forwardingRef: TypeRef | undefined, creator: (tref: TypeRef) => T, - attributes: TypeAttributes | undefined + attributes: TypeAttributes | undefined, ): TypeRef { if (forwardingRef !== undefined) { this.assertTypeRefGraph(forwardingRef); assert(this.types[typeRefIndex(forwardingRef)] === undefined); } + const tref = forwardingRef !== undefined ? forwardingRef : this.reserveTypeRef(); if (attributes !== undefined) { const index = typeRefIndex(tref); this.typeAttributes[index] = combineTypeAttributes("union", this.typeAttributes[index], attributes); } + const t = creator(tref); this.commitType(tref, t); return tref; } - typeAtIndex(index: number): Type { + typeAtIndex (index: number): Type { const maybeType = this.types[index]; if (maybeType === undefined) { return panic("Trying to deref an undefined type in a type builder"); } + return maybeType; } - atIndex(index: number): [Type, TypeAttributes] { + atIndex (index: number): [Type, TypeAttributes] { const t = this.typeAtIndex(index); const attribtues = this.typeAttributes[index]; return [t, attribtues]; } - addAttributes(tref: TypeRef, attributes: TypeAttributes): void { + addAttributes (tref: TypeRef, attributes: TypeAttributes): void { this.assertTypeRefGraph(tref); const index = typeRefIndex(tref); const existingAttributes = this.typeAttributes[index]; @@ -216,56 +227,57 @@ export class TypeBuilder { if (existing === undefined) return false; return areEqual(existing, v); }), - "Can't add different identity type attributes to an existing type" + "Can't add different identity type attributes to an existing type", ); const maybeType = this.types[index]; if (maybeType !== undefined) { attributes = this.filterTypeAttributes(maybeType, attributes); } + const nonIdentityAttributes = mapFilter(attributes, (_, k) => !k.inIdentity); this.typeAttributes[index] = combineTypeAttributes("union", existingAttributes, nonIdentityAttributes); } - finish(): TypeGraph { + finish (): TypeGraph { this.typeGraph.freeze(this.topLevels, this.types.map(defined), this.typeAttributes); return this.typeGraph; } - protected addForwardingIntersection(forwardingRef: TypeRef, tref: TypeRef): TypeRef { + protected addForwardingIntersection (forwardingRef: TypeRef, tref: TypeRef): TypeRef { this.assertTypeRefGraph(tref); this._addedForwardingIntersection = true; return this.addType(forwardingRef, tr => new IntersectionType(tr, this.typeGraph, new Set([tref])), undefined); } - protected forwardIfNecessary(forwardingRef: TypeRef | undefined, tref: undefined): undefined; - protected forwardIfNecessary(forwardingRef: TypeRef | undefined, tref: TypeRef): TypeRef; - protected forwardIfNecessary(forwardingRef: TypeRef | undefined, tref: TypeRef | undefined): TypeRef | undefined; - protected forwardIfNecessary(forwardingRef: TypeRef | undefined, tref: TypeRef | undefined): TypeRef | undefined { + protected forwardIfNecessary (forwardingRef: TypeRef | undefined, tref: undefined): undefined; + protected forwardIfNecessary (forwardingRef: TypeRef | undefined, tref: TypeRef): TypeRef; + protected forwardIfNecessary (forwardingRef: TypeRef | undefined, tref: TypeRef | undefined): TypeRef | undefined; + protected forwardIfNecessary (forwardingRef: TypeRef | undefined, tref: TypeRef | undefined): TypeRef | undefined { if (tref === undefined) return undefined; if (forwardingRef === undefined) return tref; return this.addForwardingIntersection(forwardingRef, tref); } - get didAddForwardingIntersection(): boolean { + get didAddForwardingIntersection (): boolean { return this._addedForwardingIntersection; } private readonly _typeForIdentity: EqualityMap = new EqualityMap(); - private registerTypeForIdentity(identity: MaybeTypeIdentity, tref: TypeRef): void { + private registerTypeForIdentity (identity: MaybeTypeIdentity, tref: TypeRef): void { if (identity === undefined) return; this._typeForIdentity.set(identity, tref); } - protected makeIdentity(maker: () => MaybeTypeIdentity): MaybeTypeIdentity { + protected makeIdentity (maker: () => MaybeTypeIdentity): MaybeTypeIdentity { return maker(); } - private getOrAddType( + private getOrAddType ( identityMaker: () => MaybeTypeIdentity, creator: (tr: TypeRef) => Type, attributes: TypeAttributes | undefined, - forwardingRef: TypeRef | undefined + forwardingRef: TypeRef | undefined, ): TypeRef { const identity = this.makeIdentity(identityMaker); let maybeTypeRef: TypeRef | undefined; @@ -274,6 +286,7 @@ export class TypeBuilder { } else { maybeTypeRef = this._typeForIdentity.get(identity); } + if (maybeTypeRef !== undefined) { const result = this.forwardIfNecessary(forwardingRef, maybeTypeRef); if (attributes !== undefined) { @@ -283,9 +296,10 @@ export class TypeBuilder { // asserts that no identity attributes are added later. this.addAttributes( result, - mapFilter(attributes, (_, k) => !k.inIdentity) + mapFilter(attributes, (_, k) => !k.inIdentity), ); } + return result; } @@ -294,11 +308,11 @@ export class TypeBuilder { return tref; } - private registerType(t: Type): void { + private registerType (t: Type): void { this.registerTypeForIdentity(t.identity, t.typeRef); } - getPrimitiveType(kind: PrimitiveTypeKind, maybeAttributes?: TypeAttributes, forwardingRef?: TypeRef): TypeRef { + getPrimitiveType (kind: PrimitiveTypeKind, maybeAttributes?: TypeAttributes, forwardingRef?: TypeRef): TypeRef { const attributes = withDefault(maybeAttributes, emptyTypeAttributes); // FIXME: Why do date/time types need a StringTypes attribute? // FIXME: Remove this from here and put it into flattenStrings @@ -306,56 +320,59 @@ export class TypeBuilder { if (isPrimitiveStringTypeKind(kind) && kind !== "string") { kind = stringTypeMappingGet(this._stringTypeMapping, kind); } + if (kind === "string") { return this.getStringType(attributes, stringTypes, forwardingRef); } + return this.getOrAddType( () => primitiveTypeIdentity(kind, attributes), tr => new PrimitiveType(tr, this.typeGraph, kind), attributes, - forwardingRef + forwardingRef, ); } - getStringType(attributes: TypeAttributes, stringTypes: StringTypes | undefined, forwardingRef?: TypeRef): TypeRef { + getStringType (attributes: TypeAttributes, stringTypes: StringTypes | undefined, forwardingRef?: TypeRef): TypeRef { const existingStringTypes = mapFind(attributes, (_, k) => k === stringTypesTypeAttributeKind); assert( - (stringTypes === undefined) !== (existingStringTypes === undefined), - "Must instantiate string type with one enum case attribute" + stringTypes === undefined !== (existingStringTypes === undefined), + "Must instantiate string type with one enum case attribute", ); if (existingStringTypes === undefined) { attributes = combineTypeAttributes( "union", attributes, - stringTypesTypeAttributeKind.makeAttributes(defined(stringTypes)) + stringTypesTypeAttributeKind.makeAttributes(defined(stringTypes)), ); } + return this.getOrAddType( () => primitiveTypeIdentity("string", attributes), tr => new PrimitiveType(tr, this.typeGraph, "string"), attributes, - forwardingRef + forwardingRef, ); } - getEnumType(attributes: TypeAttributes, cases: ReadonlySet, forwardingRef?: TypeRef): TypeRef { + getEnumType (attributes: TypeAttributes, cases: ReadonlySet, forwardingRef?: TypeRef): TypeRef { return this.getOrAddType( () => enumTypeIdentity(attributes, cases), tr => new EnumType(tr, this.typeGraph, cases), attributes, - forwardingRef + forwardingRef, ); } - makeClassProperty(tref: TypeRef, isOptional: boolean): ClassProperty { + makeClassProperty (tref: TypeRef, isOptional: boolean): ClassProperty { return new ClassProperty(tref, this.typeGraph, isOptional); } - getUniqueObjectType( + getUniqueObjectType ( attributes: TypeAttributes, properties: ReadonlyMap | undefined, additionalProperties: TypeRef | undefined, - forwardingRef?: TypeRef + forwardingRef?: TypeRef, ): TypeRef { this.assertTypeRefGraph(additionalProperties); @@ -363,29 +380,29 @@ export class TypeBuilder { return this.addType( forwardingRef, tref => new ObjectType(tref, this.typeGraph, "object", true, properties, additionalProperties), - attributes + attributes, ); } - getUniqueMapType(forwardingRef?: TypeRef): TypeRef { + getUniqueMapType (forwardingRef?: TypeRef): TypeRef { return this.addType(forwardingRef, tr => new MapType(tr, this.typeGraph, undefined), undefined); } - getMapType(attributes: TypeAttributes, values: TypeRef, forwardingRef?: TypeRef): TypeRef { + getMapType (attributes: TypeAttributes, values: TypeRef, forwardingRef?: TypeRef): TypeRef { this.assertTypeRefGraph(values); return this.getOrAddType( () => mapTypeIdentify(attributes, values), tr => new MapType(tr, this.typeGraph, values), attributes, - forwardingRef + forwardingRef, ); } - setObjectProperties( + setObjectProperties ( ref: TypeRef, properties: ReadonlyMap, - additionalProperties: TypeRef | undefined + additionalProperties: TypeRef | undefined, ): void { this.assertTypeRefGraph(additionalProperties); @@ -393,134 +410,139 @@ export class TypeBuilder { if (!(type instanceof ObjectType)) { return panic("Tried to set properties of non-object type"); } + type.setProperties(this.modifyPropertiesIfNecessary(properties), additionalProperties); this.registerType(type); } - getUniqueArrayType(forwardingRef?: TypeRef): TypeRef { + getUniqueArrayType (forwardingRef?: TypeRef): TypeRef { return this.addType(forwardingRef, tr => new ArrayType(tr, this.typeGraph, undefined), undefined); } - getArrayType(attributes: TypeAttributes, items: TypeRef, forwardingRef?: TypeRef): TypeRef { + getArrayType (attributes: TypeAttributes, items: TypeRef, forwardingRef?: TypeRef): TypeRef { this.assertTypeRefGraph(items); return this.getOrAddType( () => arrayTypeIdentity(attributes, items), tr => new ArrayType(tr, this.typeGraph, items), attributes, - forwardingRef + forwardingRef, ); } - setArrayItems(ref: TypeRef, items: TypeRef): void { + setArrayItems (ref: TypeRef, items: TypeRef): void { this.assertTypeRefGraph(items); const type = derefTypeRef(ref, this.typeGraph); if (!(type instanceof ArrayType)) { return panic("Tried to set items of non-array type"); } + type.setItems(items); this.registerType(type); } - modifyPropertiesIfNecessary(properties: ReadonlyMap): ReadonlyMap { + modifyPropertiesIfNecessary (properties: ReadonlyMap): ReadonlyMap { properties.forEach(p => this.assertTypeRefGraph(p.typeRef)); if (this.canonicalOrder) { properties = mapSortByKey(properties); } + if (this._allPropertiesOptional) { properties = mapMap(properties, cp => this.makeClassProperty(cp.typeRef, true)); } + return properties; } - getClassType( + getClassType ( attributes: TypeAttributes, properties: ReadonlyMap, - forwardingRef?: TypeRef + forwardingRef?: TypeRef, ): TypeRef { properties = this.modifyPropertiesIfNecessary(properties); return this.getOrAddType( () => classTypeIdentity(attributes, properties), tr => new ClassType(tr, this.typeGraph, false, properties), attributes, - forwardingRef + forwardingRef, ); } // FIXME: Maybe just distinguish between this and `getClassType` // via a flag? That would make `ClassType.map` simpler. - getUniqueClassType( + getUniqueClassType ( attributes: TypeAttributes, isFixed: boolean, properties: ReadonlyMap | undefined, - forwardingRef?: TypeRef + forwardingRef?: TypeRef, ): TypeRef { properties = definedMap(properties, p => this.modifyPropertiesIfNecessary(p)); return this.addType( forwardingRef, tref => new ClassType(tref, this.typeGraph, isFixed, properties), - attributes + attributes, ); } - getUnionType(attributes: TypeAttributes, members: ReadonlySet, forwardingRef?: TypeRef): TypeRef { + getUnionType (attributes: TypeAttributes, members: ReadonlySet, forwardingRef?: TypeRef): TypeRef { this.assertTypeRefSetGraph(members); return this.getOrAddType( () => unionTypeIdentity(attributes, members), tr => new UnionType(tr, this.typeGraph, members), attributes, - forwardingRef + forwardingRef, ); } // FIXME: why do we sometimes call this with defined members??? - getUniqueUnionType( + getUniqueUnionType ( attributes: TypeAttributes, members: ReadonlySet | undefined, - forwardingRef?: TypeRef + forwardingRef?: TypeRef, ): TypeRef { this.assertTypeRefSetGraph(members); return this.addType(forwardingRef, tref => new UnionType(tref, this.typeGraph, members), attributes); } - getIntersectionType(attributes: TypeAttributes, members: ReadonlySet, forwardingRef?: TypeRef): TypeRef { + getIntersectionType (attributes: TypeAttributes, members: ReadonlySet, forwardingRef?: TypeRef): TypeRef { this.assertTypeRefSetGraph(members); return this.getOrAddType( () => intersectionTypeIdentity(attributes, members), tr => new IntersectionType(tr, this.typeGraph, members), attributes, - forwardingRef + forwardingRef, ); } // FIXME: why do we sometimes call this with defined members??? - getUniqueIntersectionType( + getUniqueIntersectionType ( attributes: TypeAttributes, members: ReadonlySet | undefined, - forwardingRef?: TypeRef + forwardingRef?: TypeRef, ): TypeRef { this.assertTypeRefSetGraph(members); return this.addType(forwardingRef, tref => new IntersectionType(tref, this.typeGraph, members), attributes); } - setSetOperationMembers(ref: TypeRef, members: ReadonlySet): void { + setSetOperationMembers (ref: TypeRef, members: ReadonlySet): void { this.assertTypeRefSetGraph(members); const type = derefTypeRef(ref, this.typeGraph); if (!(type instanceof UnionType || type instanceof IntersectionType)) { return panic("Tried to set members of non-set-operation type"); } + type.setMembers(members); this.registerType(type); } - setLostTypeAttributes(): void { + setLostTypeAttributes (): void { return; } } diff --git a/packages/quicktype-core/src/TypeGraph.ts b/packages/quicktype-core/src/TypeGraph.ts index 09993039e..5ffa13a48 100644 --- a/packages/quicktype-core/src/TypeGraph.ts +++ b/packages/quicktype-core/src/TypeGraph.ts @@ -1,13 +1,18 @@ import { iterableFirst, setFilter, setUnionManyInto, setSubtract, mapMap, mapSome, setMap } from "collection-utils"; -import { Type, ClassType, UnionType, IntersectionType } from "./Type"; -import { separateNamedTypes, SeparatedNamedTypes, isNamedType, combineTypeAttributesOfTypes } from "./TypeUtils"; +import { type Type} from "./Type"; +import { ClassType, UnionType, IntersectionType } from "./Type"; +import { type SeparatedNamedTypes} from "./TypeUtils"; +import { separateNamedTypes, isNamedType, combineTypeAttributesOfTypes } from "./TypeUtils"; import { defined, assert, panic, mustNotHappen } from "./support/Support"; -import { TypeBuilder, StringTypeMapping, getNoStringTypeMapping, provenanceTypeAttributeKind } from "./TypeBuilder"; -import { GraphRewriteBuilder, GraphRemapBuilder, BaseGraphRewriteBuilder } from "./GraphRewriting"; +import { type TypeBuilder, type StringTypeMapping} from "./TypeBuilder"; +import { getNoStringTypeMapping, provenanceTypeAttributeKind } from "./TypeBuilder"; +import { type BaseGraphRewriteBuilder } from "./GraphRewriting"; +import { GraphRewriteBuilder, GraphRemapBuilder } from "./GraphRewriting"; import { TypeNames, namesTypeAttributeKind } from "./attributes/TypeNames"; import { Graph } from "./Graph"; -import { TypeAttributeKind, TypeAttributes, emptyTypeAttributes } from "./attributes/TypeAttributes"; +import { type TypeAttributeKind, type TypeAttributes} from "./attributes/TypeAttributes"; +import { emptyTypeAttributes } from "./attributes/TypeAttributes"; import { messageError } from "./Messages"; export type TypeRef = number; @@ -17,49 +22,49 @@ const indexMask = (1 << indexBits) - 1; const serialBits = 31 - indexBits; const serialMask = (1 << serialBits) - 1; -export function isTypeRef(x: any): x is TypeRef { +export function isTypeRef (x: any): x is TypeRef { return typeof x === "number"; } -export function makeTypeRef(graph: TypeGraph, index: number): TypeRef { +export function makeTypeRef (graph: TypeGraph, index: number): TypeRef { assert(index <= indexMask, "Too many types in graph"); - return ((graph.serial & serialMask) << indexBits) | index; + return (graph.serial & serialMask) << indexBits | index; } -export function typeRefIndex(tref: TypeRef): number { +export function typeRefIndex (tref: TypeRef): number { return tref & indexMask; } -export function assertTypeRefGraph(tref: TypeRef, graph: TypeGraph): void { +export function assertTypeRefGraph (tref: TypeRef, graph: TypeGraph): void { assert( - ((tref >> indexBits) & serialMask) === (graph.serial & serialMask), - "Mixing the wrong type reference and graph" + (tref >> indexBits & serialMask) === (graph.serial & serialMask), + "Mixing the wrong type reference and graph", ); } -function getGraph(graphOrBuilder: TypeGraph | BaseGraphRewriteBuilder): TypeGraph { +function getGraph (graphOrBuilder: TypeGraph | BaseGraphRewriteBuilder): TypeGraph { if (graphOrBuilder instanceof TypeGraph) return graphOrBuilder; return graphOrBuilder.originalGraph; } -export function derefTypeRef(tref: TypeRef, graphOrBuilder: TypeGraph | BaseGraphRewriteBuilder): Type { +export function derefTypeRef (tref: TypeRef, graphOrBuilder: TypeGraph | BaseGraphRewriteBuilder): Type { const graph = getGraph(graphOrBuilder); assertTypeRefGraph(tref, graph); return graph.typeAtIndex(typeRefIndex(tref)); } -export function attributesForTypeRef( +export function attributesForTypeRef ( tref: TypeRef, - graphOrBuilder: TypeGraph | BaseGraphRewriteBuilder + graphOrBuilder: TypeGraph | BaseGraphRewriteBuilder, ): TypeAttributes { const graph = getGraph(graphOrBuilder); assertTypeRefGraph(tref, graph); return graph.atIndex(typeRefIndex(tref))[1]; } -export function typeAndAttributesForTypeRef( +export function typeAndAttributesForTypeRef ( tref: TypeRef, - graphOrBuilder: TypeGraph | BaseGraphRewriteBuilder + graphOrBuilder: TypeGraph | BaseGraphRewriteBuilder, ): [Type, TypeAttributes] { const graph = getGraph(graphOrBuilder); assertTypeRefGraph(tref, graph); @@ -69,28 +74,30 @@ export function typeAndAttributesForTypeRef( export class TypeAttributeStore { private readonly _topLevelValues: Map = new Map(); - constructor(private readonly _typeGraph: TypeGraph, private _values: (TypeAttributes | undefined)[]) {} + constructor (private readonly _typeGraph: TypeGraph, private _values: Array) {} - private getTypeIndex(t: Type): number { + private getTypeIndex (t: Type): number { const tref = t.typeRef; assertTypeRefGraph(tref, this._typeGraph); return typeRefIndex(tref); } - attributesForType(t: Type): TypeAttributes { + attributesForType (t: Type): TypeAttributes { const index = this.getTypeIndex(t); const maybeAttributes = this._values[index]; if (maybeAttributes !== undefined) { return maybeAttributes; } + return emptyTypeAttributes; } - attributesForTopLevel(name: string): TypeAttributes { + attributesForTopLevel (name: string): TypeAttributes { const maybeAttributes = this._topLevelValues.get(name); if (maybeAttributes !== undefined) { return maybeAttributes; } + return emptyTypeAttributes; } @@ -104,6 +111,7 @@ export class TypeAttributeStore { while (index >= this._values.length) { this._values.push(undefined); } + this._values[index] = this.setInMap(this.attributesForType(t), kind, value); } @@ -125,38 +133,39 @@ export class TypeAttributeStore { } export class TypeAttributeStoreView { - constructor( + constructor ( private readonly _attributeStore: TypeAttributeStore, - private readonly _definition: TypeAttributeKind + private readonly _definition: TypeAttributeKind, ) {} - set(t: Type, value: T): void { + set (t: Type, value: T): void { this._attributeStore.set(this._definition, t, value); } - setForTopLevel(name: string, value: T): void { + setForTopLevel (name: string, value: T): void { this._attributeStore.setForTopLevel(this._definition, name, value); } - tryGet(t: Type): T | undefined { + tryGet (t: Type): T | undefined { return this._attributeStore.tryGet(this._definition, t); } - get(t: Type): T { + get (t: Type): T { return defined(this.tryGet(t)); } - tryGetForTopLevel(name: string): T | undefined { + tryGetForTopLevel (name: string): T | undefined { return this._attributeStore.tryGetForTopLevel(this._definition, name); } - getForTopLevel(name: string): T { + getForTopLevel (name: string): T { return defined(this.tryGetForTopLevel(name)); } } export class TypeGraph { private _typeBuilder?: TypeBuilder; + private _attributeStore: TypeAttributeStore | undefined = undefined; // FIXME: OrderedMap? We lose the order in PureScript right now, though, @@ -165,30 +174,30 @@ export class TypeGraph { private _types?: Type[]; - private _parents: Set[] | undefined = undefined; + private _parents: Array> | undefined = undefined; private _printOnRewrite = false; - constructor( + constructor ( typeBuilder: TypeBuilder, readonly serial: number, - private readonly _haveProvenanceAttributes: boolean + private readonly _haveProvenanceAttributes: boolean, ) { this._typeBuilder = typeBuilder; } - private get isFrozen(): boolean { + private get isFrozen (): boolean { return this._typeBuilder === undefined; } - get attributeStore(): TypeAttributeStore { + get attributeStore (): TypeAttributeStore { return defined(this._attributeStore); } - freeze( + freeze ( topLevels: ReadonlyMap, types: Type[], - typeAttributes: (TypeAttributes | undefined)[] + typeAttributes: Array, ): void { assert(!this.isFrozen, "Tried to freeze TypeGraph a second time"); for (const t of types) { @@ -206,31 +215,33 @@ export class TypeGraph { this._topLevels = mapMap(topLevels, tref => derefTypeRef(tref, this)); } - get topLevels(): ReadonlyMap { + get topLevels (): ReadonlyMap { assert(this.isFrozen, "Cannot get top-levels from a non-frozen graph"); return this._topLevels; } - typeAtIndex(index: number): Type { + typeAtIndex (index: number): Type { if (this._typeBuilder !== undefined) { return this._typeBuilder.typeAtIndex(index); } + return defined(this._types)[index]; } - atIndex(index: number): [Type, TypeAttributes] { + atIndex (index: number): [Type, TypeAttributes] { if (this._typeBuilder !== undefined) { return this._typeBuilder.atIndex(index); } + const t = this.typeAtIndex(index); return [t, defined(this._attributeStore).attributesForType(t)]; } - private filterTypes(predicate: ((t: Type) => boolean) | undefined): ReadonlySet { + private filterTypes (predicate: ((t: Type) => boolean) | undefined): ReadonlySet { const seen = new Set(); let types: Type[] = []; - function addFromType(t: Type): void { + function addFromType (t: Type): void { if (seen.has(t)) return; seen.add(t); @@ -248,19 +259,20 @@ export class TypeGraph { for (const [, t] of this.topLevels) { addFromType(t); } + return new Set(types); } - allNamedTypes(): ReadonlySet { + allNamedTypes (): ReadonlySet { return this.filterTypes(isNamedType); } - allNamedTypesSeparated(): SeparatedNamedTypes { + allNamedTypesSeparated (): SeparatedNamedTypes { const types = this.allNamedTypes(); return separateNamedTypes(types); } - private allProvenance(): ReadonlySet { + private allProvenance (): ReadonlySet { assert(this._haveProvenanceAttributes); const view = new TypeAttributeStoreView(this.attributeStore, provenanceTypeAttributeKind); @@ -274,11 +286,11 @@ export class TypeGraph { return result; } - setPrintOnRewrite(): void { + setPrintOnRewrite (): void { this._printOnRewrite = true; } - private checkLostTypeAttributes(builder: BaseGraphRewriteBuilder, newGraph: TypeGraph): void { + private checkLostTypeAttributes (builder: BaseGraphRewriteBuilder, newGraph: TypeGraph): void { if (!this._haveProvenanceAttributes || builder.lostTypeAttributes) return; const oldProvenance = this.allProvenance(); @@ -290,7 +302,7 @@ export class TypeGraph { } } - private printRewrite(title: string): void { + private printRewrite (title: string): void { if (!this._printOnRewrite) return; console.log(`\n# ${title}`); @@ -309,7 +321,7 @@ export class TypeGraph { replacementGroups: T[][], debugPrintReconstitution: boolean, replacer: (typesToReplace: ReadonlySet, builder: GraphRewriteBuilder, forwardingRef: TypeRef) => TypeRef, - force = false + force = false, ): TypeGraph { this.printRewrite(title); @@ -322,7 +334,7 @@ export class TypeGraph { this._haveProvenanceAttributes, replacementGroups, debugPrintReconstitution, - replacer + replacer, ); const newGraph = builder.finish(); @@ -338,13 +350,13 @@ export class TypeGraph { return removeIndirectionIntersections(newGraph, stringTypeMapping, debugPrintReconstitution); } - remap( + remap ( title: string, stringTypeMapping: StringTypeMapping, alphabetizeProperties: boolean, map: ReadonlyMap, debugPrintRemapping: boolean, - force = false + force = false, ): TypeGraph { this.printRewrite(title); @@ -356,7 +368,7 @@ export class TypeGraph { alphabetizeProperties, this._haveProvenanceAttributes, map, - debugPrintRemapping + debugPrintRemapping, ); const newGraph = builder.finish(); @@ -372,19 +384,19 @@ export class TypeGraph { return newGraph; } - garbageCollect(alphabetizeProperties: boolean, debugPrintReconstitution: boolean): TypeGraph { + garbageCollect (alphabetizeProperties: boolean, debugPrintReconstitution: boolean): TypeGraph { const newGraph = this.remap( "GC", getNoStringTypeMapping(), alphabetizeProperties, new Map(), debugPrintReconstitution, - true + true, ); return newGraph; } - rewriteFixedPoint(alphabetizeProperties: boolean, debugPrintReconstitution: boolean): TypeGraph { + rewriteFixedPoint (alphabetizeProperties: boolean, debugPrintReconstitution: boolean): TypeGraph { let graph: TypeGraph = this; for (;;) { const newGraph = this.rewrite( @@ -394,25 +406,26 @@ export class TypeGraph { [], debugPrintReconstitution, mustNotHappen, - true + true, ); if (graph.allTypesUnordered().size === newGraph.allTypesUnordered().size) { return graph; } + graph = newGraph; } } - allTypesUnordered(): ReadonlySet { + allTypesUnordered (): ReadonlySet { assert(this.isFrozen, "Tried to get all graph types before it was frozen"); return new Set(defined(this._types)); } - makeGraph(invertDirection: boolean, childrenOfType: (t: Type) => ReadonlySet): Graph { + makeGraph (invertDirection: boolean, childrenOfType: (t: Type) => ReadonlySet): Graph { return new Graph(defined(this._types), invertDirection, childrenOfType); } - getParentsOfType(t: Type): Set { + getParentsOfType (t: Type): Set { assertTypeRefGraph(t.typeRef, this); if (this._parents === undefined) { const parents = defined(this._types).map(_ => new Set()); @@ -422,12 +435,14 @@ export class TypeGraph { parents[index] = parents[index].add(p); } } + this._parents = parents; } + return this._parents[t.index]; } - printGraph(): void { + printGraph (): void { const types = defined(this._types); for (let i = 0; i < types.length; i++) { const t = types[i]; @@ -438,29 +453,32 @@ export class TypeGraph { parts.push( `children ${Array.from(children) .map(c => c.index) - .join(",")}` + .join(",")}`, ); } + for (const [kind, value] of t.getAttributes()) { const maybeString = kind.stringify(value); if (maybeString !== undefined) { parts.push(maybeString); } } + console.log(`${i}: ${parts.join(" | ")}`); } } } -export function noneToAny( +export function noneToAny ( graph: TypeGraph, stringTypeMapping: StringTypeMapping, - debugPrintReconstitution: boolean + debugPrintReconstitution: boolean, ): TypeGraph { const noneTypes = setFilter(graph.allTypesUnordered(), t => t.kind === "none"); if (noneTypes.size === 0) { return graph; } + assert(noneTypes.size === 1, "Cannot have more than one none type"); return graph.rewrite( "none to any", @@ -472,16 +490,16 @@ export function noneToAny( const attributes = combineTypeAttributesOfTypes("union", types); const tref = builder.getPrimitiveType("any", attributes, forwardingRef); return tref; - } + }, ); } -export function optionalToNullable( +export function optionalToNullable ( graph: TypeGraph, stringTypeMapping: StringTypeMapping, - debugPrintReconstitution: boolean + debugPrintReconstitution: boolean, ): TypeGraph { - function rewriteClass(c: ClassType, builder: GraphRewriteBuilder, forwardingRef: TypeRef): TypeRef { + function rewriteClass (c: ClassType, builder: GraphRewriteBuilder, forwardingRef: TypeRef): TypeRef { const properties = mapMap(c.getProperties(), (p, name) => { const t = p.type; let ref: TypeRef; @@ -495,11 +513,13 @@ export function optionalToNullable( } else { members = new Set([builder.reconstituteType(t), nullType]); } + const attributes = namesTypeAttributeKind.setDefaultInAttributes(t.getAttributes(), () => - TypeNames.make(new Set([name]), new Set(), true) + TypeNames.make(new Set([name]), new Set(), true), ); ref = builder.getUnionType(attributes, members); } + return builder.makeClassProperty(ref, p.isOptional); }); if (c.isFixed) { @@ -511,12 +531,13 @@ export function optionalToNullable( const classesWithOptional = setFilter( graph.allTypesUnordered(), - t => t instanceof ClassType && mapSome(t.getProperties(), p => p.isOptional) + t => t instanceof ClassType && mapSome(t.getProperties(), p => p.isOptional), ); const replacementGroups = Array.from(classesWithOptional).map(c => [c as ClassType]); if (classesWithOptional.size === 0) { return graph; } + return graph.rewrite( "optional to nullable", stringTypeMapping, @@ -527,16 +548,16 @@ export function optionalToNullable( assert(setOfClass.size === 1); const c = defined(iterableFirst(setOfClass)); return rewriteClass(c, builder, forwardingRef); - } + }, ); } -export function removeIndirectionIntersections( +export function removeIndirectionIntersections ( graph: TypeGraph, stringTypeMapping: StringTypeMapping, - debugPrintRemapping: boolean + debugPrintRemapping: boolean, ): TypeGraph { - const map: [Type, Type][] = []; + const map: Array<[Type, Type]> = []; for (const t of graph.allTypesUnordered()) { if (!(t instanceof IntersectionType)) continue; @@ -548,10 +569,12 @@ export function removeIndirectionIntersections( map.push([t, member]); break; } + if (seen.has(member)) { // FIXME: Technically, this is an any type. return panic("There's a cycle of intersection types"); } + seen.add(member); current = member; } diff --git a/packages/quicktype-core/src/TypeUtils.ts b/packages/quicktype-core/src/TypeUtils.ts index 36fb166a9..f85767fef 100644 --- a/packages/quicktype-core/src/TypeUtils.ts +++ b/packages/quicktype-core/src/TypeUtils.ts @@ -2,51 +2,57 @@ import { setFilter, setSortBy, iterableFirst, setUnion, EqualityMap } from "coll import { defined, panic, assert, assertNever } from "./support/Support"; import { - TypeAttributes, + type TypeAttributes, + type CombinationKind, +} from "./attributes/TypeAttributes"; +import { combineTypeAttributes, emptyTypeAttributes, - CombinationKind } from "./attributes/TypeAttributes"; import { - Type, - PrimitiveType, + type Type, + type PrimitiveType, + type ClassProperty, + type SetOperationType} from "./Type"; +import { ArrayType, EnumType, ObjectType, MapType, ClassType, - ClassProperty, - SetOperationType, UnionType, - isPrimitiveStringTypeKind + isPrimitiveStringTypeKind, } from "./Type"; -import { stringTypesTypeAttributeKind, StringTypes } from "./attributes/StringTypes"; +import { type StringTypes } from "./attributes/StringTypes"; +import { stringTypesTypeAttributeKind } from "./attributes/StringTypes"; -export function assertIsObject(t: Type): ObjectType { +export function assertIsObject (t: Type): ObjectType { if (t instanceof ObjectType) { return t; } + return panic("Supposed object type is not an object type"); } -export function assertIsClass(t: Type): ClassType { +export function assertIsClass (t: Type): ClassType { if (!(t instanceof ClassType)) { return panic("Supposed class type is not a class type"); } + return t; } -export function setOperationMembersRecursively( +export function setOperationMembersRecursively ( setOperation: T, combinationKind: CombinationKind | undefined ): [ReadonlySet, TypeAttributes]; -export function setOperationMembersRecursively( +export function setOperationMembersRecursively ( setOperations: T[], combinationKind: CombinationKind | undefined ): [ReadonlySet, TypeAttributes]; -export function setOperationMembersRecursively( +export function setOperationMembersRecursively ( oneOrMany: T | T[], - combinationKind: CombinationKind | undefined + combinationKind: CombinationKind | undefined, ): [ReadonlySet, TypeAttributes] { const setOperations = Array.isArray(oneOrMany) ? oneOrMany : [oneOrMany]; const kind = setOperations[0].kind; @@ -55,7 +61,7 @@ export function setOperationMembersRecursively( const members = new Set(); let attributes = emptyTypeAttributes; - function process(t: Type): void { + function process (t: Type): void { if (t.kind === kind) { const so = t as T; if (processedSetOperations.has(so)) return; @@ -63,6 +69,7 @@ export function setOperationMembersRecursively( if (combinationKind !== undefined) { attributes = combineTypeAttributes(combinationKind, attributes, t.getAttributes()); } + for (const m of so.members) { process(m); } @@ -78,12 +85,13 @@ export function setOperationMembersRecursively( for (const so of setOperations) { process(so); } + return [members, attributes]; } -export function makeGroupsToFlatten( +export function makeGroupsToFlatten ( setOperations: Iterable, - include: ((members: ReadonlySet) => boolean) | undefined + include: ((members: ReadonlySet) => boolean) | undefined, ): Type[][] { const typeGroups = new EqualityMap, Set>(); for (const u of setOperations) { @@ -102,6 +110,7 @@ export function makeGroupsToFlatten( maybeSet.add(defined(iterableFirst(members))); } } + maybeSet.add(u); typeGroups.set(members, maybeSet); } @@ -109,25 +118,25 @@ export function makeGroupsToFlatten( return Array.from(typeGroups.values()).map(ts => Array.from(ts)); } -export function combineTypeAttributesOfTypes(combinationKind: CombinationKind, types: Iterable): TypeAttributes { +export function combineTypeAttributesOfTypes (combinationKind: CombinationKind, types: Iterable): TypeAttributes { return combineTypeAttributes( combinationKind, - Array.from(types).map(t => t.getAttributes()) + Array.from(types).map(t => t.getAttributes()), ); } -export function isAnyOrNull(t: Type): boolean { +export function isAnyOrNull (t: Type): boolean { return t.kind === "any" || t.kind === "null"; } // FIXME: We shouldn't have to sort here. This is just because we're not getting // back the right order from JSON Schema, due to the changes the intersection types // introduced. -export function removeNullFromUnion( +export function removeNullFromUnion ( t: UnionType, - sortBy: boolean | ((t: Type) => any) = false + sortBy: boolean | ((t: Type) => any) = false, ): [PrimitiveType | null, ReadonlySet] { - function sort(s: ReadonlySet): ReadonlySet { + function sort (s: ReadonlySet): ReadonlySet { if (sortBy === false) return s; if (sortBy === true) return setSortBy(s, m => m.kind); return setSortBy(s, sortBy); @@ -137,54 +146,58 @@ export function removeNullFromUnion( if (nullType === undefined) { return [null, sort(t.members)]; } + return [nullType as PrimitiveType, sort(setFilter(t.members, m => m.kind !== "null"))]; } -export function removeNullFromType(t: Type): [PrimitiveType | null, ReadonlySet] { +export function removeNullFromType (t: Type): [PrimitiveType | null, ReadonlySet] { if (t.kind === "null") { return [t as PrimitiveType, new Set()]; } + if (!(t instanceof UnionType)) { return [null, new Set([t])]; } + return removeNullFromUnion(t); } -export function nullableFromUnion(t: UnionType): Type | null { +export function nullableFromUnion (t: UnionType): Type | null { const [hasNull, nonNulls] = removeNullFromUnion(t); if (hasNull === null) return null; if (nonNulls.size !== 1) return null; return defined(iterableFirst(nonNulls)); } -export function nonNullTypeCases(t: Type): ReadonlySet { +export function nonNullTypeCases (t: Type): ReadonlySet { return removeNullFromType(t)[1]; } -export function getNullAsOptional(cp: ClassProperty): [boolean, ReadonlySet] { +export function getNullAsOptional (cp: ClassProperty): [boolean, ReadonlySet] { const [maybeNull, nonNulls] = removeNullFromType(cp.type); if (cp.isOptional) { return [true, nonNulls]; } + return [maybeNull !== null, nonNulls]; } // FIXME: Give this an appropriate name, considering that we don't distinguish // between named and non-named types anymore. -export function isNamedType(t: Type): boolean { - return ["class", "union", "enum", "object"].indexOf(t.kind) >= 0; +export function isNamedType (t: Type): boolean { + return ["class", "union", "enum", "object"].includes(t.kind); } -export type SeparatedNamedTypes = { - objects: ReadonlySet; +export interface SeparatedNamedTypes { enums: ReadonlySet; + objects: ReadonlySet; unions: ReadonlySet; -}; +} -export function separateNamedTypes(types: Iterable): SeparatedNamedTypes { +export function separateNamedTypes (types: Iterable): SeparatedNamedTypes { const objects = setFilter( types, - t => t.kind === "object" || t.kind === "class" + t => t.kind === "object" || t.kind === "class", ) as Set as ReadonlySet; const enums = setFilter(types, t => t instanceof EnumType) as Set as ReadonlySet; const unions = setFilter(types, t => t instanceof UnionType) as Set as ReadonlySet; @@ -192,42 +205,44 @@ export function separateNamedTypes(types: Iterable): SeparatedNamedTypes { return { objects, enums, unions }; } -export function directlyReachableTypes(t: Type, setForType: (t: Type) => ReadonlySet | null): ReadonlySet { +export function directlyReachableTypes (t: Type, setForType: (t: Type) => ReadonlySet | null): ReadonlySet { const set = setForType(t); if (set !== null) return set; return setUnion(...Array.from(t.getNonAttributeChildren()).map(c => directlyReachableTypes(c, setForType))); } -export function directlyReachableSingleNamedType(type: Type): Type | undefined { +export function directlyReachableSingleNamedType (type: Type): Type | undefined { const definedTypes = directlyReachableTypes(type, t => { if ( - (!(t instanceof UnionType) && isNamedType(t)) || - (t instanceof UnionType && nullableFromUnion(t) === null) + !(t instanceof UnionType) && isNamedType(t) || + t instanceof UnionType && nullableFromUnion(t) === null ) { return new Set([t]); } + return null; }); assert(definedTypes.size <= 1, "Cannot have more than one defined type per top-level"); return iterableFirst(definedTypes); } -export function stringTypesForType(t: PrimitiveType): StringTypes { +export function stringTypesForType (t: PrimitiveType): StringTypes { assert(t.kind === "string", "Only strings can have string types"); const stringTypes = stringTypesTypeAttributeKind.tryGetInAttributes(t.getAttributes()); if (stringTypes === undefined) { return panic("All strings must have a string type attribute"); } + return stringTypes; } -export type StringTypeMatchers = { +export interface StringTypeMatchers { + dateTimeType?: (dateTimeType: PrimitiveType) => U; dateType?: (dateType: PrimitiveType) => U; timeType?: (timeType: PrimitiveType) => U; - dateTimeType?: (dateTimeType: PrimitiveType) => U; -}; +} -export function matchTypeExhaustive( +export function matchTypeExhaustive ( t: Type, noneType: (noneType: PrimitiveType) => U, anyType: (anyType: PrimitiveType) => U, @@ -242,15 +257,17 @@ export function matchTypeExhaustive( objectType: (objectType: ObjectType) => U, enumType: (enumType: EnumType) => U, unionType: (unionType: UnionType) => U, - transformedStringType: (transformedStringType: PrimitiveType) => U + transformedStringType: (transformedStringType: PrimitiveType) => U, ): U { if (t.isPrimitive()) { if (isPrimitiveStringTypeKind(t.kind)) { if (t.kind === "string") { return stringType(t); } + return transformedStringType(t); } + const kind = t.kind; const f = { none: noneType, @@ -258,7 +275,7 @@ export function matchTypeExhaustive( null: nullType, bool: boolType, integer: integerType, - double: doubleType + double: doubleType, }[kind]; if (f !== undefined) return f(t); return assertNever(f); @@ -271,7 +288,7 @@ export function matchTypeExhaustive( return panic(`Unknown type ${t.kind}`); } -export function matchType( +export function matchType ( type: Type, anyType: (anyType: PrimitiveType) => U, nullType: (nullType: PrimitiveType) => U, @@ -284,9 +301,9 @@ export function matchType( mapType: (mapType: MapType) => U, enumType: (enumType: EnumType) => U, unionType: (unionType: UnionType) => U, - transformedStringType?: (transformedStringType: PrimitiveType) => U + transformedStringType?: (transformedStringType: PrimitiveType) => U, ): U { - function typeNotSupported(t: Type) { + function typeNotSupported (t: Type) { return panic(`Unsupported type ${t.kind} in non-exhaustive match`); } @@ -305,23 +322,23 @@ export function matchType( typeNotSupported, enumType, unionType, - transformedStringType || typeNotSupported + transformedStringType || typeNotSupported, ); } -export function matchCompoundType( +export function matchCompoundType ( t: Type, arrayType: (arrayType: ArrayType) => void, classType: (classType: ClassType) => void, mapType: (mapType: MapType) => void, objectType: (objectType: ObjectType) => void, - unionType: (unionType: UnionType) => void + unionType: (unionType: UnionType) => void, ): void { - function ignore(_: T): void { + function ignore (_: T): void { return; } - return matchTypeExhaustive( + matchTypeExhaustive( t, ignore, ignore, @@ -336,6 +353,6 @@ export function matchCompoundType( objectType, ignore, unionType, - ignore + ignore, ); } diff --git a/packages/quicktype-core/src/UnifyClasses.ts b/packages/quicktype-core/src/UnifyClasses.ts index cb445ae82..b94bec7ad 100644 --- a/packages/quicktype-core/src/UnifyClasses.ts +++ b/packages/quicktype-core/src/UnifyClasses.ts @@ -1,18 +1,21 @@ import { iterableFirst, setUnionInto } from "collection-utils"; -import { Type, ClassProperty, UnionType, ObjectType } from "./Type"; +import { type Type, type ClassProperty, type ObjectType } from "./Type"; +import { UnionType } from "./Type"; import { assertIsObject } from "./TypeUtils"; -import { TypeBuilder } from "./TypeBuilder"; -import { TypeLookerUp, GraphRewriteBuilder, BaseGraphRewriteBuilder } from "./GraphRewriting"; +import { type TypeBuilder } from "./TypeBuilder"; +import { type TypeLookerUp, type GraphRewriteBuilder, type BaseGraphRewriteBuilder } from "./GraphRewriting"; import { UnionBuilder, TypeRefUnionAccumulator } from "./UnionBuilder"; import { panic, assert, defined } from "./support/Support"; -import { TypeAttributes, combineTypeAttributes, emptyTypeAttributes } from "./attributes/TypeAttributes"; -import { TypeRef, derefTypeRef } from "./TypeGraph"; +import { type TypeAttributes} from "./attributes/TypeAttributes"; +import { combineTypeAttributes, emptyTypeAttributes } from "./attributes/TypeAttributes"; +import { type TypeRef} from "./TypeGraph"; +import { derefTypeRef } from "./TypeGraph"; -function getCliqueProperties( +function getCliqueProperties ( clique: ObjectType[], builder: TypeBuilder, - makePropertyType: (types: ReadonlySet) => TypeRef + makePropertyType: (types: ReadonlySet) => TypeRef, ): [ReadonlyMap, TypeRef | undefined, boolean] { let lostTypeAttributes = false; let propertyNames = new Set(); @@ -28,6 +31,7 @@ function getCliqueProperties( if (additionalProperties === undefined) { additionalProperties = new Set(); } + if (additional !== undefined) { additionalProperties.add(additional); } @@ -45,6 +49,7 @@ function getCliqueProperties( if (maybeProperty.isOptional) { isOptional = true; } + types.add(maybeProperty.type); } @@ -63,10 +68,10 @@ function getCliqueProperties( return [unifiedProperties, unifiedAdditionalProperties, lostTypeAttributes]; } -function countProperties(clique: ObjectType[]): { - hasProperties: boolean; - hasAdditionalProperties: boolean; - hasNonAnyAdditionalProperties: boolean; +function countProperties (clique: ObjectType[]): { + hasAdditionalProperties: boolean, + hasNonAnyAdditionalProperties: boolean, + hasProperties: boolean, } { let hasProperties = false; let hasAdditionalProperties = false; @@ -75,6 +80,7 @@ function countProperties(clique: ObjectType[]): { if (o.getProperties().size > 0) { hasProperties = true; } + const additional = o.getAdditionalProperties(); if (additional !== undefined) { hasAdditionalProperties = true; @@ -83,29 +89,30 @@ function countProperties(clique: ObjectType[]): { } } } + return { hasProperties, hasAdditionalProperties, hasNonAnyAdditionalProperties }; } export class UnifyUnionBuilder extends UnionBuilder { - constructor( + constructor ( typeBuilder: BaseGraphRewriteBuilder, private readonly _makeObjectTypes: boolean, private readonly _makeClassesFixed: boolean, - private readonly _unifyTypes: (typesToUnify: TypeRef[]) => TypeRef + private readonly _unifyTypes: (typesToUnify: TypeRef[]) => TypeRef, ) { super(typeBuilder); } - protected makeObject( + protected makeObject ( objectRefs: TypeRef[], typeAttributes: TypeAttributes, - forwardingRef: TypeRef | undefined + forwardingRef: TypeRef | undefined, ): TypeRef { const maybeTypeRef = this.typeBuilder.lookupTypeRefs(objectRefs, forwardingRef); if (maybeTypeRef !== undefined) { assert( forwardingRef === undefined || maybeTypeRef === forwardingRef, - "The forwarding ref must be consumed" + "The forwarding ref must be consumed", ); this.typeBuilder.addAttributes(maybeTypeRef, typeAttributes); return maybeTypeRef; @@ -118,18 +125,19 @@ export class UnifyUnionBuilder extends UnionBuilder assertIsObject(derefTypeRef(r, this.typeBuilder))); const { hasProperties, hasAdditionalProperties, hasNonAnyAdditionalProperties } = countProperties(objectTypes); - if (!this._makeObjectTypes && (hasNonAnyAdditionalProperties || (!hasProperties && hasAdditionalProperties))) { + if (!this._makeObjectTypes && (hasNonAnyAdditionalProperties || !hasProperties && hasAdditionalProperties)) { const propertyTypes = new Set(); for (const o of objectTypes) { setUnionInto( propertyTypes, - Array.from(o.getProperties().values()).map(cp => cp.typeRef) + Array.from(o.getProperties().values()).map(cp => cp.typeRef), ); } + const additionalPropertyTypes = new Set( objectTypes .filter(o => o.getAdditionalProperties() !== undefined) - .map(o => defined(o.getAdditionalProperties()).typeRef) + .map(o => defined(o.getAdditionalProperties()).typeRef), ); setUnionInto(propertyTypes, additionalPropertyTypes); return this.typeBuilder.getMapType(typeAttributes, this._unifyTypes(Array.from(propertyTypes))); @@ -140,17 +148,18 @@ export class UnifyUnionBuilder extends UnionBuilder { assert(types.size > 0, "Property has no type"); return this._unifyTypes(Array.from(types).map(t => t.typeRef)); - } + }, ); if (lostTypeAttributes) { this.typeBuilder.setLostTypeAttributes(); } + if (this._makeObjectTypes) { return this.typeBuilder.getUniqueObjectType( typeAttributes, properties, additionalProperties, - forwardingRef + forwardingRef, ); } else { assert(additionalProperties === undefined, "We have additional properties but want to make a class"); @@ -158,27 +167,27 @@ export class UnifyUnionBuilder extends UnionBuilder( +export function unionBuilderForUnification ( typeBuilder: GraphRewriteBuilder, makeObjectTypes: boolean, makeClassesFixed: boolean, - conflateNumbers: boolean + conflateNumbers: boolean, ): UnionBuilder { return new UnifyUnionBuilder(typeBuilder, makeObjectTypes, makeClassesFixed, trefs => unifyTypes( @@ -186,20 +195,20 @@ export function unionBuilderForUnification( emptyTypeAttributes, typeBuilder, unionBuilderForUnification(typeBuilder, makeObjectTypes, makeClassesFixed, conflateNumbers), - conflateNumbers - ) + conflateNumbers, + ), ); } // typeAttributes must not be reconstituted yet. // FIXME: The UnionBuilder might end up not being used. -export function unifyTypes( +export function unifyTypes ( types: ReadonlySet, typeAttributes: TypeAttributes, typeBuilder: GraphRewriteBuilder, unionBuilder: UnionBuilder, conflateNumbers: boolean, - maybeForwardingRef?: TypeRef + maybeForwardingRef?: TypeRef, ): TypeRef { typeAttributes = typeBuilder.reconstituteTypeAttributes(typeAttributes); if (types.size === 0) { diff --git a/packages/quicktype-core/src/UnionBuilder.ts b/packages/quicktype-core/src/UnionBuilder.ts index c4a21d9d8..e3840144a 100644 --- a/packages/quicktype-core/src/UnionBuilder.ts +++ b/packages/quicktype-core/src/UnionBuilder.ts @@ -1,18 +1,20 @@ import { mapMerge, mapUpdateInto, mapMap, setUnionInto } from "collection-utils"; -import { TypeKind, PrimitiveStringTypeKind, Type, UnionType, PrimitiveTypeKind, isPrimitiveTypeKind } from "./Type"; +import { type TypeKind, type PrimitiveStringTypeKind, type Type, type PrimitiveTypeKind} from "./Type"; +import { UnionType, isPrimitiveTypeKind } from "./Type"; import { matchTypeExhaustive } from "./TypeUtils"; import { - TypeAttributes, + type TypeAttributes} from "./attributes/TypeAttributes"; +import { combineTypeAttributes, emptyTypeAttributes, makeTypeAttributesInferred, - increaseTypeAttributesDistance + increaseTypeAttributesDistance, } from "./attributes/TypeAttributes"; import { defined, assert, panic, assertNever } from "./support/Support"; -import { TypeBuilder } from "./TypeBuilder"; +import { type TypeBuilder } from "./TypeBuilder"; import { StringTypes, stringTypesTypeAttributeKind } from "./attributes/StringTypes"; -import { TypeRef } from "./TypeGraph"; +import { type TypeRef } from "./TypeGraph"; // FIXME: This interface is badly designed. All the properties // should use immutable types, and getMemberKinds should be @@ -22,53 +24,54 @@ import { TypeRef } from "./TypeGraph"; // Well, maybe getMemberKinds() is fine as it is. export interface UnionTypeProvider { readonly arrayData: TArrayData; - readonly objectData: TObjectData; - readonly enumCases: ReadonlySet; - getMemberKinds(): TypeAttributeMap; + getMemberKinds: () => TypeAttributeMap; readonly lostTypeAttributes: boolean; + + readonly objectData: TObjectData; } export type TypeAttributeMap = Map; type TypeAttributeMapBuilder = Map; -function addAttributes( +function addAttributes ( accumulatorAttributes: TypeAttributes | undefined, - newAttributes: TypeAttributes + newAttributes: TypeAttributes, ): TypeAttributes { if (accumulatorAttributes === undefined) return newAttributes; return combineTypeAttributes("union", accumulatorAttributes, newAttributes); } -function setAttributes( +function setAttributes ( attributeMap: TypeAttributeMap, kind: T, - newAttributes: TypeAttributes + newAttributes: TypeAttributes, ): void { attributeMap.set(kind, addAttributes(attributeMap.get(kind), newAttributes)); } -function addAttributesToBuilder( +function addAttributesToBuilder ( builder: TypeAttributeMapBuilder, kind: T, - newAttributes: TypeAttributes + newAttributes: TypeAttributes, ): void { let arr = builder.get(kind); if (arr === undefined) { arr = []; builder.set(kind, arr); } + arr.push(newAttributes); } -function buildTypeAttributeMap(builder: TypeAttributeMapBuilder): TypeAttributeMap { +function buildTypeAttributeMap (builder: TypeAttributeMapBuilder): TypeAttributeMap { return mapMap(builder, arr => combineTypeAttributes("union", arr)); } -function moveAttributes(map: TypeAttributeMap, fromKind: T, toKind: T): void { +function moveAttributes (map: TypeAttributeMap, fromKind: T, toKind: T): void { const fromAttributes = defined(map.get(fromKind)); map.delete(fromKind); setAttributes(map, toKind, fromAttributes); @@ -76,45 +79,50 @@ function moveAttributes(map: TypeAttributeMap, fromKind: export class UnionAccumulator implements UnionTypeProvider { private readonly _nonStringTypeAttributes: TypeAttributeMapBuilder = new Map(); + private readonly _stringTypeAttributes: TypeAttributeMapBuilder = new Map(); readonly arrayData: TArray[] = []; + readonly objectData: TObject[] = []; private readonly _enumCases: Set = new Set(); private _lostTypeAttributes = false; - constructor(private readonly _conflateNumbers: boolean) {} + constructor (private readonly _conflateNumbers: boolean) {} - private have(kind: TypeKind): boolean { + private have (kind: TypeKind): boolean { return ( this._nonStringTypeAttributes.has(kind) || this._stringTypeAttributes.has(kind as PrimitiveStringTypeKind) ); } - addNone(_attributes: TypeAttributes): void { + addNone (_attributes: TypeAttributes): void { // FIXME: Add them to all members? Or add them to the union, which means we'd have // to change getMemberKinds() to also return the attributes for the union itself, // or add a new method that does that. this._lostTypeAttributes = true; } - addAny(attributes: TypeAttributes): void { + + addAny (attributes: TypeAttributes): void { addAttributesToBuilder(this._nonStringTypeAttributes, "any", attributes); this._lostTypeAttributes = true; } - addPrimitive(kind: PrimitiveTypeKind, attributes: TypeAttributes): void { + + addPrimitive (kind: PrimitiveTypeKind, attributes: TypeAttributes): void { assert(kind !== "any", "any must be added with addAny"); addAttributesToBuilder(this._nonStringTypeAttributes, kind, attributes); } - protected addFullStringType(attributes: TypeAttributes, stringTypes: StringTypes | undefined): void { + protected addFullStringType (attributes: TypeAttributes, stringTypes: StringTypes | undefined): void { let stringTypesAttributes: TypeAttributes | undefined = undefined; if (stringTypes === undefined) { stringTypes = stringTypesTypeAttributeKind.tryGetInAttributes(attributes); } else { stringTypesAttributes = stringTypesTypeAttributeKind.makeAttributes(stringTypes); } + if (stringTypes === undefined) { stringTypes = StringTypes.unrestricted; stringTypesAttributes = stringTypesTypeAttributeKind.makeAttributes(stringTypes); @@ -124,7 +132,7 @@ export class UnionAccumulator implements UnionTypeProvider implements UnionTypeProvider, attributes: TypeAttributes): void { + addEnum (cases: ReadonlySet, attributes: TypeAttributes): void { const maybeStringAttributes = this._stringTypeAttributes.get("string"); if (maybeStringAttributes !== undefined) { addAttributesToBuilder(this._stringTypeAttributes, "string", attributes); return; } + addAttributesToBuilder(this._nonStringTypeAttributes, "enum", attributes); setUnionInto(this._enumCases, cases); } - addStringCases(cases: string[], attributes: TypeAttributes): void { + addStringCases (cases: string[], attributes: TypeAttributes): void { this.addFullStringType(attributes, StringTypes.fromCases(cases)); } - addStringCase(s: string, count: number, attributes: TypeAttributes): void { + + addStringCase (s: string, count: number, attributes: TypeAttributes): void { this.addFullStringType(attributes, StringTypes.fromCase(s, count)); } - get enumCases(): ReadonlySet { + get enumCases (): ReadonlySet { return this._enumCases; } - getMemberKinds(): TypeAttributeMap { + getMemberKinds (): TypeAttributeMap { assert(!(this.have("enum") && this.have("string")), "We can't have both strings and enums in the same union"); let merged = mapMerge( buildTypeAttributeMap(this._nonStringTypeAttributes), - buildTypeAttributeMap(this._stringTypeAttributes) + buildTypeAttributeMap(this._stringTypeAttributes), ); if (merged.size === 0) { @@ -201,26 +213,28 @@ export class UnionAccumulator implements UnionTypeProvider): [ReadonlyMap, TypeAttributes] { +function attributesForTypes (types: Iterable): [ReadonlyMap, TypeAttributes] { // These two maps are the reverse of each other. unionsForType is all the unions // that are ancestors of that type, when going from one of the given types, only // following unions. @@ -232,7 +246,7 @@ function attributesForTypes(types: Iterable): [ReadonlyMap = new Set(); - function traverse(t: Type, path: UnionOrFaux[], isEquivalentToRoot: boolean): void { + function traverse (t: Type, path: UnionOrFaux[], isEquivalentToRoot: boolean): void { if (t instanceof UnionType) { unions.add(t); if (isEquivalentToRoot) { @@ -244,11 +258,12 @@ function attributesForTypes(types: Iterable): [ReadonlyMap (s === undefined ? new Set(path) : setUnionInto(s, path))); + mapUpdateInto(unionsForType, t, s => s === undefined ? new Set(path) : setUnionInto(s, path)); for (const u of path) { - mapUpdateInto(typesForUnion, u, s => (s === undefined ? new Set([t]) : s.add(t))); + mapUpdateInto(typesForUnion, u, s => s === undefined ? new Set([t]) : s.add(t)); } } } @@ -263,7 +278,7 @@ function attributesForTypes(types: Iterable): [ReadonlyMap defined(typesForUnion.get(u)).size === 1); assert( singleAncestors.every(u => defined(typesForUnion.get(u)).has(t)), - "We messed up bookkeeping" + "We messed up bookkeeping", ); const inheritedAttributes = singleAncestors.map(u => u.getAttributes()); return combineTypeAttributes("union", [t.getAttributes()].concat(inheritedAttributes)); @@ -273,10 +288,12 @@ function attributesForTypes(types: Iterable): [ReadonlyMap): [ReadonlyMap { // There is a method analogous to this in the IntersectionAccumulator. It might // make sense to find a common interface. - private addType(t: Type, attributes: TypeAttributes): void { + private addType (t: Type, attributes: TypeAttributes): void { matchTypeExhaustive( t, _noneType => this.addNone(attributes), @@ -308,38 +325,39 @@ export class TypeRefUnionAccumulator extends UnionAccumulator return panic("The unions should have been eliminated in attributesForTypesInUnion"); }, transformedStringType => - this.addStringType(transformedStringType.kind as PrimitiveStringTypeKind, attributes) + this.addStringType(transformedStringType.kind as PrimitiveStringTypeKind, attributes), ); } - addTypes(types: Iterable): TypeAttributes { + addTypes (types: Iterable): TypeAttributes { const [attributesMap, unionAttributes] = attributesForTypes(types); for (const [t, attributes] of attributesMap) { this.addType(t, attributes); } + return unionAttributes; } } export abstract class UnionBuilder { - constructor(protected readonly typeBuilder: TBuilder) {} + constructor (protected readonly typeBuilder: TBuilder) {} - protected abstract makeObject( + protected abstract makeObject ( objects: TObjectData, typeAttributes: TypeAttributes, forwardingRef: TypeRef | undefined ): TypeRef; - protected abstract makeArray( + protected abstract makeArray ( arrays: TArrayData, typeAttributes: TypeAttributes, forwardingRef: TypeRef | undefined ): TypeRef; - private makeTypeOfKind( + private makeTypeOfKind ( typeProvider: UnionTypeProvider, kind: TypeKind, typeAttributes: TypeAttributes, - forwardingRef: TypeRef | undefined + forwardingRef: TypeRef | undefined, ): TypeRef { switch (kind) { case "string": @@ -354,18 +372,20 @@ export abstract class UnionBuilder, unique: boolean, typeAttributes: TypeAttributes, - forwardingRef?: TypeRef + forwardingRef?: TypeRef, ): TypeRef { const kinds = typeProvider.getMemberKinds(); @@ -382,7 +402,7 @@ export abstract class UnionBuilder; export type AccessorNames = Map; class AccessorNamesTypeAttributeKind extends TypeAttributeKind { - constructor() { + constructor () { super("accessorNames"); } - makeInferred(_: AccessorNames): undefined { + makeInferred (_: AccessorNames): undefined { return undefined; } } @@ -31,7 +32,7 @@ class AccessorNamesTypeAttributeKind extends TypeAttributeKind { export const accessorNamesTypeAttributeKind: TypeAttributeKind = new AccessorNamesTypeAttributeKind(); // Returns [name, isFixed]. -function getFromEntry(entry: AccessorEntry, language: string): [string, boolean] | undefined { +function getFromEntry (entry: AccessorEntry, language: string): [string, boolean] | undefined { if (typeof entry === "string") return [entry, false]; const maybeForLanguage = entry.get(language); @@ -43,28 +44,28 @@ function getFromEntry(entry: AccessorEntry, language: string): [string, boolean] return undefined; } -export function lookupKey(accessors: AccessorNames, key: string, language: string): [string, boolean] | undefined { +export function lookupKey (accessors: AccessorNames, key: string, language: string): [string, boolean] | undefined { const entry = accessors.get(key); if (entry === undefined) return undefined; return getFromEntry(entry, language); } -export function objectPropertyNames(o: ObjectType, language: string): Map { +export function objectPropertyNames (o: ObjectType, language: string): Map { const accessors = accessorNamesTypeAttributeKind.tryGetInAttributes(o.getAttributes()); const map = o.getProperties(); if (accessors === undefined) return mapMap(map, _ => undefined); return mapMap(map, (_cp, n) => lookupKey(accessors, n, language)); } -export function enumCaseNames(e: EnumType, language: string): Map { +export function enumCaseNames (e: EnumType, language: string): Map { const accessors = accessorNamesTypeAttributeKind.tryGetInAttributes(e.getAttributes()); if (accessors === undefined) return mapMap(e.cases.entries(), _ => undefined); return mapMap(e.cases.entries(), c => lookupKey(accessors, c, language)); } -export function getAccessorName( +export function getAccessorName ( names: Map, - original: string + original: string, ): [string | undefined, boolean] { const maybeName = names.get(original); if (maybeName === undefined) return [undefined, false]; @@ -79,15 +80,15 @@ export function getAccessorName( // up its union's identifier(s), and then look up the member's accessor entries for that // identifier. Of course we might find more than one, potentially conflicting. class UnionIdentifierTypeAttributeKind extends TypeAttributeKind> { - constructor() { + constructor () { super("unionIdentifier"); } - combine(arr: ReadonlySet[]): ReadonlySet { + combine (arr: Array>): ReadonlySet { return setUnionManyInto(new Set(), arr); } - makeInferred(_: ReadonlySet): ReadonlySet { + makeInferred (_: ReadonlySet): ReadonlySet { return new Set(); } } @@ -97,22 +98,23 @@ export const unionIdentifierTypeAttributeKind: TypeAttributeKind> { - constructor() { + constructor () { super("unionMemberNames"); } - combine(arr: Map[]): Map { + combine (arr: Array>): Map { const result = new Map(); for (const m of arr) { mapMergeInto(result, m); } + return result; } } @@ -120,13 +122,13 @@ class UnionMemberNamesTypeAttributeKind extends TypeAttributeKind> = new UnionMemberNamesTypeAttributeKind(); -export function makeUnionMemberNamesAttribute(unionAttributes: TypeAttributes, entry: AccessorEntry): TypeAttributes { +export function makeUnionMemberNamesAttribute (unionAttributes: TypeAttributes, entry: AccessorEntry): TypeAttributes { const identifiers = defined(unionIdentifierTypeAttributeKind.tryGetInAttributes(unionAttributes)); const map = mapFromIterable(identifiers, _ => entry); return unionMemberNamesTypeAttributeKind.makeAttributes(map); } -export function unionMemberName(u: UnionType, member: Type, language: string): [string | undefined, boolean] { +export function unionMemberName (u: UnionType, member: Type, language: string): [string | undefined, boolean] { const identifiers = unionIdentifierTypeAttributeKind.tryGetInAttributes(u.getAttributes()); if (identifiers === undefined) return [undefined, false]; @@ -166,29 +168,30 @@ export function unionMemberName(u: UnionType, member: Type, language: string): [ return [first, isFixed]; } -function isAccessorEntry(x: any): x is string | { [language: string]: string } { +function isAccessorEntry (x: any): x is string | { [language: string]: string, } { if (typeof x === "string") { return true; } + return isStringMap(x, (v: any): v is string => typeof v === "string"); } -function makeAccessorEntry(ae: string | { [language: string]: string }): AccessorEntry { +function makeAccessorEntry (ae: string | { [language: string]: string, }): AccessorEntry { if (typeof ae === "string") return ae; return mapFromObject(ae); } -export function makeAccessorNames(x: any): AccessorNames { +export function makeAccessorNames (x: any): AccessorNames { // FIXME: Do proper error reporting const stringMap = checkStringMap(x, isAccessorEntry); return mapMap(mapFromObject(stringMap), makeAccessorEntry); } -export function accessorNamesAttributeProducer( +export function accessorNamesAttributeProducer ( schema: JSONSchema, canonicalRef: Ref, _types: Set, - cases: JSONSchema[] | undefined + cases: JSONSchema[] | undefined, ): JSONSchemaAttributes | undefined { if (typeof schema !== "object") return undefined; const maybeAccessors = schema["qt-accessors"]; @@ -202,10 +205,10 @@ export function accessorNamesAttributeProducer( const accessors = checkArray(maybeAccessors, isAccessorEntry); messageAssert(cases.length === accessors.length, "SchemaWrongAccessorEntryArrayLength", { operation: "oneOf", - ref: canonicalRef.push("oneOf") + ref: canonicalRef.push("oneOf"), }); const caseAttributes = accessors.map(accessor => - makeUnionMemberNamesAttribute(identifierAttribute, makeAccessorEntry(accessor)) + makeUnionMemberNamesAttribute(identifierAttribute, makeAccessorEntry(accessor)), ); return { forUnion: identifierAttribute, forCases: caseAttributes }; } diff --git a/packages/quicktype-core/src/attributes/Constraints.ts b/packages/quicktype-core/src/attributes/Constraints.ts index a0370f4cc..d63442f26 100644 --- a/packages/quicktype-core/src/attributes/Constraints.ts +++ b/packages/quicktype-core/src/attributes/Constraints.ts @@ -1,41 +1,43 @@ -import { Type, TypeKind } from "../Type"; +import { type Type, type TypeKind } from "../Type"; import { TypeAttributeKind } from "./TypeAttributes"; import { assert } from "../support/Support"; import { messageError } from "../Messages"; -import { JSONSchemaType, JSONSchemaAttributes, Ref } from "../input/JSONSchemaInput"; -import { JSONSchema } from "../input/JSONSchemaStore"; +import { type JSONSchemaType, type JSONSchemaAttributes, type Ref } from "../input/JSONSchemaInput"; +import { type JSONSchema } from "../input/JSONSchemaStore"; // This can't be an object type, unfortunately, because it's in the // type's identity and as such must be comparable and hashable with // `areEqual`, `hashCodeOf`. export type MinMaxConstraint = [number | undefined, number | undefined]; -function checkMinMaxConstraint(minmax: MinMaxConstraint): MinMaxConstraint | undefined { +function checkMinMaxConstraint (minmax: MinMaxConstraint): MinMaxConstraint | undefined { const [min, max] = minmax; if (typeof min === "number" && typeof max === "number" && min > max) { return messageError("MiscInvalidMinMaxConstraint", { min, max }); } + if (min === undefined && max === undefined) { return undefined; } + return minmax; } export class MinMaxConstraintTypeAttributeKind extends TypeAttributeKind { - constructor( + constructor ( name: string, - private _typeKinds: Set, + private readonly _typeKinds: Set, private _minSchemaProperty: string, - private _maxSchemaProperty: string + private _maxSchemaProperty: string, ) { super(name); } - get inIdentity(): boolean { + get inIdentity (): boolean { return true; } - combine(arr: MinMaxConstraint[]): MinMaxConstraint | undefined { + combine (arr: MinMaxConstraint[]): MinMaxConstraint | undefined { assert(arr.length > 0); let [min, max] = arr[0]; @@ -46,16 +48,18 @@ export class MinMaxConstraintTypeAttributeKind extends TypeAttributeKind 0); let [min, max] = arr[0]; @@ -66,32 +70,35 @@ export class MinMaxConstraintTypeAttributeKind extends TypeAttributeKind = new "minMax", new Set(["integer", "double"]), "minimum", - "maximum" + "maximum", ); export const minMaxLengthTypeAttributeKind: TypeAttributeKind = new MinMaxConstraintTypeAttributeKind( "minMaxLength", new Set(["string"]), "minLength", - "maxLength" + "maxLength", ); -function producer(schema: JSONSchema, minProperty: string, maxProperty: string): MinMaxConstraint | undefined { +function producer (schema: JSONSchema, minProperty: string, maxProperty: string): MinMaxConstraint | undefined { if (!(typeof schema === "object")) return undefined; let min: number | undefined = undefined; @@ -119,6 +126,7 @@ function producer(schema: JSONSchema, minProperty: string, maxProperty: string): if (typeof schema[minProperty] === "number") { min = schema[minProperty]; } + if (typeof schema[maxProperty] === "number") { max = schema[maxProperty]; } @@ -127,10 +135,10 @@ function producer(schema: JSONSchema, minProperty: string, maxProperty: string): return [min, max]; } -export function minMaxAttributeProducer( +export function minMaxAttributeProducer ( schema: JSONSchema, _ref: Ref, - types: Set + types: Set, ): JSONSchemaAttributes | undefined { if (!types.has("number") && !types.has("integer")) return undefined; @@ -139,10 +147,10 @@ export function minMaxAttributeProducer( return { forNumber: minMaxTypeAttributeKind.makeAttributes(maybeMinMax) }; } -export function minMaxLengthAttributeProducer( +export function minMaxLengthAttributeProducer ( schema: JSONSchema, _ref: Ref, - types: Set + types: Set, ): JSONSchemaAttributes | undefined { if (!types.has("string")) return undefined; @@ -151,38 +159,38 @@ export function minMaxLengthAttributeProducer( return { forString: minMaxLengthTypeAttributeKind.makeAttributes(maybeMinMaxLength) }; } -export function minMaxValueForType(t: Type): MinMaxConstraint | undefined { +export function minMaxValueForType (t: Type): MinMaxConstraint | undefined { return minMaxTypeAttributeKind.tryGetInAttributes(t.getAttributes()); } -export function minMaxLengthForType(t: Type): MinMaxConstraint | undefined { +export function minMaxLengthForType (t: Type): MinMaxConstraint | undefined { return minMaxLengthTypeAttributeKind.tryGetInAttributes(t.getAttributes()); } export class PatternTypeAttributeKind extends TypeAttributeKind { - constructor() { + constructor () { super("pattern"); } - get inIdentity(): boolean { + get inIdentity (): boolean { return true; } - combine(arr: string[]): string { + combine (arr: string[]): string { assert(arr.length > 0); return arr.map(p => `(${p})`).join("|"); } - intersect(_arr: string[]): string | undefined { + intersect (_arr: string[]): string | undefined { /** FIXME!!! what is the intersection of regexps? */ return undefined; } - makeInferred(_: string): undefined { + makeInferred (_: string): undefined { return undefined; } - addToSchema(schema: { [name: string]: unknown }, t: Type, attr: string): void { + addToSchema (schema: { [name: string]: unknown, }, t: Type, attr: string): void { if (t.kind !== "string") return; schema.pattern = attr; } @@ -190,10 +198,10 @@ export class PatternTypeAttributeKind extends TypeAttributeKind { export const patternTypeAttributeKind: TypeAttributeKind = new PatternTypeAttributeKind(); -export function patternAttributeProducer( +export function patternAttributeProducer ( schema: JSONSchema, _ref: Ref, - types: Set + types: Set, ): JSONSchemaAttributes | undefined { if (!(typeof schema === "object")) return undefined; if (!types.has("string")) return undefined; @@ -203,6 +211,6 @@ export function patternAttributeProducer( return { forString: patternTypeAttributeKind.makeAttributes(patt) }; } -export function patternForType(t: Type): string | undefined { +export function patternForType (t: Type): string | undefined { return patternTypeAttributeKind.tryGetInAttributes(t.getAttributes()); } diff --git a/packages/quicktype-core/src/attributes/Description.ts b/packages/quicktype-core/src/attributes/Description.ts index 6684b95c3..34bc6151c 100644 --- a/packages/quicktype-core/src/attributes/Description.ts +++ b/packages/quicktype-core/src/attributes/Description.ts @@ -5,51 +5,54 @@ import { iterableFirst, setUnionManyInto, mapMergeWithInto, - setSubtract + setSubtract, } from "collection-utils"; // There's a cyclic import here. Ignoring now because it requires a large refactor. // skipcq: JS-E1008 import { TypeAttributeKind, emptyTypeAttributes } from "./TypeAttributes"; // FIXME: This is a circular import -import { JSONSchemaType, Ref, JSONSchemaAttributes, PathElementKind, PathElement } from "../input/JSONSchemaInput"; -import { JSONSchema } from "../input/JSONSchemaStore"; -import { Type } from "../Type"; - -export function addDescriptionToSchema( - schema: { [name: string]: unknown }, - description: Iterable | undefined +import { type JSONSchemaType, type Ref, type JSONSchemaAttributes, type PathElement } from "../input/JSONSchemaInput"; +import { PathElementKind } from "../input/JSONSchemaInput"; +import { type JSONSchema } from "../input/JSONSchemaStore"; +import { type Type } from "../Type"; + +export function addDescriptionToSchema ( + schema: { [name: string]: unknown, }, + description: Iterable | undefined, ): void { if (description === undefined) return; schema.description = Array.from(description).join("\n"); } class DescriptionTypeAttributeKind extends TypeAttributeKind> { - constructor() { + constructor () { super("description"); } - combine(attrs: ReadonlySet[]): ReadonlySet { + combine (attrs: Array>): ReadonlySet { return setUnionManyInto(new Set(), attrs); } - makeInferred(_: ReadonlySet): undefined { + makeInferred (_: ReadonlySet): undefined { return undefined; } - addToSchema(schema: { [name: string]: unknown }, _t: Type, attrs: ReadonlySet): void { + addToSchema (schema: { [name: string]: unknown, }, _t: Type, attrs: ReadonlySet): void { addDescriptionToSchema(schema, attrs); } - stringify(descriptions: ReadonlySet): string | undefined { + stringify (descriptions: ReadonlySet): string | undefined { let result = iterableFirst(descriptions); if (result === undefined) return undefined; if (result.length > 5 + 3) { result = `${result.slice(0, 5)}...`; } + if (descriptions.size > 1) { result = `${result}, ...`; } + return result; } } @@ -57,24 +60,25 @@ class DescriptionTypeAttributeKind extends TypeAttributeKind export const descriptionTypeAttributeKind: TypeAttributeKind> = new DescriptionTypeAttributeKind(); class PropertyDescriptionsTypeAttributeKind extends TypeAttributeKind>> { - constructor() { + constructor () { super("propertyDescriptions"); } - combine(attrs: Map>[]): Map> { + combine (attrs: Array>>): Map> { // FIXME: Implement this with mutable sets const result = new Map>(); for (const attr of attrs) { mapMergeWithInto(result, (sa, sb) => setUnion(sa, sb), attr); } + return result; } - makeInferred(_: Map>): undefined { + makeInferred (_: Map>): undefined { return undefined; } - stringify(propertyDescriptions: Map>): string | undefined { + stringify (propertyDescriptions: Map>): string | undefined { if (propertyDescriptions.size === 0) return undefined; return `prop descs: ${propertyDescriptions.size}`; } @@ -83,14 +87,14 @@ class PropertyDescriptionsTypeAttributeKind extends TypeAttributeKind>> = new PropertyDescriptionsTypeAttributeKind(); -function isPropertiesKey(el: PathElement): boolean { +function isPropertiesKey (el: PathElement): boolean { return el.kind === PathElementKind.KeyOrIndex && el.key === "properties"; } -export function descriptionAttributeProducer( +export function descriptionAttributeProducer ( schema: JSONSchema, ref: Ref, - types: Set + types: Set, ): JSONSchemaAttributes | undefined { if (!(typeof schema === "object")) return undefined; @@ -119,6 +123,7 @@ export function descriptionAttributeProducer( return new Set([desc]); } } + return undefined; }); if (propertyDescriptions.size > 0) { diff --git a/packages/quicktype-core/src/attributes/EnumValues.ts b/packages/quicktype-core/src/attributes/EnumValues.ts index f81b73a37..ccb3a6a24 100644 --- a/packages/quicktype-core/src/attributes/EnumValues.ts +++ b/packages/quicktype-core/src/attributes/EnumValues.ts @@ -1,32 +1,34 @@ import { mapMap } from "collection-utils"; -import { lookupKey, AccessorNames, makeAccessorNames } from "./AccessorNames"; -import { EnumType } from "../Type"; +import { type AccessorNames} from "./AccessorNames"; +import { lookupKey, makeAccessorNames } from "./AccessorNames"; +import { type EnumType } from "../Type"; import { TypeAttributeKind } from "./TypeAttributes"; -import { JSONSchema } from "../input/JSONSchemaStore"; -import { Ref, JSONSchemaType, JSONSchemaAttributes } from "../input/JSONSchemaInput"; +import { type JSONSchema } from "../input/JSONSchemaStore"; +import { type Ref, type JSONSchemaType, type JSONSchemaAttributes } from "../input/JSONSchemaInput"; class EnumValuesTypeAttributeKind extends TypeAttributeKind { - constructor() { + constructor () { super("enumValues"); } - makeInferred(_: AccessorNames) { + + makeInferred (_: AccessorNames) { return undefined; } } export const enumValuesTypeAttributeKind: TypeAttributeKind = new EnumValuesTypeAttributeKind(); -export function enumCaseValues(e: EnumType, language: string): Map { +export function enumCaseValues (e: EnumType, language: string): Map { const enumValues = enumValuesTypeAttributeKind.tryGetInAttributes(e.getAttributes()); if (enumValues === undefined) return mapMap(e.cases.entries(), _ => undefined); return mapMap(e.cases.entries(), c => lookupKey(enumValues, c, language)); } -export function enumValuesAttributeProducer( +export function enumValuesAttributeProducer ( schema: JSONSchema, _canonicalRef: Ref | undefined, - _types: Set + _types: Set, ): JSONSchemaAttributes | undefined { if (typeof schema !== "object") return undefined; diff --git a/packages/quicktype-core/src/attributes/StringTypes.ts b/packages/quicktype-core/src/attributes/StringTypes.ts index c14d7d58d..555301d80 100644 --- a/packages/quicktype-core/src/attributes/StringTypes.ts +++ b/packages/quicktype-core/src/attributes/StringTypes.ts @@ -7,47 +7,49 @@ import { mapMergeWithInto, definedMap, addHashCode, - setUnionInto + setUnionInto, } from "collection-utils"; import { TypeAttributeKind } from "./TypeAttributes"; import { defined, assert } from "../support/Support"; -import { StringTypeMapping, stringTypeMappingGet } from "../TypeBuilder"; -import { TransformedStringTypeKind } from "../Type"; -import { DateTimeRecognizer } from "../DateTime"; +import { type StringTypeMapping} from "../TypeBuilder"; +import { stringTypeMappingGet } from "../TypeBuilder"; +import { type TransformedStringTypeKind } from "../Type"; +import { type DateTimeRecognizer } from "../DateTime"; export class StringTypes { static readonly unrestricted: StringTypes = new StringTypes(undefined, new Set()); - static fromCase(s: string, count: number): StringTypes { - const caseMap: { [name: string]: number } = {}; + static fromCase (s: string, count: number): StringTypes { + const caseMap: { [name: string]: number, } = {}; caseMap[s] = count; return new StringTypes(new Map([[s, count] as [string, number]]), new Set()); } - static fromCases(cases: string[]): StringTypes { - const caseMap: { [name: string]: number } = {}; + static fromCases (cases: string[]): StringTypes { + const caseMap: { [name: string]: number, } = {}; for (const s of cases) { caseMap[s] = 1; } + return new StringTypes(new Map(cases.map(s => [s, 1] as [string, number])), new Set()); } // undefined means no restrictions - constructor( + constructor ( readonly cases: ReadonlyMap | undefined, - readonly transformations: ReadonlySet + readonly transformations: ReadonlySet, ) { if (cases === undefined) { assert(transformations.size === 0, "We can't have an unrestricted string that also allows transformations"); } } - get isRestricted(): boolean { + get isRestricted (): boolean { return this.cases !== undefined; } - union(othersArray: StringTypes[], startIndex: number): StringTypes { + union (othersArray: StringTypes[], startIndex: number): StringTypes { if (this.cases === undefined) return this; const cases = new Map(this.cases); @@ -65,7 +67,7 @@ export class StringTypes { return new StringTypes(cases, transformations); } - intersect(othersArray: StringTypes[], startIndex: number): StringTypes { + intersect (othersArray: StringTypes[], startIndex: number): StringTypes { let cases = this.cases; let transformations = this.transformations; @@ -89,10 +91,11 @@ export class StringTypes { transformations = setIntersect(transformations, other.transformations); } + return new StringTypes(cases, transformations); } - applyStringTypeMapping(mapping: StringTypeMapping): StringTypes { + applyStringTypeMapping (mapping: StringTypeMapping): StringTypes { if (!this.isRestricted) return this; const kinds = new Set(); @@ -101,21 +104,22 @@ export class StringTypes { if (mapped === "string") return StringTypes.unrestricted; kinds.add(mapped); } + return new StringTypes(this.cases, new Set(kinds)); } - equals(other: any): boolean { + equals (other: any): boolean { if (!(other instanceof StringTypes)) return false; return areEqual(this.cases, other.cases) && areEqual(this.transformations, other.transformations); } - hashCode(): number { + hashCode (): number { let h = hashCodeOf(this.cases); h = addHashCode(h, hashCodeOf(this.transformations)); return h; } - toString(): string { + toString (): string { const parts: string[] = []; const enumCases = this.cases; @@ -135,33 +139,33 @@ export class StringTypes { } class StringTypesTypeAttributeKind extends TypeAttributeKind { - constructor() { + constructor () { super("stringTypes"); } - get inIdentity(): boolean { + get inIdentity (): boolean { return true; } - requiresUniqueIdentity(st: StringTypes): boolean { + requiresUniqueIdentity (st: StringTypes): boolean { return st.cases !== undefined && st.cases.size > 0; } - combine(arr: StringTypes[]): StringTypes { + combine (arr: StringTypes[]): StringTypes { assert(arr.length > 0); return arr[0].union(arr, 1); } - intersect(arr: StringTypes[]): StringTypes { + intersect (arr: StringTypes[]): StringTypes { assert(arr.length > 0); return arr[0].intersect(arr, 1); } - makeInferred(_: StringTypes): undefined { + makeInferred (_: StringTypes): undefined { return undefined; } - stringify(st: StringTypes): string { + stringify (st: StringTypes): string { return st.toString(); } } @@ -174,18 +178,19 @@ const INTEGER_STRING = /^(0|-?[1-9]\d*)$/; const MIN_INTEGER_STRING = 1 << 31; const MAX_INTEGER_STRING = -(MIN_INTEGER_STRING + 1); -function isIntegerString(s: string): boolean { - if (s.match(INTEGER_STRING) === null) { +function isIntegerString (s: string): boolean { + if (INTEGER_STRING.exec(s) === null) { return false; } + const i = parseInt(s, 10); return i >= MIN_INTEGER_STRING && i <= MAX_INTEGER_STRING; } const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/; -function isUUID(s: string): boolean { - return s.match(UUID) !== null; +function isUUID (s: string): boolean { + return UUID.exec(s) !== null; } // FIXME: This is obviously not a complete URI regex. The exclusion of @@ -193,8 +198,8 @@ function isUUID(s: string): boolean { // with those characters which ajv refuses to accept as `uri`. const URI = /^(https?|ftp):\/\/[^{}]+$/; -function isURI(s: string): boolean { - return s.match(URI) !== null; +function isURI (s: string): boolean { + return URI.exec(s) !== null; } /** @@ -204,11 +209,11 @@ function isURI(s: string): boolean { * * @param s The string for which to determine the transformed string type kind. */ -export function inferTransformedStringTypeKindForString( +export function inferTransformedStringTypeKindForString ( s: string, - recognizer: DateTimeRecognizer + recognizer: DateTimeRecognizer, ): TransformedStringTypeKind | undefined { - if (s.length === 0 || "0123456789-abcdefth".indexOf(s[0]) < 0) return undefined; + if (s.length === 0 || !"0123456789-abcdefth".includes(s[0])) return undefined; if (recognizer.isDate(s)) { return "date"; @@ -225,5 +230,6 @@ export function inferTransformedStringTypeKindForString( } else if (isURI(s)) { return "uri"; } + return undefined; } diff --git a/packages/quicktype-core/src/attributes/TypeAttributes.ts b/packages/quicktype-core/src/attributes/TypeAttributes.ts index 1c73e8ffc..2077e0ca1 100644 --- a/packages/quicktype-core/src/attributes/TypeAttributes.ts +++ b/packages/quicktype-core/src/attributes/TypeAttributes.ts @@ -1,49 +1,49 @@ import { mapFilterMap, mapFilter, mapTranspose, hashString } from "collection-utils"; import { panic, assert } from "../support/Support"; -import { Type, TypeKind } from "../Type"; -import { BaseGraphRewriteBuilder } from "../GraphRewriting"; +import { type Type, type TypeKind } from "../Type"; +import { type BaseGraphRewriteBuilder } from "../GraphRewriting"; export class TypeAttributeKind { - constructor(readonly name: string) {} + constructor (readonly name: string) {} - appliesToTypeKind(kind: TypeKind): boolean { + appliesToTypeKind (kind: TypeKind): boolean { return kind !== "any"; } - combine(_attrs: T[]): T | undefined { + combine (_attrs: T[]): T | undefined { return panic(`Cannot combine type attribute ${this.name}`); } - intersect(attrs: T[]): T | undefined { + intersect (attrs: T[]): T | undefined { return this.combine(attrs); } - makeInferred(_: T): T | undefined { + makeInferred (_: T): T | undefined { return panic(`Cannot make type attribute ${this.name} inferred`); } - increaseDistance(attrs: T): T | undefined { + increaseDistance (attrs: T): T | undefined { return attrs; } - addToSchema(_schema: { [name: string]: unknown }, _t: Type, _attrs: T): void { + addToSchema (_schema: { [name: string]: unknown, }, _t: Type, _attrs: T): void { return; } - children(_: T): ReadonlySet { + children (_: T): ReadonlySet { return new Set(); } - stringify(_: T): string | undefined { + stringify (_: T): string | undefined { return undefined; } - get inIdentity(): boolean { + get inIdentity (): boolean { return false; } - requiresUniqueIdentity(_: T): boolean { + requiresUniqueIdentity (_: T): boolean { return false; } @@ -51,21 +51,21 @@ export class TypeAttributeKind { return a; } - makeAttributes(value: T): TypeAttributes { - const kvps: [this, T][] = [[this, value]]; + makeAttributes (value: T): TypeAttributes { + const kvps: Array<[this, T]> = [[this, value]]; return new Map(kvps); } - tryGetInAttributes(a: TypeAttributes): T | undefined { + tryGetInAttributes (a: TypeAttributes): T | undefined { return a.get(this); } - private setInAttributes(a: TypeAttributes, value: T): TypeAttributes { + private setInAttributes (a: TypeAttributes, value: T): TypeAttributes { // FIXME: This is potentially super slow return new Map(a).set(this, value); } - modifyInAttributes(a: TypeAttributes, modify: (value: T | undefined) => T | undefined): TypeAttributes { + modifyInAttributes (a: TypeAttributes, modify: (value: T | undefined) => T | undefined): TypeAttributes { const modified = modify(this.tryGetInAttributes(a)); if (modified === undefined) { // FIXME: This is potentially super slow @@ -73,26 +73,28 @@ export class TypeAttributeKind { result.delete(this); return result; } + return this.setInAttributes(a, modified); } - setDefaultInAttributes(a: TypeAttributes, makeDefault: () => T): TypeAttributes { + setDefaultInAttributes (a: TypeAttributes, makeDefault: () => T): TypeAttributes { if (this.tryGetInAttributes(a) !== undefined) return a; return this.modifyInAttributes(a, makeDefault); } - removeInAttributes(a: TypeAttributes): TypeAttributes { + removeInAttributes (a: TypeAttributes): TypeAttributes { return mapFilter(a, (_, k) => k !== this); } - equals(other: any): boolean { + equals (other: any): boolean { if (!(other instanceof TypeAttributeKind)) { return false; } + return this.name === other.name; } - hashCode(): number { + hashCode (): number { return hashString(this.name); } } @@ -103,12 +105,12 @@ export const emptyTypeAttributes: TypeAttributes = new Map(); export type CombinationKind = "union" | "intersect"; -export function combineTypeAttributes(kind: CombinationKind, attributeArray: TypeAttributes[]): TypeAttributes; -export function combineTypeAttributes(kind: CombinationKind, a: TypeAttributes, b: TypeAttributes): TypeAttributes; -export function combineTypeAttributes( +export function combineTypeAttributes (kind: CombinationKind, attributeArray: TypeAttributes[]): TypeAttributes; +export function combineTypeAttributes (kind: CombinationKind, a: TypeAttributes, b: TypeAttributes): TypeAttributes; +export function combineTypeAttributes ( combinationKind: CombinationKind, firstOrArray: TypeAttributes[] | TypeAttributes, - second?: TypeAttributes + second?: TypeAttributes, ): TypeAttributes { const union = combinationKind === "union"; let attributeArray: TypeAttributes[]; @@ -118,12 +120,13 @@ export function combineTypeAttributes( if (second === undefined) { return panic("Must have on array or two attributes"); } + attributeArray = [firstOrArray, second]; } const attributesByKind = mapTranspose(attributeArray); - function combine(attrs: any[], kind: TypeAttributeKind): any { + function combine (attrs: any[], kind: TypeAttributeKind): any { assert(attrs.length > 0, "Cannot combine zero type attributes"); if (attrs.length === 1) return attrs[0]; if (union) { @@ -136,10 +139,10 @@ export function combineTypeAttributes( return mapFilterMap(attributesByKind, combine); } -export function makeTypeAttributesInferred(attr: TypeAttributes): TypeAttributes { +export function makeTypeAttributesInferred (attr: TypeAttributes): TypeAttributes { return mapFilterMap(attr, (value, kind) => kind.makeInferred(value)); } -export function increaseTypeAttributesDistance(attr: TypeAttributes): TypeAttributes { +export function increaseTypeAttributesDistance (attr: TypeAttributes): TypeAttributes { return mapFilterMap(attr, (value, kind) => kind.increaseDistance(value)); } diff --git a/packages/quicktype-core/src/attributes/TypeNames.ts b/packages/quicktype-core/src/attributes/TypeNames.ts index c7225f3b7..119ebec14 100644 --- a/packages/quicktype-core/src/attributes/TypeNames.ts +++ b/packages/quicktype-core/src/attributes/TypeNames.ts @@ -2,21 +2,22 @@ import * as pluralize from "pluralize"; import { setMap, iterableFirst, iterableSkip, setUnionInto, definedMap } from "collection-utils"; import { panic, defined, assert } from "../support/Support"; -import { TypeAttributeKind, TypeAttributes } from "./TypeAttributes"; +import { type TypeAttributes } from "./TypeAttributes"; +import { TypeAttributeKind } from "./TypeAttributes"; import { splitIntoWords } from "../support/Strings"; import { Chance } from "../support/Chance"; let chance: Chance; let usedRandomNames: Set; -export function initTypeNames(): void { +export function initTypeNames (): void { chance = new Chance(31415); usedRandomNames = new Set(); } initTypeNames(); -function makeRandomName(): string { +function makeRandomName (): string { for (;;) { const name = `${chance.city()} ${chance.animal()}`; if (usedRandomNames.has(name)) continue; @@ -31,11 +32,12 @@ export type NameOrNames = string | TypeNames; // produce a name that includes the overlap twice. For example, for // the names "aaa" and "aaaa" we have the common prefix "aaa" and the // common suffix "aaa", so we will produce the combined name "aaaaaa". -function combineNames(names: ReadonlySet): string { +function combineNames (names: ReadonlySet): string { let originalFirst = iterableFirst(names); if (originalFirst === undefined) { return panic("Named type has no names"); } + if (names.size === 1) { return originalFirst; } @@ -43,7 +45,7 @@ function combineNames(names: ReadonlySet): string { const namesSet = setMap(names, s => splitIntoWords(s) .map(w => w.word.toLowerCase()) - .join("_") + .join("_"), ); const first = defined(iterableFirst(namesSet)); if (namesSet.size === 1) { @@ -69,22 +71,24 @@ function combineNames(names: ReadonlySet): string { } } } + const prefix = prefixLength > 2 ? first.slice(0, prefixLength) : ""; const suffix = suffixLength > 2 ? first.slice(first.length - suffixLength) : ""; const combined = prefix + suffix; if (combined.length > 2) { return combined; } + return first; } export const tooManyNamesThreshold = 1000; export abstract class TypeNames { - static makeWithDistance( + static makeWithDistance ( names: ReadonlySet, alternativeNames: ReadonlySet | undefined, - distance: number + distance: number, ): TypeNames { if (names.size >= tooManyNamesThreshold) { return new TooManyTypeNames(distance); @@ -97,41 +101,41 @@ export abstract class TypeNames { return new RegularTypeNames(names, alternativeNames, distance); } - static make( + static make ( names: ReadonlySet, alternativeNames: ReadonlySet | undefined, - areInferred: boolean + areInferred: boolean, ): TypeNames { return TypeNames.makeWithDistance(names, alternativeNames, areInferred ? 1 : 0); } - constructor(readonly distance: number) {} + constructor (readonly distance: number) {} - get areInferred(): boolean { + get areInferred (): boolean { return this.distance > 0; } - abstract get names(): ReadonlySet; - abstract get combinedName(): string; - abstract get proposedNames(): ReadonlySet; + abstract get names (): ReadonlySet; + abstract get combinedName (): string; + abstract get proposedNames (): ReadonlySet; - abstract add(namesArray: TypeNames[], startIndex?: number): TypeNames; - abstract clearInferred(): TypeNames; - abstract makeInferred(): TypeNames; - abstract singularize(): TypeNames; - abstract toString(): string; + abstract add (namesArray: TypeNames[], startIndex?: number): TypeNames; + abstract clearInferred (): TypeNames; + abstract makeInferred (): TypeNames; + abstract singularize (): TypeNames; + abstract toString (): string; } export class RegularTypeNames extends TypeNames { - constructor( + constructor ( readonly names: ReadonlySet, private readonly _alternativeNames: ReadonlySet | undefined, - distance: number + distance: number, ) { super(distance); } - add(namesArray: TypeNames[], startIndex = 0): TypeNames { + add (namesArray: TypeNames[], startIndex = 0): TypeNames { let newNames = new Set(this.names); let newDistance = this.distance; let newAlternativeNames = definedMap(this._alternativeNames, s => new Set(s)); @@ -143,6 +147,7 @@ export class RegularTypeNames extends TypeNames { if (newAlternativeNames === undefined) { newAlternativeNames = new Set(); } + setUnionInto(newAlternativeNames, other._alternativeNames); } @@ -165,45 +170,48 @@ export class RegularTypeNames extends TypeNames { setUnionInto(newNames, other.names); } } + return TypeNames.makeWithDistance(newNames, newAlternativeNames, newDistance); } - clearInferred(): TypeNames { + clearInferred (): TypeNames { const newNames = this.areInferred ? new Set() : this.names; return TypeNames.makeWithDistance(newNames, new Set(), this.distance); } - get combinedName(): string { + get combinedName (): string { return combineNames(this.names); } - get proposedNames(): ReadonlySet { + get proposedNames (): ReadonlySet { const set = new Set([this.combinedName]); if (this._alternativeNames === undefined) { return set; } + setUnionInto(set, this._alternativeNames); return set; } - makeInferred(): TypeNames { + makeInferred (): TypeNames { return TypeNames.makeWithDistance(this.names, this._alternativeNames, this.distance + 1); } - singularize(): TypeNames { + singularize (): TypeNames { return TypeNames.makeWithDistance( setMap(this.names, pluralize.singular), definedMap(this._alternativeNames, an => setMap(an, pluralize.singular)), - this.distance + 1 + this.distance + 1, ); } - toString(): string { + toString (): string { const inferred = this.areInferred ? `distance ${this.distance}` : "given"; const names = `${inferred} ${Array.from(this.names).join(",")}`; if (this._alternativeNames === undefined) { return names; } + return `${names} (${Array.from(this._alternativeNames).join(",")})`; } } @@ -211,24 +219,25 @@ export class RegularTypeNames extends TypeNames { export class TooManyTypeNames extends TypeNames { readonly names: ReadonlySet; - constructor(distance: number, name?: string) { + constructor (distance: number, name?: string) { super(distance); if (name === undefined) { name = makeRandomName(); } + this.names = new Set([name]); } - get combinedName(): string { + get combinedName (): string { return defined(iterableFirst(this.names)); } - get proposedNames(): ReadonlySet { + get proposedNames (): ReadonlySet { return this.names; } - add(namesArray: TypeNames[], startIndex = 0): TypeNames { + add (namesArray: TypeNames[], startIndex = 0): TypeNames { if (!this.areInferred) return this; for (let i = startIndex; i < namesArray.length; i++) { @@ -241,72 +250,74 @@ export class TooManyTypeNames extends TypeNames { return this; } - clearInferred(): TypeNames { + clearInferred (): TypeNames { if (!this.areInferred) { return this; } + return TypeNames.makeWithDistance(new Set(), new Set(), this.distance); } - makeInferred(): TypeNames { + makeInferred (): TypeNames { return new TooManyTypeNames(this.distance + 1, iterableFirst(this.names)); } - singularize(): TypeNames { + singularize (): TypeNames { return this; } - toString(): string { + toString (): string { return `too many ${this.combinedName}`; } } class TypeNamesTypeAttributeKind extends TypeAttributeKind { - constructor() { + constructor () { super("names"); } - combine(namesArray: TypeNames[]): TypeNames { + combine (namesArray: TypeNames[]): TypeNames { assert(namesArray.length > 0, "Can't combine zero type names"); return namesArray[0].add(namesArray, 1); } - makeInferred(tn: TypeNames): TypeNames { + makeInferred (tn: TypeNames): TypeNames { return tn.makeInferred(); } - increaseDistance(tn: TypeNames): TypeNames { + increaseDistance (tn: TypeNames): TypeNames { return tn.makeInferred(); } - stringify(tn: TypeNames): string { + stringify (tn: TypeNames): string { return tn.toString(); } } export const namesTypeAttributeKind: TypeAttributeKind = new TypeNamesTypeAttributeKind(); -export function modifyTypeNames( +export function modifyTypeNames ( attributes: TypeAttributes, - modifier: (tn: TypeNames | undefined) => TypeNames | undefined + modifier: (tn: TypeNames | undefined) => TypeNames | undefined, ): TypeAttributes { return namesTypeAttributeKind.modifyInAttributes(attributes, modifier); } -export function singularizeTypeNames(attributes: TypeAttributes): TypeAttributes { +export function singularizeTypeNames (attributes: TypeAttributes): TypeAttributes { return modifyTypeNames(attributes, maybeNames => { if (maybeNames === undefined) return undefined; return maybeNames.singularize(); }); } -export function makeNamesTypeAttributes(nameOrNames: NameOrNames, areNamesInferred?: boolean): TypeAttributes { +export function makeNamesTypeAttributes (nameOrNames: NameOrNames, areNamesInferred?: boolean): TypeAttributes { let typeNames: TypeNames; if (typeof nameOrNames === "string") { typeNames = TypeNames.make(new Set([nameOrNames]), new Set(), defined(areNamesInferred)); } else { typeNames = nameOrNames as TypeNames; } + return namesTypeAttributeKind.makeAttributes(typeNames); } diff --git a/packages/quicktype-core/src/attributes/URIAttributes.ts b/packages/quicktype-core/src/attributes/URIAttributes.ts index 1f779708b..3213a389c 100644 --- a/packages/quicktype-core/src/attributes/URIAttributes.ts +++ b/packages/quicktype-core/src/attributes/URIAttributes.ts @@ -1,11 +1,12 @@ import URI from "urijs"; -import { TypeAttributeKind, TypeAttributes, emptyTypeAttributes } from "./TypeAttributes"; +import { type TypeAttributes} from "./TypeAttributes"; +import { TypeAttributeKind, emptyTypeAttributes } from "./TypeAttributes"; import { setUnionManyInto } from "collection-utils"; -import { JSONSchemaType, JSONSchemaAttributes, Ref } from "../input/JSONSchemaInput"; -import { JSONSchema } from "../input/JSONSchemaStore"; +import { type JSONSchemaType, type JSONSchemaAttributes, type Ref } from "../input/JSONSchemaInput"; +import { type JSONSchema } from "../input/JSONSchemaStore"; import { checkArray, checkString } from "../support/Support"; -import { Type } from "../Type"; +import { type Type } from "../Type"; const protocolsSchemaProperty = "qt-uri-protocols"; const extensionsSchemaProperty = "qt-uri-extensions"; @@ -14,31 +15,32 @@ const extensionsSchemaProperty = "qt-uri-extensions"; type URIAttributes = [ReadonlySet, ReadonlySet]; class URITypeAttributeKind extends TypeAttributeKind { - constructor() { + constructor () { super("uriAttributes"); } - get inIdentity(): boolean { + get inIdentity (): boolean { return true; } - combine(attrs: URIAttributes[]): URIAttributes { + combine (attrs: URIAttributes[]): URIAttributes { const protocolSets = attrs.map(a => a[0]); const extensionSets = attrs.map(a => a[1]); return [setUnionManyInto(new Set(), protocolSets), setUnionManyInto(new Set(), extensionSets)]; } - makeInferred(_: URIAttributes): undefined { + makeInferred (_: URIAttributes): undefined { return undefined; } - addToSchema(schema: { [name: string]: unknown }, t: Type, attrs: URIAttributes): void { + addToSchema (schema: { [name: string]: unknown, }, t: Type, attrs: URIAttributes): void { if (t.kind !== "string" && t.kind !== "uri") return; const [protocols, extensions] = attrs; if (protocols.size > 0) { schema[protocolsSchemaProperty] = Array.from(protocols).sort(); } + if (extensions.size > 0) { schema[extensionsSchemaProperty] = Array.from(extensions).sort(); } @@ -49,13 +51,13 @@ export const uriTypeAttributeKind: TypeAttributeKind = new URITyp const extensionRegex = /^.+(\.[^./\\]+)$/; -function pathExtension(path: string): string | undefined { - const matches = path.match(extensionRegex); +function pathExtension (path: string): string | undefined { + const matches = extensionRegex.exec(path); if (matches === null) return undefined; return matches[1]; } -export function uriInferenceAttributesProducer(s: string): TypeAttributes { +export function uriInferenceAttributesProducer (s: string): TypeAttributes { try { const uri = URI(s); const extension = pathExtension(uri.path()); @@ -66,10 +68,10 @@ export function uriInferenceAttributesProducer(s: string): TypeAttributes { } } -export function uriSchemaAttributesProducer( +export function uriSchemaAttributesProducer ( schema: JSONSchema, _ref: Ref, - types: Set + types: Set, ): JSONSchemaAttributes | undefined { if (!(typeof schema === "object")) return undefined; if (!types.has("string")) return undefined; diff --git a/packages/quicktype-core/src/index.ts b/packages/quicktype-core/src/index.ts index aa04f0857..a56413a31 100644 --- a/packages/quicktype-core/src/index.ts +++ b/packages/quicktype-core/src/index.ts @@ -1,6 +1,6 @@ export { - Options, - RendererOptions, + type Options, + type RendererOptions, getTargetLanguage, quicktypeMultiFile, quicktypeMultiFileSync, @@ -10,26 +10,26 @@ export { inferenceFlagNames, defaultInferenceFlags, inferenceFlagsObject, - InferenceFlags, - InferenceFlagName, - RunContext + type InferenceFlags, + type InferenceFlagName, + type RunContext, } from "./Run"; -export { CompressedJSON, Value } from "./input/CompressedJSON"; -export { Input, InputData, JSONInput, JSONSourceData, jsonInputForTargetLanguage } from "./input/Inputs"; -export { JSONSchemaInput, JSONSchemaSourceData } from "./input/JSONSchemaInput"; -export { Ref, JSONSchemaType, JSONSchemaAttributes } from "./input/JSONSchemaInput"; -export { RenderContext } from "./Renderer"; -export { Option, OptionDefinition, getOptionValues, OptionValues } from "./RendererOptions"; -export { TargetLanguage, MultiFileRenderResult } from "./TargetLanguage"; +export { CompressedJSON, type Value } from "./input/CompressedJSON"; +export { type Input, InputData, JSONInput, type JSONSourceData, jsonInputForTargetLanguage } from "./input/Inputs"; +export { JSONSchemaInput, type JSONSchemaSourceData } from "./input/JSONSchemaInput"; +export { Ref, type JSONSchemaType, type JSONSchemaAttributes } from "./input/JSONSchemaInput"; +export type { RenderContext } from "./Renderer"; +export { Option, type OptionDefinition, getOptionValues, type OptionValues } from "./RendererOptions"; +export { TargetLanguage, type MultiFileRenderResult } from "./TargetLanguage"; export { all as defaultTargetLanguages, languageNamed } from "./language/All"; export { - MultiWord, - Sourcelike, - SerializedRenderResult, - Annotation, + type MultiWord, + type Sourcelike, + type SerializedRenderResult, + type Annotation, modifySource, singleWord, - parenIfNeeded + parenIfNeeded, } from "./Source"; export { Name, funPrefixNamer, Namer } from "./Naming"; export { IssueAnnotationData } from "./Annotation"; @@ -41,7 +41,7 @@ export { parseJSON, checkStringMap, checkArray, - inflateBase64 + inflateBase64, } from "./support/Support"; export { splitIntoWords, @@ -50,7 +50,7 @@ export { firstUpperWordStyle, allUpperWordStyle, legalizeCharacters, - isLetterOrDigit + isLetterOrDigit, } from "./support/Strings"; export { train as trainMarkovChain } from "./MarkovChain"; export { QuickTypeError, messageError, messageAssert } from "./Messages"; @@ -63,19 +63,19 @@ export { EnumType, MapType, UnionType, - TypeKind, + type TypeKind, ObjectType, - TransformedStringTypeKind, - PrimitiveStringTypeKind + type TransformedStringTypeKind, + type PrimitiveStringTypeKind, } from "./Type"; export { getStream } from "./input/io/get-stream"; export { readableFromFileOrURL, readFromFileOrURL } from "./input/io/NodeIO"; export { FetchingJSONSchemaStore } from "./input/FetchingJSONSchemaStore"; -export { JSONSchemaStore, JSONSchema } from "./input/JSONSchemaStore"; +export { JSONSchemaStore, type JSONSchema } from "./input/JSONSchemaStore"; export { sourcesFromPostmanCollection } from "./input/PostmanCollection"; -export { TypeBuilder, StringTypeMapping } from "./TypeBuilder"; -export { TypeRef, derefTypeRef } from "./TypeGraph"; -export { TypeAttributeKind, TypeAttributes, emptyTypeAttributes } from "./attributes/TypeAttributes"; +export { TypeBuilder, type StringTypeMapping } from "./TypeBuilder"; +export { type TypeRef, derefTypeRef } from "./TypeGraph"; +export { TypeAttributeKind, type TypeAttributes, emptyTypeAttributes } from "./attributes/TypeAttributes"; export { TypeNames, makeNamesTypeAttributes, namesTypeAttributeKind } from "./attributes/TypeNames"; export { StringTypes } from "./attributes/StringTypes"; export { removeNullFromUnion, matchType, nullableFromUnion } from "./TypeUtils"; @@ -93,14 +93,14 @@ export { JavaScriptTargetLanguage, JavaScriptRenderer, javaScriptOptions } from export { JavaScriptPropTypesTargetLanguage, JavaScriptPropTypesRenderer, - javaScriptPropTypesOptions + javaScriptPropTypesOptions, } from "./language/JavaScriptPropTypes"; export { TypeScriptTargetLanguage, TypeScriptRenderer, FlowTargetLanguage, FlowRenderer, - tsFlowOptions + tsFlowOptions, } from "./language/TypeScriptFlow"; export { SwiftTargetLanguage, SwiftRenderer, swiftOptions } from "./language/Swift"; export { KotlinTargetLanguage, KotlinRenderer, kotlinOptions } from "./language/Kotlin"; diff --git a/packages/quicktype-core/src/input/CompressedJSON.ts b/packages/quicktype-core/src/input/CompressedJSON.ts index 2bdb2cc85..7832c0675 100644 --- a/packages/quicktype-core/src/input/CompressedJSON.ts +++ b/packages/quicktype-core/src/input/CompressedJSON.ts @@ -1,8 +1,9 @@ import { addHashCode, hashCodeInit, hashString } from "collection-utils"; import { defined, panic, assert } from "../support/Support"; -import { TransformedStringTypeKind, isPrimitiveStringTypeKind, transformedStringTypeTargetTypeKindsMap } from "../Type"; -import { DateTimeRecognizer } from "../DateTime"; +import { type TransformedStringTypeKind} from "../Type"; +import { isPrimitiveStringTypeKind, transformedStringTypeTargetTypeKindsMap } from "../Type"; +import { type DateTimeRecognizer } from "../DateTime"; import { inferTransformedStringTypeKindForString } from "../attributes/StringTypes"; export enum Tag { @@ -24,46 +25,50 @@ export type Value = number; const TAG_BITS = 4; const TAG_MASK = (1 << TAG_BITS) - 1; -export function makeValue(t: Tag, index: number): Value { - return t | (index << TAG_BITS); +export function makeValue (t: Tag, index: number): Value { + return t | index << TAG_BITS; } -function getIndex(v: Value, tag: Tag): number { +function getIndex (v: Value, tag: Tag): number { assert(valueTag(v) === tag, "Trying to get index for value with invalid tag"); return v >> TAG_BITS; } -export function valueTag(v: Value): Tag { +export function valueTag (v: Value): Tag { return v & TAG_MASK; } -type Context = { - currentObject: Value[] | undefined; +interface Context { currentArray: Value[] | undefined; currentKey: string | undefined; currentNumberIsDouble: boolean; -}; + currentObject: Value[] | undefined; +} export abstract class CompressedJSON { private _rootValue: Value | undefined; private _ctx: Context | undefined; + private _contextStack: Context[] = []; private _strings: string[] = []; - private _stringIndexes: { [str: string]: number } = {}; + + private _stringIndexes: { [str: string]: number, } = {}; + private _objects: Value[][] = []; + private _arrays: Value[][] = []; - constructor(readonly dateTimeRecognizer: DateTimeRecognizer, readonly handleRefs: boolean) {} + constructor (readonly dateTimeRecognizer: DateTimeRecognizer, readonly handleRefs: boolean) {} - abstract parse(input: T): Promise; + abstract parse (input: T): Promise; - parseSync(_input: T): Value { + parseSync (_input: T): Value { return panic("parseSync not implemented in CompressedJSON"); } - getStringForValue(v: Value): string { + getStringForValue (v: Value): string { const tag = valueTag(v); assert(tag === Tag.InternedString || tag === Tag.TransformedString); return this._strings[getIndex(v, tag)]; @@ -77,35 +82,37 @@ export abstract class CompressedJSON { return this._arrays[getIndex(v, Tag.Array)]; }; - getStringFormatTypeKind(v: Value): TransformedStringTypeKind { + getStringFormatTypeKind (v: Value): TransformedStringTypeKind { const kind = this._strings[getIndex(v, Tag.StringFormat)]; if (!isPrimitiveStringTypeKind(kind) || kind === "string") { return panic("Not a transformed string type kind"); } + return kind; } - protected get context(): Context { + protected get context (): Context { return defined(this._ctx); } - protected internString(s: string): number { + protected internString (s: string): number { if (Object.prototype.hasOwnProperty.call(this._stringIndexes, s)) { return this._stringIndexes[s]; } + const index = this._strings.length; this._strings.push(s); this._stringIndexes[s] = index; return index; } - protected makeString(s: string): Value { + protected makeString (s: string): Value { const value = makeValue(Tag.InternedString, this.internString(s)); assert(typeof value === "number", `Interned string value is not a number: ${value}`); return value; } - protected internObject(obj: Value[]): Value { + protected internObject (obj: Value[]): Value { const index = this._objects.length; this._objects.push(obj); return makeValue(Tag.Object, index); @@ -117,22 +124,23 @@ export abstract class CompressedJSON { return makeValue(Tag.Array, index); }; - protected get isExpectingRef(): boolean { + protected get isExpectingRef (): boolean { return this._ctx !== undefined && this._ctx.currentKey === "$ref"; } - protected commitValue(value: Value): void { + protected commitValue (value: Value): void { assert(typeof value === "number", `CompressedJSON value is not a number: ${value}`); if (this._ctx === undefined) { assert( this._rootValue === undefined, - "Committing value but nowhere to commit to - root value still there." + "Committing value but nowhere to commit to - root value still there.", ); this._rootValue = value; } else if (this._ctx.currentObject !== undefined) { if (this._ctx.currentKey === undefined) { return panic("Must have key and can't have string when committing"); } + this._ctx.currentObject.push(this.makeString(this._ctx.currentKey), value); this._ctx.currentKey = undefined; } else if (this._ctx.currentArray !== undefined) { @@ -142,20 +150,20 @@ export abstract class CompressedJSON { } } - protected commitNull(): void { + protected commitNull (): void { this.commitValue(makeValue(Tag.Null, 0)); } - protected commitBoolean(v: boolean): void { + protected commitBoolean (v: boolean): void { this.commitValue(makeValue(v ? Tag.True : Tag.False, 0)); } - protected commitNumber(isDouble: boolean): void { + protected commitNumber (isDouble: boolean): void { const numberTag = isDouble ? Tag.Double : Tag.Integer; this.commitValue(makeValue(numberTag, 0)); } - protected commitString(s: string): void { + protected commitString (s: string): void { let value: Value | undefined = undefined; if (this.handleRefs && this.isExpectingRef) { value = this.makeString(s); @@ -173,74 +181,79 @@ export abstract class CompressedJSON { value = makeValue(Tag.UninternedString, 0); } } + this.commitValue(value); } - protected finish(): Value { + protected finish (): Value { const value = this._rootValue; if (value === undefined) { return panic("Finished without root document"); } + assert(this._ctx === undefined && this._contextStack.length === 0, "Finished with contexts present"); this._rootValue = undefined; return value; } - protected pushContext(): void { + protected pushContext (): void { if (this._ctx !== undefined) { this._contextStack.push(this._ctx); } + this._ctx = { currentObject: undefined, currentArray: undefined, currentKey: undefined, - currentNumberIsDouble: false + currentNumberIsDouble: false, }; } - protected pushObjectContext(): void { + protected pushObjectContext (): void { this.pushContext(); defined(this._ctx).currentObject = []; } - protected setPropertyKey(key: string): void { + protected setPropertyKey (key: string): void { const ctx = this.context; ctx.currentKey = key; } - protected finishObject(): void { + protected finishObject (): void { const obj = this.context.currentObject; if (obj === undefined) { return panic("Object ended but not started"); } + this.popContext(); this.commitValue(this.internObject(obj)); } - protected pushArrayContext(): void { + protected pushArrayContext (): void { this.pushContext(); defined(this._ctx).currentArray = []; } - protected finishArray(): void { + protected finishArray (): void { const arr = this.context.currentArray; if (arr === undefined) { return panic("Array ended but not started"); } + this.popContext(); this.commitValue(this.internArray(arr)); } - protected popContext(): void { + protected popContext (): void { assert(this._ctx !== undefined, "Popping context when there isn't one"); this._ctx = this._contextStack.pop(); } - equals(other: any): boolean { + equals (other: any): boolean { return this === other; } - hashCode(): number { + hashCode (): number { let hashAccumulator = hashCodeInit; for (const s of this._strings) { hashAccumulator = addHashCode(hashAccumulator, hashString(s)); @@ -256,6 +269,7 @@ export abstract class CompressedJSON { hashAccumulator = addHashCode(hashAccumulator, v); } } + for (const o of this._arrays) { for (const v of o) { hashAccumulator = addHashCode(hashAccumulator, v); @@ -267,17 +281,17 @@ export abstract class CompressedJSON { } export class CompressedJSONFromString extends CompressedJSON { - async parse(input: string): Promise { + async parse (input: string): Promise { return this.parseSync(input); } - parseSync(input: string): Value { + parseSync (input: string): Value { const json = JSON.parse(input); this.process(json); return this.finish(); } - private process(json: unknown): void { + private process (json: unknown): void { if (json === null) { this.commitNull(); } else if (typeof json === "boolean") { @@ -293,6 +307,7 @@ export class CompressedJSONFromString extends CompressedJSON { for (const v of json) { this.process(v); } + this.finishArray(); } else if (typeof json === "object") { this.pushObjectContext(); @@ -300,6 +315,7 @@ export class CompressedJSONFromString extends CompressedJSON { this.setPropertyKey(key); this.process((json as any)[key]); } + this.finishObject(); } else { return panic("Invalid JSON object"); diff --git a/packages/quicktype-core/src/input/FetchingJSONSchemaStore.ts b/packages/quicktype-core/src/input/FetchingJSONSchemaStore.ts index 08c6e0526..113baf372 100644 --- a/packages/quicktype-core/src/input/FetchingJSONSchemaStore.ts +++ b/packages/quicktype-core/src/input/FetchingJSONSchemaStore.ts @@ -1,13 +1,14 @@ -import { JSONSchema, JSONSchemaStore } from "./JSONSchemaStore"; +import { type JSONSchema} from "./JSONSchemaStore"; +import { JSONSchemaStore } from "./JSONSchemaStore"; import { parseJSON } from ".."; import { readFromFileOrURL } from "./io/NodeIO"; export class FetchingJSONSchemaStore extends JSONSchemaStore { - constructor(private readonly _httpHeaders?: string[]) { + constructor (private readonly _httpHeaders?: string[]) { super(); } - async fetch(address: string): Promise { + async fetch (address: string): Promise { // console.log(`Fetching ${address}`); return parseJSON(await readFromFileOrURL(address, this._httpHeaders), "JSON Schema", address); } diff --git a/packages/quicktype-core/src/input/Inference.ts b/packages/quicktype-core/src/input/Inference.ts index 9fdcea588..272c15d61 100644 --- a/packages/quicktype-core/src/input/Inference.ts +++ b/packages/quicktype-core/src/input/Inference.ts @@ -1,18 +1,22 @@ -import { Value, Tag, valueTag, CompressedJSON } from "./CompressedJSON"; +import { type Value, type CompressedJSON } from "./CompressedJSON"; +import { Tag, valueTag } from "./CompressedJSON"; import { assertNever, defined, panic, assert } from "../support/Support"; -import { TypeBuilder } from "../TypeBuilder"; +import { type TypeBuilder } from "../TypeBuilder"; import { UnionBuilder, UnionAccumulator } from "../UnionBuilder"; import { - ClassProperty, + type ClassProperty} from "../Type"; +import { transformedStringTypeTargetTypeKindsMap, UnionType, ClassType, MapType, - ArrayType + ArrayType, } from "../Type"; -import { TypeAttributes, emptyTypeAttributes } from "../attributes/TypeAttributes"; +import { type TypeAttributes} from "../attributes/TypeAttributes"; +import { emptyTypeAttributes } from "../attributes/TypeAttributes"; import { StringTypes, inferTransformedStringTypeKindForString } from "../attributes/StringTypes"; -import { TypeRef, derefTypeRef } from "../TypeGraph"; +import { type TypeRef} from "../TypeGraph"; +import { derefTypeRef } from "../TypeGraph"; import { messageError } from "../Messages"; import { nullableFromUnion } from "../TypeUtils"; @@ -21,10 +25,11 @@ import { nullableFromUnion } from "../TypeUtils"; // but TypeScript doesn't support that. export type NestedValueArray = any; -function forEachArrayInNestedValueArray(va: NestedValueArray, f: (va: Value[]) => void): void { +function forEachArrayInNestedValueArray (va: NestedValueArray, f: (va: Value[]) => void): void { if (va.length === 0) { return; } + if (Array.isArray(va[0])) { for (const x of va) { forEachArrayInNestedValueArray(x, f); @@ -34,7 +39,7 @@ function forEachArrayInNestedValueArray(va: NestedValueArray, f: (va: Value[]) = } } -function forEachValueInNestedValueArray(va: NestedValueArray, f: (v: Value) => void): void { +function forEachValueInNestedValueArray (va: NestedValueArray, f: (v: Value) => void): void { forEachArrayInNestedValueArray(va, a => { for (const x of a) { f(x); @@ -43,51 +48,51 @@ function forEachValueInNestedValueArray(va: NestedValueArray, f: (v: Value) => v } class InferenceUnionBuilder extends UnionBuilder { - constructor( + constructor ( typeBuilder: TypeBuilder, private readonly _typeInference: TypeInference, - private readonly _fixed: boolean + private readonly _fixed: boolean, ) { super(typeBuilder); } - protected makeObject( + protected makeObject ( objects: NestedValueArray, typeAttributes: TypeAttributes, - forwardingRef: TypeRef | undefined + forwardingRef: TypeRef | undefined, ): TypeRef { return this._typeInference.inferClassType(typeAttributes, objects, this._fixed, forwardingRef); } - protected makeArray( + protected makeArray ( arrays: NestedValueArray, typeAttributes: TypeAttributes, - forwardingRef: TypeRef | undefined + forwardingRef: TypeRef | undefined, ): TypeRef { return this.typeBuilder.getArrayType( typeAttributes, - this._typeInference.inferType(emptyTypeAttributes, arrays, this._fixed, forwardingRef) + this._typeInference.inferType(emptyTypeAttributes, arrays, this._fixed, forwardingRef), ); } } -function canBeEnumCase(_s: string): boolean { +function canBeEnumCase (_s: string): boolean { return true; } export type Accumulator = UnionAccumulator; export class TypeInference { - private _refIntersections: [TypeRef, string[]][] | undefined; + private _refIntersections: Array<[TypeRef, string[]]> | undefined; - constructor( + constructor ( private readonly _cjson: CompressedJSON, private readonly _typeBuilder: TypeBuilder, private readonly _inferMaps: boolean, - private readonly _inferEnums: boolean + private readonly _inferEnums: boolean, ) {} - addValuesToAccumulator(valueArray: NestedValueArray, accumulator: Accumulator): void { + addValuesToAccumulator (valueArray: NestedValueArray, accumulator: Accumulator): void { forEachValueInNestedValueArray(valueArray, value => { const t = valueTag(value); switch (t) { @@ -115,6 +120,7 @@ export class TypeInference { } else { accumulator.addStringType("string", emptyTypeAttributes); } + break; case Tag.UninternedString: accumulator.addStringType("string", emptyTypeAttributes); @@ -130,43 +136,48 @@ export class TypeInference { accumulator.addStringType( "string", emptyTypeAttributes, - new StringTypes(new Map(), new Set([kind])) + new StringTypes(new Map(), new Set([kind])), ); break; } + case Tag.TransformedString: { const s = this._cjson.getStringForValue(value); const kind = inferTransformedStringTypeKindForString(s, this._cjson.dateTimeRecognizer); if (kind === undefined) { return panic("TransformedString does not have a kind"); } + const producer = defined(transformedStringTypeTargetTypeKindsMap.get(kind)).attributesProducer; if (producer === undefined) { return panic("TransformedString does not have attribute producer"); } + accumulator.addStringType("string", producer(s), new StringTypes(new Map(), new Set([kind]))); break; } + default: return assertNever(t); } }); } - inferType( + inferType ( typeAttributes: TypeAttributes, valueArray: NestedValueArray, fixed: boolean, - forwardingRef?: TypeRef + forwardingRef?: TypeRef, ): TypeRef { const accumulator = this.accumulatorForArray(valueArray); return this.makeTypeFromAccumulator(accumulator, typeAttributes, fixed, forwardingRef); } - private resolveRef(ref: string, topLevel: TypeRef): TypeRef { + private resolveRef (ref: string, topLevel: TypeRef): TypeRef { if (!ref.startsWith("#/")) { return messageError("InferenceJSONReferenceNotRooted", { reference: ref }); } + const parts = ref.split("/").slice(1); const graph = this._typeBuilder.typeGraph; let tref = topLevel; @@ -178,33 +189,39 @@ export class TypeInference { // FIXME: handle unions return messageError("InferenceJSONReferenceToUnion", { reference: ref }); } + t = nullable; } + if (t instanceof ClassType) { const cp = t.getProperties().get(part); if (cp === undefined) { return messageError("InferenceJSONReferenceWrongProperty", { reference: ref }); } + tref = cp.typeRef; } else if (t instanceof MapType) { tref = t.values.typeRef; } else if (t instanceof ArrayType) { - if (part.match("^[0-9]+$") === null) { + if (/^[0-9]+$/.exec(part) === null) { return messageError("InferenceJSONReferenceInvalidArrayIndex", { reference: ref }); } + tref = t.items.typeRef; } else { return messageError("InferenceJSONReferenceWrongProperty", { reference: ref }); } } + return tref; } - inferTopLevelType(typeAttributes: TypeAttributes, valueArray: NestedValueArray, fixed: boolean): TypeRef { + inferTopLevelType (typeAttributes: TypeAttributes, valueArray: NestedValueArray, fixed: boolean): TypeRef { assert(this._refIntersections === undefined, "Didn't reset ref intersections - nested invocations?"); if (this._cjson.handleRefs) { this._refIntersections = []; } + const topLevel = this.inferType(typeAttributes, valueArray, fixed); if (this._cjson.handleRefs) { for (const [tref, refs] of defined(this._refIntersections)) { @@ -214,33 +231,34 @@ export class TypeInference { this._refIntersections = undefined; } + return topLevel; } - accumulatorForArray(valueArray: NestedValueArray): Accumulator { + accumulatorForArray (valueArray: NestedValueArray): Accumulator { const accumulator = new UnionAccumulator(true); this.addValuesToAccumulator(valueArray, accumulator); return accumulator; } - makeTypeFromAccumulator( + makeTypeFromAccumulator ( accumulator: Accumulator, typeAttributes: TypeAttributes, fixed: boolean, - forwardingRef?: TypeRef + forwardingRef?: TypeRef, ): TypeRef { const unionBuilder = new InferenceUnionBuilder(this._typeBuilder, this, fixed); return unionBuilder.buildUnion(accumulator, false, typeAttributes, forwardingRef); } - inferClassType( + inferClassType ( typeAttributes: TypeAttributes, objects: NestedValueArray, fixed: boolean, - forwardingRef?: TypeRef + forwardingRef?: TypeRef, ): TypeRef { const propertyNames: string[] = []; - const propertyValues: { [name: string]: Value[] } = {}; + const propertyValues: { [name: string]: Value[], } = {}; forEachArrayInNestedValueArray(objects, arr => { for (let i = 0; i < arr.length; i += 2) { @@ -250,12 +268,13 @@ export class TypeInference { propertyNames.push(key); propertyValues[key] = []; } + propertyValues[key].push(value); } }); if (this._cjson.handleRefs && propertyNames.length === 1 && propertyNames[0] === "$ref") { - const values = propertyValues["$ref"]; + const values = propertyValues.$ref; if (values.every(v => valueTag(v) === Tag.InternedString)) { const allRefs = values.map(v => this._cjson.getStringForValue(v)); // FIXME: Add is-ref attribute @@ -270,6 +289,7 @@ export class TypeInference { for (const key of propertyNames) { this.addValuesToAccumulator(propertyValues[key], accumulator); } + const values = this.makeTypeFromAccumulator(accumulator, emptyTypeAttributes, fixed); return this._typeBuilder.getMapType(typeAttributes, values, forwardingRef); } diff --git a/packages/quicktype-core/src/input/Inputs.ts b/packages/quicktype-core/src/input/Inputs.ts index 9ff8905fa..4d9ebc1de 100644 --- a/packages/quicktype-core/src/input/Inputs.ts +++ b/packages/quicktype-core/src/input/Inputs.ts @@ -1,85 +1,92 @@ import { iterableFirst, iterableFind, iterableSome, setFilterMap, withDefault, arrayMapSync } from "collection-utils"; -import { Value, CompressedJSON, CompressedJSONFromString } from "./CompressedJSON"; +import { type Value, type CompressedJSON} from "./CompressedJSON"; +import { CompressedJSONFromString } from "./CompressedJSON"; import { panic, errorMessage, defined } from "../support/Support"; import { messageError } from "../Messages"; -import { TypeBuilder } from "../TypeBuilder"; +import { type TypeBuilder } from "../TypeBuilder"; import { makeNamesTypeAttributes } from "../attributes/TypeNames"; import { descriptionTypeAttributeKind } from "../attributes/Description"; import { TypeInference } from "./Inference"; -import { TargetLanguage } from "../TargetLanguage"; -import { RunContext } from "../Run"; +import { type TargetLanguage } from "../TargetLanguage"; +import { type RunContext } from "../Run"; import { languageNamed } from "../language/All"; export interface Input { - readonly kind: string; - readonly needIR: boolean; - readonly needSchemaProcessing: boolean; - - addSource(source: T): Promise; - addSourceSync(source: T): void; - - singleStringSchemaSource(): string | undefined; - - addTypes( + addSource: (source: T) => Promise; + addSourceSync: (source: T) => void; + addTypes: ( ctx: RunContext, typeBuilder: TypeBuilder, inferMaps: boolean, inferEnums: boolean, fixedTopLevels: boolean - ): Promise; - addTypesSync( + ) => Promise; + + addTypesSync: ( ctx: RunContext, typeBuilder: TypeBuilder, inferMaps: boolean, inferEnums: boolean, fixedTopLevels: boolean - ): void; + ) => void; + readonly kind: string; + + readonly needIR: boolean; + + readonly needSchemaProcessing: boolean; + singleStringSchemaSource: () => string | undefined; } -type JSONTopLevel = { samples: Value[]; description: string | undefined }; +interface JSONTopLevel { + description: string | undefined; samples: Value[]; +} export interface JSONSourceData { + description?: string; name: string; samples: T[]; - description?: string; } -function messageParseError(name: string, description: string | undefined, e: unknown): never { +function messageParseError (name: string, description: string | undefined, e: unknown): never { return messageError("MiscJSONParseError", { description: withDefault(description, "input"), address: name, - message: errorMessage(e) + message: errorMessage(e), }); } export class JSONInput implements Input> { readonly kind: string = "json"; + readonly needIR: boolean = true; + readonly needSchemaProcessing: boolean = false; private readonly _topLevels: Map = new Map(); - constructor(private readonly _compressedJSON: CompressedJSON) {} + constructor (private readonly _compressedJSON: CompressedJSON) {} - private addSample(topLevelName: string, sample: Value): void { + private addSample (topLevelName: string, sample: Value): void { let topLevel = this._topLevels.get(topLevelName); if (topLevel === undefined) { topLevel = { samples: [], description: undefined }; this._topLevels.set(topLevelName, topLevel); } + topLevel.samples.push(sample); } - private setDescription(topLevelName: string, description: string): void { + private setDescription (topLevelName: string, description: string): void { let topLevel = this._topLevels.get(topLevelName); if (topLevel === undefined) { return panic("Trying to set description for a top-level that doesn't exist"); } + topLevel.description = description; } - private addSamples(name: string, values: Value[], description: string | undefined): void { + private addSamples (name: string, values: Value[], description: string | undefined): void { for (const value of values) { this.addSample(name, value); if (description !== undefined) { @@ -88,7 +95,7 @@ export class JSONInput implements Input> { } } - async addSource(source: JSONSourceData): Promise { + async addSource (source: JSONSourceData): Promise { const { name, samples, description } = source; try { const values = await arrayMapSync(samples, async s => await this._compressedJSON.parse(s)); @@ -98,7 +105,7 @@ export class JSONInput implements Input> { } } - addSourceSync(source: JSONSourceData): void { + addSourceSync (source: JSONSourceData): void { const { name, samples, description } = source; try { const values = samples.map(s => this._compressedJSON.parseSync(s)); @@ -108,26 +115,26 @@ export class JSONInput implements Input> { } } - singleStringSchemaSource(): undefined { + singleStringSchemaSource (): undefined { return undefined; } - async addTypes( + async addTypes ( ctx: RunContext, typeBuilder: TypeBuilder, inferMaps: boolean, inferEnums: boolean, - fixedTopLevels: boolean + fixedTopLevels: boolean, ): Promise { - return this.addTypesSync(ctx, typeBuilder, inferMaps, inferEnums, fixedTopLevels); + this.addTypesSync(ctx, typeBuilder, inferMaps, inferEnums, fixedTopLevels); } - addTypesSync( + addTypesSync ( _ctx: RunContext, typeBuilder: TypeBuilder, inferMaps: boolean, inferEnums: boolean, - fixedTopLevels: boolean + fixedTopLevels: boolean, ): void { const inference = new TypeInference(this._compressedJSON, typeBuilder, inferMaps, inferEnums); @@ -142,14 +149,15 @@ export class JSONInput implements Input> { } } -export function jsonInputForTargetLanguage( +export function jsonInputForTargetLanguage ( targetLanguage: string | TargetLanguage, languages?: TargetLanguage[], - handleJSONRefs = false + handleJSONRefs = false, ): JSONInput { if (typeof targetLanguage === "string") { targetLanguage = defined(languageNamed(targetLanguage, languages)); } + const compressedJSON = new CompressedJSONFromString(targetLanguage.dateTimeRecognizer, handleJSONRefs); return new JSONInput(compressedJSON); } @@ -168,6 +176,7 @@ export class InputData { input = makeInput(); this.addInput(input); } + return input; } @@ -181,43 +190,44 @@ export class InputData { input.addSourceSync(source); } - async addTypes( + async addTypes ( ctx: RunContext, typeBuilder: TypeBuilder, inferMaps: boolean, inferEnums: boolean, - fixedTopLevels: boolean + fixedTopLevels: boolean, ): Promise { for (const input of this._inputs) { await input.addTypes(ctx, typeBuilder, inferMaps, inferEnums, fixedTopLevels); } } - addTypesSync( + addTypesSync ( ctx: RunContext, typeBuilder: TypeBuilder, inferMaps: boolean, inferEnums: boolean, - fixedTopLevels: boolean + fixedTopLevels: boolean, ): void { for (const input of this._inputs) { input.addTypesSync(ctx, typeBuilder, inferMaps, inferEnums, fixedTopLevels); } } - get needIR(): boolean { + get needIR (): boolean { return iterableSome(this._inputs, i => i.needIR); } - get needSchemaProcessing(): boolean { + get needSchemaProcessing (): boolean { return iterableSome(this._inputs, i => i.needSchemaProcessing); } - singleStringSchemaSource(): string | undefined { + singleStringSchemaSource (): string | undefined { const schemaStrings = setFilterMap(this._inputs, i => i.singleStringSchemaSource()); if (schemaStrings.size > 1) { return panic("We have more than one input with a string schema source"); } + return iterableFirst(schemaStrings); } } diff --git a/packages/quicktype-core/src/input/JSONSchemaInput.ts b/packages/quicktype-core/src/input/JSONSchemaInput.ts index 8fc74e6dd..ae8f4b5fd 100644 --- a/packages/quicktype-core/src/input/JSONSchemaInput.ts +++ b/packages/quicktype-core/src/input/JSONSchemaInput.ts @@ -18,30 +18,34 @@ import { definedMap, addHashCode, iterableFirst, - hashString + hashString, } from "collection-utils"; import { - PrimitiveTypeKind, - TransformedStringTypeKind, + type PrimitiveTypeKind, + type TransformedStringTypeKind} from "../Type"; +import { transformedStringTypeTargetTypeKindsMap, - isNumberTypeKind + isNumberTypeKind, } from "../Type"; -import { panic, assertNever, StringMap, assert, defined, parseJSON } from "../support/Support"; -import { TypeBuilder } from "../TypeBuilder"; +import { type StringMap} from "../support/Support"; +import { panic, assertNever, assert, defined, parseJSON } from "../support/Support"; +import { type TypeBuilder } from "../TypeBuilder"; import { TypeNames } from "../attributes/TypeNames"; import { makeNamesTypeAttributes, modifyTypeNames, singularizeTypeNames } from "../attributes/TypeNames"; import { - TypeAttributes, + type TypeAttributes} from "../attributes/TypeAttributes"; +import { makeTypeAttributesInferred, emptyTypeAttributes, - combineTypeAttributes + combineTypeAttributes, } from "../attributes/TypeAttributes"; -import { JSONSchema, JSONSchemaStore } from "./JSONSchemaStore"; +import { type JSONSchema} from "./JSONSchemaStore"; +import { JSONSchemaStore } from "./JSONSchemaStore"; import { messageAssert, messageError } from "../Messages"; import { StringTypes } from "../attributes/StringTypes"; -import { TypeRef } from "../TypeGraph"; +import { type TypeRef } from "../TypeGraph"; import { type RunContext } from "../Run"; import { type Input } from "./Inputs"; @@ -64,17 +68,17 @@ export enum PathElementKind { } export type PathElement = - | { kind: PathElementKind.Root } - | { kind: PathElementKind.KeyOrIndex; key: string } - | { kind: PathElementKind.Type; index: number } - | { kind: PathElementKind.Object }; + | { kind: PathElementKind.Root, } + | { key: string, kind: PathElementKind.KeyOrIndex, } + | { index: number, kind: PathElementKind.Type, } + | { kind: PathElementKind.Object, }; -function keyOrIndex(pe: PathElement): string | undefined { +function keyOrIndex (pe: PathElement): string | undefined { if (pe.kind !== PathElementKind.KeyOrIndex) return undefined; return pe.key; } -function pathElementEquals(a: PathElement, b: PathElement): boolean { +function pathElementEquals (a: PathElement, b: PathElement): boolean { if (a.kind !== b.kind) return false; switch (a.kind) { case PathElementKind.Type: @@ -86,35 +90,38 @@ function pathElementEquals(a: PathElement, b: PathElement): boolean { } } -function withRef(refOrLoc: Ref | (() => Ref) | Location): { ref: Ref }; -function withRef(refOrLoc: Ref | (() => Ref) | Location, props?: T): T & { ref: Ref }; -function withRef(refOrLoc: Ref | (() => Ref) | Location, props?: T): any { +function withRef (refOrLoc: Ref | (() => Ref) | Location): { ref: Ref, }; +function withRef (refOrLoc: Ref | (() => Ref) | Location, props?: T): T & { ref: Ref, }; +function withRef (refOrLoc: Ref | (() => Ref) | Location, props?: T): any { const ref = typeof refOrLoc === "function" ? refOrLoc() : refOrLoc instanceof Ref ? refOrLoc : refOrLoc.canonicalRef; return Object.assign({ ref }, props === undefined ? {} : props); } -function checkJSONSchemaObject(x: any, refOrLoc: Ref | (() => Ref)): StringMap { +function checkJSONSchemaObject (x: any, refOrLoc: Ref | (() => Ref)): StringMap { if (Array.isArray(x)) { return messageError("SchemaArrayIsInvalidSchema", withRef(refOrLoc)); } + if (x === null) { return messageError("SchemaNullIsInvalidSchema", withRef(refOrLoc)); } + if (typeof x !== "object") { return messageError("SchemaInvalidJSONSchemaType", withRef(refOrLoc, { type: typeof x })); } + return x; } -function checkJSONSchema(x: any, refOrLoc: Ref | (() => Ref)): JSONSchema { +function checkJSONSchema (x: any, refOrLoc: Ref | (() => Ref)): JSONSchema { if (typeof x === "boolean") return x; return checkJSONSchemaObject(x, refOrLoc); } const numberRegexp = new RegExp("^[0-9]+$"); -function normalizeURI(uri: string | URI): URI { +function normalizeURI (uri: string | URI): URI { // FIXME: This is overly complicated and a bit shady. The problem is // that `normalize` will URL-escape, with the result that if we want to // open the URL as a file, escaped character will thwart us. I think the @@ -123,16 +130,17 @@ function normalizeURI(uri: string | URI): URI { if (typeof uri === "string") { uri = new URI(uri); } + return new URI(URI.decode(uri.clone().normalize().toString())); } export class Ref { - static root(address: string | undefined): Ref { + static root (address: string | undefined): Ref { const uri = definedMap(address, a => new URI(a)); return new Ref(uri, []); } - private static parsePath(path: string): ReadonlyArray { + private static parsePath (path: string): readonly PathElement[] { const elements: PathElement[] = []; if (path.startsWith("/")) { @@ -146,10 +154,11 @@ export class Ref { elements.push({ kind: PathElementKind.KeyOrIndex, key: parts[i] }); } } + return elements; } - static parseURI(uri: URI, destroyURI = false): Ref { + static parseURI (uri: URI, destroyURI = false): Ref { if (!destroyURI) { uri = uri.clone(); } @@ -159,19 +168,20 @@ export class Ref { if ((uri.host() !== "" || uri.filename() !== "") && path === "") { path = "/"; } + const elements = Ref.parsePath(path); return new Ref(uri, elements); } - static parse(ref: string): Ref { + static parse (ref: string): Ref { return Ref.parseURI(new URI(ref), true); } public addressURI: URI | undefined; - constructor( + constructor ( addressURI: URI | undefined, - readonly path: ReadonlyArray + readonly path: readonly PathElement[], ) { if (addressURI !== undefined) { assert(addressURI.fragment() === "", `Ref URI with fragment is not allowed: ${addressURI.toString()}`); @@ -181,49 +191,51 @@ export class Ref { } } - get hasAddress(): boolean { + get hasAddress (): boolean { return this.addressURI !== undefined; } - get address(): string { + get address (): string { return defined(this.addressURI).toString(); } - get isRoot(): boolean { + get isRoot (): boolean { return this.path.length === 1 && this.path[0].kind === PathElementKind.Root; } - private pushElement(pe: PathElement): Ref { + private pushElement (pe: PathElement): Ref { const newPath = Array.from(this.path); newPath.push(pe); return new Ref(this.addressURI, newPath); } - push(...keys: string[]): Ref { + push (...keys: string[]): Ref { let ref: Ref = this; for (const key of keys) { ref = ref.pushElement({ kind: PathElementKind.KeyOrIndex, key }); } + return ref; } - pushObject(): Ref { + pushObject (): Ref { return this.pushElement({ kind: PathElementKind.Object }); } - pushType(index: number): Ref { + pushType (index: number): Ref { return this.pushElement({ kind: PathElementKind.Type, index }); } - resolveAgainst(base: Ref | undefined): Ref { + resolveAgainst (base: Ref | undefined): Ref { let addressURI = this.addressURI; - if (base !== undefined && base.addressURI !== undefined) { + if (base?.addressURI !== undefined) { addressURI = addressURI === undefined ? base.addressURI : addressURI.absoluteTo(base.addressURI); } + return new Ref(addressURI, this.path); } - get name(): string { + get name (): string { const path = Array.from(this.path); for (;;) { @@ -234,9 +246,11 @@ export class Ref { if (name.length > suffix.length + 1) { name = name.slice(0, name.length - suffix.length - 1); } + if (name === "") { return "Something"; } + return name; } @@ -245,6 +259,7 @@ export class Ref { if (numberRegexp.test(e.key)) { return e.key; } + break; case PathElementKind.Type: case PathElementKind.Object: @@ -255,15 +270,15 @@ export class Ref { } } - get definitionName(): string | undefined { + get definitionName (): string | undefined { const pe = arrayGetFromEnd(this.path, 2); if (pe === undefined) return undefined; if (keyOrIndex(pe) === "definitions") return keyOrIndex(defined(arrayLast(this.path))); return undefined; } - toString(): string { - function elementToString(e: PathElement): string { + toString (): string { + function elementToString (e: PathElement): string { switch (e.kind) { case PathElementKind.Root: return ""; @@ -277,16 +292,18 @@ export class Ref { return assertNever(e); } } + const address = this.addressURI === undefined ? "" : this.addressURI.toString(); return address + "#" + this.path.map(elementToString).join("/"); } - private lookup(local: any, path: ReadonlyArray, root: JSONSchema): JSONSchema { + private lookup (local: any, path: readonly PathElement[], root: JSONSchema): JSONSchema { const refMaker = () => new Ref(this.addressURI, path); const first = path[0]; if (first === undefined) { return checkJSONSchema(local, refMaker); } + const rest = path.slice(1); switch (first.kind) { case PathElementKind.Root: @@ -297,46 +314,52 @@ export class Ref { if (!/^\d+$/.test(key)) { return messageError("SchemaCannotIndexArrayWithNonNumber", withRef(refMaker, { actual: key })); } + const index = parseInt(first.key, 10); if (index >= local.length) { return messageError("SchemaIndexNotInArray", withRef(refMaker, { index })); } + return this.lookup(local[index], rest, root); } else { if (!hasOwnProperty(local, key)) { return messageError("SchemaKeyNotInObject", withRef(refMaker, { key })); } + return this.lookup(checkJSONSchemaObject(local, refMaker)[first.key], rest, root); } + case PathElementKind.Type: - return panic('Cannot look up path that indexes "type"'); + return panic("Cannot look up path that indexes \"type\""); case PathElementKind.Object: - return panic('Cannot look up path that indexes "object"'); + return panic("Cannot look up path that indexes \"object\""); default: return assertNever(first); } } - lookupRef(root: JSONSchema): JSONSchema { + lookupRef (root: JSONSchema): JSONSchema { return this.lookup(root, this.path, root); } - equals(other: any): boolean { + equals (other: any): boolean { if (!(other instanceof Ref)) return false; if (this.addressURI !== undefined && other.addressURI !== undefined) { if (!this.addressURI.equals(other.addressURI)) return false; } else { - if ((this.addressURI === undefined) !== (other.addressURI === undefined)) return false; + if (this.addressURI === undefined !== (other.addressURI === undefined)) return false; } + const l = this.path.length; if (l !== other.path.length) return false; for (let i = 0; i < l; i++) { if (!pathElementEquals(this.path[i], other.path[i])) return false; } + return true; } - hashCode(): number { + hashCode (): number { let acc = hashCodeOf(definedMap(this.addressURI, u => u.toString())); for (const pe of this.path) { acc = addHashCode(acc, pe.kind); @@ -351,84 +374,94 @@ export class Ref { break; } } + return acc; } } class Location { public readonly canonicalRef: Ref; + public readonly virtualRef: Ref; - constructor( + constructor ( canonicalRef: Ref, virtualRef?: Ref, - readonly haveID: boolean = false + readonly haveID: boolean = false, ) { this.canonicalRef = canonicalRef; this.virtualRef = virtualRef !== undefined ? virtualRef : canonicalRef; } - updateWithID(id: any) { + updateWithID (id: any) { if (typeof id !== "string") return this; const parsed = Ref.parse(id); const virtual = this.haveID ? parsed.resolveAgainst(this.virtualRef) : parsed; if (!this.haveID) { messageAssert(virtual.hasAddress, "SchemaIDMustHaveAddress", withRef(this, { id })); } + return new Location(this.canonicalRef, virtual, true); } - push(...keys: string[]): Location { + push (...keys: string[]): Location { return new Location(this.canonicalRef.push(...keys), this.virtualRef.push(...keys), this.haveID); } - pushObject(): Location { + pushObject (): Location { return new Location(this.canonicalRef.pushObject(), this.virtualRef.pushObject(), this.haveID); } - pushType(index: number): Location { + pushType (index: number): Location { return new Location(this.canonicalRef.pushType(index), this.virtualRef.pushType(index), this.haveID); } - toString(): string { + toString (): string { return `${this.virtualRef.toString()} (${this.canonicalRef.toString()})`; } } class Canonizer { private readonly _map = new EqualityMap(); + private readonly _schemaAddressesAdded = new Set(); - constructor(private readonly _ctx: RunContext) {} + constructor (private readonly _ctx: RunContext) {} - private addIDs(schema: any, loc: Location) { + private addIDs (schema: any, loc: Location) { if (schema === null) return; if (Array.isArray(schema)) { for (let i = 0; i < schema.length; i++) { this.addIDs(schema[i], loc.push(i.toString())); } + return; } + if (typeof schema !== "object") { return; } + const locWithoutID = loc; - const maybeID = schema["$id"]; + const maybeID = schema.$id; if (typeof maybeID === "string") { loc = loc.updateWithID(maybeID); } + if (loc.haveID) { if (this._ctx.debugPrintSchemaResolving) { console.log(`adding mapping ${loc.toString()}`); } + this._map.set(loc.virtualRef, locWithoutID); } + for (const property of Object.getOwnPropertyNames(schema)) { this.addIDs(schema[property], loc.push(property)); } } - addSchema(schema: any, address: string): boolean { + addSchema (schema: any, address: string): boolean { if (this._schemaAddressesAdded.has(address)) return false; this.addIDs(schema, new Location(Ref.root(address), Ref.root(undefined))); @@ -437,19 +470,20 @@ class Canonizer { } // Returns: Canonical ref - canonize(base: Location, ref: Ref): Location { + canonize (base: Location, ref: Ref): Location { const virtual = ref.resolveAgainst(base.virtualRef); const loc = this._map.get(virtual); if (loc !== undefined) { return loc; } + const canonicalRef = virtual.addressURI === undefined ? new Ref(base.canonicalRef.addressURI, virtual.path) : virtual; return new Location(canonicalRef, new Ref(undefined, virtual.path)); } } -function checkTypeList(typeOrTypes: any, loc: Location): ReadonlySet { +function checkTypeList (typeOrTypes: any, loc: Location): ReadonlySet { let set: Set; if (typeof typeOrTypes === "string") { set = new Set([typeOrTypes]); @@ -459,30 +493,36 @@ function checkTypeList(typeOrTypes: any, loc: Location): ReadonlySet { if (typeof t !== "string") { return messageError("SchemaTypeElementMustBeString", withRef(loc, { element: t })); } + arr.push(t); } + set = new Set(arr); } else { return messageError("SchemaTypeMustBeStringOrStringArray", withRef(loc, { actual: typeOrTypes })); } + messageAssert(set.size > 0, "SchemaNoTypeSpecified", withRef(loc)); const validTypes = ["null", "boolean", "object", "array", "number", "string", "integer"]; - const maybeInvalid = iterableFind(set, s => validTypes.indexOf(s) < 0); + const maybeInvalid = iterableFind(set, s => !validTypes.includes(s)); if (maybeInvalid !== undefined) { return messageError("SchemaInvalidType", withRef(loc, { type: maybeInvalid })); } + return set; } -function checkRequiredArray(arr: any, loc: Location): string[] { +function checkRequiredArray (arr: any, loc: Location): string[] { if (!Array.isArray(arr)) { return messageError("SchemaRequiredMustBeStringOrStringArray", withRef(loc, { actual: arr })); } + for (const e of arr) { if (typeof e !== "string") { return messageError("SchemaRequiredElementMustBeString", withRef(loc, { element: e })); } } + return arr; } @@ -493,20 +533,20 @@ export const schemaTypeDict = { integer: true, number: true, array: true, - object: true + object: true, }; export type JSONSchemaType = keyof typeof schemaTypeDict; const schemaTypes = Object.getOwnPropertyNames(schemaTypeDict) as JSONSchemaType[]; -export type JSONSchemaAttributes = { - forType?: TypeAttributes; - forUnion?: TypeAttributes; - forObject?: TypeAttributes; +export interface JSONSchemaAttributes { + forCases?: TypeAttributes[]; forNumber?: TypeAttributes; + forObject?: TypeAttributes; forString?: TypeAttributes; - forCases?: TypeAttributes[]; -}; + forType?: TypeAttributes; + forUnion?: TypeAttributes; +} export type JSONSchemaAttributeProducer = ( schema: JSONSchema, canonicalRef: Ref, @@ -514,16 +554,16 @@ export type JSONSchemaAttributeProducer = ( unionCases: JSONSchema[] | undefined ) => JSONSchemaAttributes | undefined; -function typeKindForJSONSchemaFormat(format: string): TransformedStringTypeKind | undefined { +function typeKindForJSONSchemaFormat (format: string): TransformedStringTypeKind | undefined { const target = iterableFind( transformedStringTypeTargetTypeKindsMap, - ([_, { jsonSchema }]) => jsonSchema === format + ([_, { jsonSchema }]) => jsonSchema === format, ); if (target === undefined) return undefined; return target[0] as TransformedStringTypeKind; } -function schemaFetchError(base: Location | undefined, address: string): never { +function schemaFetchError (base: Location | undefined, address: string): never { if (base === undefined) { return messageError("SchemaFetchErrorTopLevel", { address }); } else { @@ -532,16 +572,16 @@ function schemaFetchError(base: Location | undefined, address: string): never { } class Resolver { - constructor( + constructor ( private readonly _ctx: RunContext, private readonly _store: JSONSchemaStore, - private readonly _canonizer: Canonizer + private readonly _canonizer: Canonizer, ) {} - private async tryResolveVirtualRef( + private async tryResolveVirtualRef ( fetchBase: Location, lookupBase: Location, - virtualRef: Ref + virtualRef: Ref, ): Promise<[JSONSchema | undefined, Location]> { let didAdd = false; // If we are resolving into a schema file that we haven't seen yet then @@ -571,15 +611,16 @@ class Resolver { lookupLoc = new Location( new Ref(loc.canonicalRef.addressURI, lookupLoc.canonicalRef.path), lookupLoc.virtualRef, - lookupLoc.haveID + lookupLoc.haveID, ); } + return [lookupLoc.canonicalRef.lookupRef(schema), lookupLoc]; } } } - async resolveVirtualRef(base: Location, virtualRef: Ref): Promise<[JSONSchema, Location]> { + async resolveVirtualRef (base: Location, virtualRef: Ref): Promise<[JSONSchema, Location]> { if (this._ctx.debugPrintSchemaResolving) { console.log(`resolving ${virtualRef.toString()} relative to ${base.toString()}`); } @@ -592,13 +633,14 @@ class Resolver { if (this._ctx.debugPrintSchemaResolving) { console.log(`resolved to ${result[1].toString()}`); } + return [schema, result[1]]; } const altBase = new Location( base.canonicalRef, new Ref(base.canonicalRef.addressURI, base.virtualRef.path), - base.haveID + base.haveID, ); result = await this.tryResolveVirtualRef(altBase, base, virtualRef); schema = result[0]; @@ -606,40 +648,42 @@ class Resolver { if (this._ctx.debugPrintSchemaResolving) { console.log(`resolved to ${result[1].toString()}`); } + return [schema, result[1]]; } return schemaFetchError(base, virtualRef.address); } - async resolveTopLevelRef(ref: Ref): Promise<[JSONSchema, Location]> { + async resolveTopLevelRef (ref: Ref): Promise<[JSONSchema, Location]> { return await this.resolveVirtualRef(new Location(new Ref(ref.addressURI, [])), new Ref(undefined, ref.path)); } } -async function addTypesInSchema( +async function addTypesInSchema ( resolver: Resolver, typeBuilder: TypeBuilder, references: ReadonlyMap, - attributeProducers: JSONSchemaAttributeProducer[] + attributeProducers: JSONSchemaAttributeProducer[], ): Promise { let typeForCanonicalRef = new EqualityMap(); - function setTypeForLocation(loc: Location, t: TypeRef): void { + function setTypeForLocation (loc: Location, t: TypeRef): void { const maybeRef = typeForCanonicalRef.get(loc.canonicalRef); if (maybeRef !== undefined) { assert(maybeRef === t, "Trying to set path again to different type"); } + typeForCanonicalRef.set(loc.canonicalRef, t); } - async function makeObject( + async function makeObject ( loc: Location, attributes: TypeAttributes, properties: StringMap, requiredArray: string[], additionalProperties: any, - sortKey: (k: string) => number | string = (k: string) => k.toLowerCase() + sortKey: (k: string) => number | string = (k: string) => k.toLowerCase(), ): Promise { const required = new Set(requiredArray); const propertiesMap = mapSortBy(mapFromObject(properties), (_, k) => sortKey(k)); @@ -648,7 +692,7 @@ async function addTypesInSchema( const t = await toType( checkJSONSchema(propSchema, propLoc.canonicalRef), propLoc, - makeNamesTypeAttributes(propName, true) + makeNamesTypeAttributes(propName, true), ); const isOptional = !required.has(propName); return typeBuilder.makeClassProperty(t, isOptional); @@ -663,9 +707,10 @@ async function addTypesInSchema( additionalPropertiesType = await toType( checkJSONSchema(additionalProperties, additionalLoc.canonicalRef), additionalLoc, - singularizeTypeNames(attributes) + singularizeTypeNames(attributes), ); } + const additionalRequired = setSubtract(required, props.keys()); if (additionalRequired.size > 0) { const t = additionalPropertiesType; @@ -674,22 +719,24 @@ async function addTypesInSchema( } const additionalProps = mapFromIterable(additionalRequired, _name => - typeBuilder.makeClassProperty(t, false) + typeBuilder.makeClassProperty(t, false), ); mapMergeInto(props, additionalProps); } + return typeBuilder.getUniqueObjectType(attributes, props, additionalPropertiesType); } - async function convertToType(schema: StringMap, loc: Location, typeAttributes: TypeAttributes): Promise { + async function convertToType (schema: StringMap, loc: Location, typeAttributes: TypeAttributes): Promise { const enumArray = Array.isArray(schema.enum) ? schema.enum : undefined; const isConst = schema.const !== undefined; const typeSet = definedMap(schema.type, t => checkTypeList(t, loc)); - function isTypeIncluded(name: JSONSchemaType): boolean { + function isTypeIncluded (name: JSONSchemaType): boolean { if (typeSet !== undefined && !typeSet.has(name)) { return false; } + if (enumArray !== undefined) { let predicate: (x: any) => boolean; switch (name) { @@ -706,18 +753,20 @@ async function addTypesInSchema( return enumArray.find(predicate) !== undefined; } + if (isConst) { return name === (schema.type ?? typeof schema.const); } + return true; } const includedTypes = setFilter(schemaTypes, isTypeIncluded); let producedAttributesForNoCases: JSONSchemaAttributes[] | undefined = undefined; - function forEachProducedAttribute( + function forEachProducedAttribute ( cases: JSONSchema[] | undefined, - f: (attributes: JSONSchemaAttributes) => void + f: (attributes: JSONSchemaAttributes) => void, ): void { let attributes: JSONSchemaAttributes[]; if (cases === undefined && producedAttributesForNoCases !== undefined) { @@ -729,17 +778,19 @@ async function addTypesInSchema( if (newAttributes === undefined) continue; attributes.push(newAttributes); } + if (cases === undefined) { producedAttributesForNoCases = attributes; } } + for (const a of attributes) { f(a); } } - function combineProducedAttributes( - f: (attributes: JSONSchemaAttributes) => TypeAttributes | undefined + function combineProducedAttributes ( + f: (attributes: JSONSchemaAttributes) => TypeAttributes | undefined, ): TypeAttributes { let result = emptyTypeAttributes; forEachProducedAttribute(undefined, attr => { @@ -750,7 +801,7 @@ async function addTypesInSchema( return result; } - function makeAttributes(attributes: TypeAttributes): TypeAttributes { + function makeAttributes (attributes: TypeAttributes): TypeAttributes { if (schema.oneOf === undefined) { attributes = combineTypeAttributes( "union", @@ -758,17 +809,19 @@ async function addTypesInSchema( combineProducedAttributes(({ forType, forUnion, forCases }) => { assert( forUnion === undefined && forCases === undefined, - "We can't have attributes for unions and cases if we don't have a union" + "We can't have attributes for unions and cases if we don't have a union", ); return forType; - }) + }), ); } + return modifyTypeNames(attributes, maybeTypeNames => { const typeNames = defined(maybeTypeNames); if (!typeNames.areInferred) { return typeNames; } + let title = schema.title; if (typeof title !== "string") { title = loc.canonicalRef.definitionName; @@ -785,7 +838,7 @@ async function addTypesInSchema( typeAttributes = makeAttributes(typeAttributes); const inferredAttributes = makeTypeAttributesInferred(typeAttributes); - function makeStringType(attributes: TypeAttributes): TypeRef { + function makeStringType (attributes: TypeAttributes): TypeRef { const kind = typeKindForJSONSchemaFormat(schema.format); if (kind === undefined) { return typeBuilder.getStringType(attributes, StringTypes.unrestricted); @@ -794,7 +847,7 @@ async function addTypesInSchema( } } - async function makeArrayType(): Promise { + async function makeArrayType (): Promise { const singularAttributes = singularizeTypeNames(typeAttributes); const items = schema.items; let itemType: TypeRef; @@ -813,11 +866,12 @@ async function addTypesInSchema( } else { itemType = typeBuilder.getPrimitiveType("any"); } + typeBuilder.addAttributes(itemType, singularAttributes); return typeBuilder.getArrayType(emptyTypeAttributes, itemType); } - async function makeObjectType(): Promise { + async function makeObjectType (): Promise { let required: string[]; if (schema.required === undefined || typeof schema.required === "boolean") { required = []; @@ -834,7 +888,7 @@ async function addTypesInSchema( // In Schema Draft 3, `required` is `true` on a property that's required. for (const p of Object.getOwnPropertyNames(properties)) { - if (properties[p].required === true && required.indexOf(p) < 0) { + if (properties[p].required === true && !required.includes(p)) { required.push(p); } } @@ -853,7 +907,7 @@ async function addTypesInSchema( const objectAttributes = combineTypeAttributes( "union", inferredAttributes, - combineProducedAttributes(({ forObject }) => forObject) + combineProducedAttributes(({ forObject }) => forObject), ); const order = schema.quicktypePropertyOrder ? schema.quicktypePropertyOrder : []; const orderKey = (propertyName: string) => { @@ -866,18 +920,19 @@ async function addTypesInSchema( return await makeObject(loc, objectAttributes, properties, required, additionalProperties, orderKey); } - async function makeTypesFromCases(cases: any, kind: string): Promise { + async function makeTypesFromCases (cases: any, kind: string): Promise { const kindLoc = loc.push(kind); if (!Array.isArray(cases)) { return messageError("SchemaSetOperationCasesIsNotArray", withRef(kindLoc, { operation: kind, cases })); } + // FIXME: This cast shouldn't be necessary, but TypeScript forces our hand. return await arrayMapSync(cases, async (t, index) => { const caseLoc = kindLoc.push(index.toString()); return await toType( checkJSONSchema(t, caseLoc.canonicalRef), caseLoc, - makeTypeAttributesInferred(typeAttributes) + makeTypeAttributesInferred(typeAttributes), ); }); } @@ -885,7 +940,7 @@ async function addTypesInSchema( const intersectionType = typeBuilder.getUniqueIntersectionType(typeAttributes, undefined); setTypeForLocation(loc, intersectionType); - async function convertOneOrAnyOf(cases: any, kind: string): Promise { + async function convertOneOrAnyOf (cases: any, kind: string): Promise { const typeRefs = await makeTypesFromCases(cases, kind); let unionAttributes = makeTypeAttributesInferred(typeAttributes); if (kind === "oneOf") { @@ -893,13 +948,15 @@ async function addTypesInSchema( if (forType !== undefined) { typeBuilder.addAttributes(intersectionType, forType); } + if (forUnion !== undefined) { unionAttributes = combineTypeAttributes("union", unionAttributes, forUnion); } + if (forCases !== undefined) { assert( forCases.length === typeRefs.length, - "Number of case attributes doesn't match number of cases" + "Number of case attributes doesn't match number of cases", ); for (let i = 0; i < typeRefs.length; i++) { typeBuilder.addAttributes(typeRefs[i], forCases[i]); @@ -907,6 +964,7 @@ async function addTypesInSchema( } }); } + const unionType = typeBuilder.getUniqueUnionType(unionAttributes, undefined); typeBuilder.setSetOperationMembers(unionType, new Set(typeRefs)); return unionType; @@ -938,8 +996,8 @@ async function addTypesInSchema( ["null", "null"], ["number", "double"], ["integer", "integer"], - ["boolean", "bool"] - ] as [JSONSchemaType, PrimitiveTypeKind][]) { + ["boolean", "bool"], + ] as Array<[JSONSchemaType, PrimitiveTypeKind]>) { if (!includedTypes.has(name)) continue; const attributes = isNumberTypeKind(kind) ? numberAttributes : undefined; @@ -949,7 +1007,7 @@ async function addTypesInSchema( const stringAttributes = combineTypeAttributes( "union", inferredAttributes, - combineProducedAttributes(({ forString }) => forString) + combineProducedAttributes(({ forString }) => forString), ); if (needStringEnum || isConst) { @@ -964,6 +1022,7 @@ async function addTypesInSchema( if (includeArray) { unionTypes.push(await makeArrayType()); } + if (includeObject) { unionTypes.push(await makeObjectType()); } @@ -975,6 +1034,7 @@ async function addTypesInSchema( if (typeof schema.$ref !== "string") { return messageError("SchemaRefMustBeString", withRef(loc, { actual: typeof schema.$ref })); } + const virtualRef = Ref.parse(schema.$ref); const [target, newLoc] = await resolver.resolveVirtualRef(loc, virtualRef); const attributes = modifyTypeNames(typeAttributes, tn => { @@ -985,11 +1045,13 @@ async function addTypesInSchema( } if (schema.allOf !== undefined) { - types.push(...(await makeTypesFromCases(schema.allOf, "allOf"))); + types.push(...await makeTypesFromCases(schema.allOf, "allOf")); } + if (schema.oneOf !== undefined) { types.push(await convertOneOrAnyOf(schema.oneOf, "oneOf")); } + if (schema.anyOf !== undefined) { types.push(await convertOneOrAnyOf(schema.anyOf, "anyOf")); } @@ -998,7 +1060,7 @@ async function addTypesInSchema( return intersectionType; } - async function toType(schema: JSONSchema, loc: Location, typeAttributes: TypeAttributes): Promise { + async function toType (schema: JSONSchema, loc: Location, typeAttributes: TypeAttributes): Promise { const maybeType = typeForCanonicalRef.get(loc.canonicalRef); if (maybeType !== undefined) { return maybeType; @@ -1011,7 +1073,7 @@ async function addTypesInSchema( messageAssert(schema === true, "SchemaFalseNotSupported", withRef(loc)); result = typeBuilder.getPrimitiveType("any"); } else { - loc = loc.updateWithID(schema["$id"]); + loc = loc.updateWithID(schema.$id); result = await convertToType(schema, loc, typeAttributes); } @@ -1026,7 +1088,7 @@ async function addTypesInSchema( } } -function removeExtension(fn: string): string { +function removeExtension (fn: string): string { const lower = fn.toLowerCase(); const extensions = [".json", ".schema"]; for (const ext of extensions) { @@ -1037,10 +1099,11 @@ function removeExtension(fn: string): string { } } } + return fn; } -function nameFromURI(uri: URI): string | undefined { +function nameFromURI (uri: URI): string | undefined { const fragment = uri.fragment(); if (fragment !== "") { const components = fragment.split("/"); @@ -1048,27 +1111,31 @@ function nameFromURI(uri: URI): string | undefined { if (components[len - 1] !== "") { return removeExtension(components[len - 1]); } + if (len > 1 && components[len - 2] !== "") { return removeExtension(components[len - 2]); } } + const filename = uri.filename(); if (filename !== "") { return removeExtension(filename); } + return messageError("DriverCannotInferNameForSchema", { uri: uri.toString() }); } -async function refsInSchemaForURI( +async function refsInSchemaForURI ( resolver: Resolver, uri: URI, - defaultName: string + defaultName: string, ): Promise | [string, Ref]> { const fragment = uri.fragment(); let propertiesAreTypes = fragment.endsWith("/"); if (propertiesAreTypes) { uri = uri.clone().fragment(fragment.slice(0, -1)); } + const ref = Ref.parseURI(uri); if (ref.isRoot) { propertiesAreTypes = false; @@ -1080,6 +1147,7 @@ async function refsInSchemaForURI( if (typeof schema !== "object") { return messageError("SchemaCannotGetTypesFromBoolean", { ref: ref.toString() }); } + return mapMap(mapFromObject(schema), (_, name) => ref.push(name)); } else { let name: string; @@ -1089,54 +1157,59 @@ async function refsInSchemaForURI( const maybeName = nameFromURI(uri); name = maybeName !== undefined ? maybeName : defaultName; } + return [name, ref]; } } class InputJSONSchemaStore extends JSONSchemaStore { - constructor( + constructor ( private readonly _inputs: Map, - private readonly _delegate?: JSONSchemaStore + private readonly _delegate?: JSONSchemaStore, ) { super(); } - async fetch(address: string): Promise { + async fetch (address: string): Promise { const maybeInput = this._inputs.get(address); if (maybeInput !== undefined) { return checkJSONSchema(parseJSON(maybeInput, "JSON Schema", address), () => Ref.root(address)); } + if (this._delegate === undefined) { return panic(`Schema URI ${address} requested, but no store given`); } + return await this._delegate.fetch(address); } } export interface JSONSchemaSourceData { + isConverted?: boolean; name: string; - uris?: string[]; schema?: string; - isConverted?: boolean; + uris?: string[]; } export class JSONSchemaInput implements Input { readonly kind: string = "schema"; + readonly needSchemaProcessing: boolean = true; private readonly _attributeProducers: JSONSchemaAttributeProducer[]; private readonly _schemaInputs: Map = new Map(); - private _schemaSources: [URI, JSONSchemaSourceData][] = []; + + private _schemaSources: Array<[URI, JSONSchemaSourceData]> = []; private readonly _topLevels: Map = new Map(); private _needIR = false; - constructor( + constructor ( private _schemaStore: JSONSchemaStore | undefined, additionalAttributeProducers: JSONSchemaAttributeProducer[] = [], - private readonly _additionalSchemaAddresses: ReadonlyArray = [] + private readonly _additionalSchemaAddresses: readonly string[] = [], ) { this._attributeProducers = [ descriptionAttributeProducer, @@ -1145,19 +1218,19 @@ export class JSONSchemaInput implements Input { uriSchemaAttributesProducer, minMaxAttributeProducer, minMaxLengthAttributeProducer, - patternAttributeProducer + patternAttributeProducer, ].concat(additionalAttributeProducers); } - get needIR(): boolean { + get needIR (): boolean { return this._needIR; } - addTopLevel(name: string, ref: Ref): void { + addTopLevel (name: string, ref: Ref): void { this._topLevels.set(name, ref); } - async addTypes(ctx: RunContext, typeBuilder: TypeBuilder): Promise { + async addTypes (ctx: RunContext, typeBuilder: TypeBuilder): Promise { if (this._schemaSources.length === 0) return; let maybeSchemaStore = this._schemaStore; @@ -1168,6 +1241,7 @@ export class JSONSchemaInput implements Input { } else { maybeSchemaStore = this._schemaStore = new InputJSONSchemaStore(this._schemaInputs, maybeSchemaStore); } + const schemaStore = maybeSchemaStore; const canonizer = new Canonizer(ctx); @@ -1176,6 +1250,7 @@ export class JSONSchemaInput implements Input { if (schema === undefined) { return messageError("SchemaFetchErrorAdditional", { address }); } + canonizer.addSchema(schema, address); } @@ -1192,6 +1267,7 @@ export class JSONSchemaInput implements Input { } else { name = refs[0]; } + this.addTopLevel(name, refs[1]); } else { for (const [refName, ref] of refs) { @@ -1203,15 +1279,15 @@ export class JSONSchemaInput implements Input { await addTypesInSchema(resolver, typeBuilder, this._topLevels, this._attributeProducers); } - addTypesSync(): void { + addTypesSync (): void { return panic("addTypesSync not supported in JSONSchemaInput"); } - async addSource(schemaSource: JSONSchemaSourceData): Promise { - return this.addSourceSync(schemaSource); + async addSource (schemaSource: JSONSchemaSourceData): Promise { + this.addSourceSync(schemaSource); } - addSourceSync(schemaSource: JSONSchemaSourceData): void { + addSourceSync (schemaSource: JSONSchemaSourceData): void { const { name, uris, schema, isConverted } = schemaSource; if (isConverted !== true) { @@ -1227,6 +1303,7 @@ export class JSONSchemaInput implements Input { if (normalizedURI.clone().hash("").toString() === "") { normalizedURI.path(name); } + return normalizedURI; }); } @@ -1243,8 +1320,10 @@ export class JSONSchemaInput implements Input { if (suffix > 0) { uri.path(`${path}-${suffix}`); } + suffix++; } while (this._schemaInputs.has(uri.toString())); + this._schemaInputs.set(uri.toString(), schema); normalizedURIs[i] = uri.hash(normalizedURI.hash()); } @@ -1256,14 +1335,16 @@ export class JSONSchemaInput implements Input { } } - singleStringSchemaSource(): string | undefined { + singleStringSchemaSource (): string | undefined { if (!this._schemaSources.every(([_, { schema }]) => typeof schema === "string")) { return undefined; } + const set = new Set(this._schemaSources.map(([_, { schema }]) => schema as string)); if (set.size === 1) { return defined(iterableFirst(set)); } + return undefined; } } diff --git a/packages/quicktype-core/src/input/JSONSchemaStore.ts b/packages/quicktype-core/src/input/JSONSchemaStore.ts index dc7ef9aea..32f886e3e 100644 --- a/packages/quicktype-core/src/input/JSONSchemaStore.ts +++ b/packages/quicktype-core/src/input/JSONSchemaStore.ts @@ -1,38 +1,45 @@ -import { StringMap, assert } from "../support/Support"; +import { type StringMap} from "../support/Support"; +import { assert } from "../support/Support"; export type JSONSchema = StringMap | boolean; export abstract class JSONSchemaStore { private readonly _schemas = new Map(); - private add(address: string, schema: JSONSchema): void { + private add (address: string, schema: JSONSchema): void { assert(!this._schemas.has(address), "Cannot set a schema for an address twice"); this._schemas.set(address, schema); } // FIXME: Remove the undefined option - abstract fetch(_address: string): Promise; + abstract fetch (_address: string): Promise; - async get(address: string, debugPrint: boolean): Promise { + async get (address: string, debugPrint: boolean): Promise { let schema = this._schemas.get(address); if (schema !== undefined) { return schema; } + if (debugPrint) { console.log(`trying to fetch ${address}`); } + try { schema = await this.fetch(address); } catch {} + if (schema === undefined) { if (debugPrint) { console.log(`couldn't fetch ${address}`); } + return undefined; } + if (debugPrint) { console.log(`successully fetched ${address}`); } + this.add(address, schema); return schema; } diff --git a/packages/quicktype-core/src/input/PostmanCollection.ts b/packages/quicktype-core/src/input/PostmanCollection.ts index d5de09947..7d4a4b7b2 100644 --- a/packages/quicktype-core/src/input/PostmanCollection.ts +++ b/packages/quicktype-core/src/input/PostmanCollection.ts @@ -1,7 +1,7 @@ import { parseJSON } from "../support/Support"; -import { JSONSourceData } from "./Inputs"; +import { type JSONSourceData } from "./Inputs"; -function isValidJSON(s: string): boolean { +function isValidJSON (s: string): boolean { try { JSON.parse(s); return true; @@ -10,23 +10,25 @@ function isValidJSON(s: string): boolean { } } -export function sourcesFromPostmanCollection( +export function sourcesFromPostmanCollection ( collectionJSON: string, - collectionJSONAddress?: string -): { sources: JSONSourceData[]; description: string | undefined } { - const sources: JSONSourceData[] = []; + collectionJSONAddress?: string, +): { description: string | undefined, sources: Array>, } { + const sources: Array> = []; const descriptions: string[] = []; - function processCollection(c: any): void { + function processCollection (c: any): void { if (typeof c !== "object") return; if (Array.isArray(c.item)) { for (const item of c.item) { processCollection(item); } + if (typeof c.info === "object" && typeof c.info.description === "string") { descriptions.push(c.info.description); } } + if (typeof c.name === "string" && Array.isArray(c.response)) { const samples: string[] = []; for (const r of c.response) { @@ -34,6 +36,7 @@ export function sourcesFromPostmanCollection( samples.push(r.body); } } + if (samples.length > 0) { const source: JSONSourceData = { name: c.name, samples }; const sourceDescription = [c.name]; diff --git a/packages/quicktype-core/src/input/io/NodeIO.ts b/packages/quicktype-core/src/input/io/NodeIO.ts index e7cfe588e..bb6d3f8f9 100644 --- a/packages/quicktype-core/src/input/io/NodeIO.ts +++ b/packages/quicktype-core/src/input/io/NodeIO.ts @@ -1,5 +1,5 @@ import * as fs from "fs"; -import { Readable } from "readable-stream"; +import { type Readable } from "readable-stream"; import { isNode } from "browser-or-node"; import { getStream } from "./get-stream"; import { defined, exceptionToString } from "@glideapps/ts-necessities"; @@ -12,7 +12,7 @@ interface HttpHeaders { [key: string]: string; } -function parseHeaders(httpHeaders?: string[]): HttpHeaders { +function parseHeaders (httpHeaders?: string[]): HttpHeaders { if (!Array.isArray(httpHeaders)) { return {}; } @@ -34,11 +34,11 @@ function parseHeaders(httpHeaders?: string[]): HttpHeaders { }, {} as HttpHeaders); } -export async function readableFromFileOrURL(fileOrURL: string, httpHeaders?: string[]): Promise { +export async function readableFromFileOrURL (fileOrURL: string, httpHeaders?: string[]): Promise { try { if (isURL(fileOrURL)) { const response = await fetch(fileOrURL, { - headers: parseHeaders(httpHeaders) + headers: parseHeaders(httpHeaders), }); return defined(response.body) as unknown as Readable; } else if (isNode) { @@ -46,6 +46,7 @@ export async function readableFromFileOrURL(fileOrURL: string, httpHeaders?: str // Cast node readable to isomorphic readable from readable-stream return process.stdin as unknown as Readable; } + const filePath = fs.lstatSync(fileOrURL).isSymbolicLink() ? fs.readlinkSync(fileOrURL) : fileOrURL; if (fs.existsSync(filePath)) { // Cast node readable to isomorphic readable from readable-stream @@ -55,10 +56,11 @@ export async function readableFromFileOrURL(fileOrURL: string, httpHeaders?: str } catch (e) { return messageError("MiscReadError", { fileOrURL, message: exceptionToString(e) }); } + return messageError("DriverInputFileDoesNotExist", { filename: fileOrURL }); } -export async function readFromFileOrURL(fileOrURL: string, httpHeaders?: string[]): Promise { +export async function readFromFileOrURL (fileOrURL: string, httpHeaders?: string[]): Promise { const readable = await readableFromFileOrURL(fileOrURL, httpHeaders); try { return await getStream(readable); diff --git a/packages/quicktype-core/src/input/io/get-stream/buffer-stream.ts b/packages/quicktype-core/src/input/io/get-stream/buffer-stream.ts index 19cd6ec30..f1cb10861 100644 --- a/packages/quicktype-core/src/input/io/get-stream/buffer-stream.ts +++ b/packages/quicktype-core/src/input/io/get-stream/buffer-stream.ts @@ -1,7 +1,7 @@ -import { Options } from "."; +import { type Options } from "."; import { PassThrough } from "readable-stream"; -export default function bufferStream(opts: Options) { +export default function bufferStream (opts: Options) { opts = Object.assign({}, opts); const array = opts.array; @@ -22,7 +22,7 @@ export default function bufferStream(opts: Options) { let len = 0; const ret: any[] = []; const stream = new PassThrough({ - objectMode + objectMode, }) as any; if (encoding) { diff --git a/packages/quicktype-core/src/input/io/get-stream/index.ts b/packages/quicktype-core/src/input/io/get-stream/index.ts index 9036e7c89..98ae97240 100644 --- a/packages/quicktype-core/src/input/io/get-stream/index.ts +++ b/packages/quicktype-core/src/input/io/get-stream/index.ts @@ -1,15 +1,15 @@ -import { Readable } from "readable-stream"; +import { type Readable } from "readable-stream"; import bufferStream from "./buffer-stream"; export interface Options { - maxBuffer?: number; array?: boolean; encoding?: string; + maxBuffer?: number; } -export function getStream(inputStream: Readable, opts: Options = {}) { +export async function getStream (inputStream: Readable, opts: Options = {}) { if (!inputStream) { - return Promise.reject(new Error("Expected a stream")); + return await Promise.reject(new Error("Expected a stream")); } opts = Object.assign({ maxBuffer: Infinity }, opts); @@ -50,13 +50,13 @@ export function getStream(inputStream: Readable, opts: Options = {}) { p.then(clean, clean); - return p.then(() => stream.getBufferedValue()); + return await p.then(() => stream.getBufferedValue()); } -export function buffer(stream: Readable, opts: Options = {}) { +export function buffer (stream: Readable, opts: Options = {}) { getStream(stream, Object.assign({}, opts, { encoding: "buffer" })); } -export function array(stream: Readable, opts: Options = {}) { +export function array (stream: Readable, opts: Options = {}) { getStream(stream, Object.assign({}, opts, { array: true })); } diff --git a/packages/quicktype-core/src/language/All.ts b/packages/quicktype-core/src/language/All.ts index 19313870a..91cb4b1a0 100644 --- a/packages/quicktype-core/src/language/All.ts +++ b/packages/quicktype-core/src/language/All.ts @@ -1,6 +1,6 @@ import { iterableFind } from "collection-utils"; -import { TargetLanguage } from "../TargetLanguage"; +import { type TargetLanguage } from "../TargetLanguage"; import { CSharpTargetLanguage } from "./CSharp"; import { GoTargetLanguage } from "./Golang"; @@ -54,16 +54,17 @@ export const all: TargetLanguage[] = [ new HaskellTargetLanguage(), new TypeScriptZodTargetLanguage(), new TypeScriptEffectSchemaTargetLanguage(), - new PhpTargetLanguage() + new PhpTargetLanguage(), ]; -export function languageNamed(name: string, targetLanguages?: TargetLanguage[]): TargetLanguage | undefined { +export function languageNamed (name: string, targetLanguages?: TargetLanguage[]): TargetLanguage | undefined { if (targetLanguages === undefined) { targetLanguages = all; } + const maybeTargetLanguage = iterableFind( targetLanguages, - l => l.names.indexOf(name) >= 0 || l.displayName === name + l => l.names.includes(name) || l.displayName === name, ); if (maybeTargetLanguage !== undefined) return maybeTargetLanguage; return iterableFind(targetLanguages, l => l.extension === name); diff --git a/packages/quicktype-core/src/language/CJSON.ts b/packages/quicktype-core/src/language/CJSON.ts index 8dd1990b2..c103d3ffe 100644 --- a/packages/quicktype-core/src/language/CJSON.ts +++ b/packages/quicktype-core/src/language/CJSON.ts @@ -23,23 +23,28 @@ /* Imports */ import { TargetLanguage } from "../TargetLanguage"; -import { Type, TypeKind, ClassType, ArrayType, MapType, EnumType, UnionType } from "../Type"; +import { type Type, type TypeKind} from "../Type"; +import { ClassType, ArrayType, MapType, EnumType, UnionType } from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { NameStyle, Name, Namer, funPrefixNamer } from "../Naming"; -import { Sourcelike } from "../Source"; +import { type NameStyle, type Name, type Namer} from "../Naming"; +import { funPrefixNamer } from "../Naming"; +import { type Sourcelike } from "../Source"; +import { + type NamingStyle} from "../support/Strings"; import { allUpperWordStyle, legalizeCharacters, isAscii, isLetterOrUnderscoreOrDigit, - NamingStyle, - makeNameStyle + makeNameStyle, } from "../support/Strings"; import { defined, assertNever, panic, numberEnumValues } from "../support/Support"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { EnumOption, StringOption, Option, getOptionValues, OptionValues } from "../RendererOptions"; +import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { ConvenienceRenderer } from "../ConvenienceRenderer"; +import { type Option, type OptionValues } from "../RendererOptions"; +import { EnumOption, StringOption, getOptionValues } from "../RendererOptions"; import { assert } from "../support/Support"; -import { RenderContext } from "../Renderer"; +import { type RenderContext } from "../Renderer"; import { getAccessorName } from "../attributes/AccessorNames"; import { enumCaseValues } from "../attributes/EnumValues"; @@ -58,10 +63,10 @@ export const cJSONOptions = { "Source code generation type, whether to generate single or multiple source files", [ ["single-source", true], - ["multi-source", false] + ["multi-source", false], ], "single-source", - "secondary" + "secondary", ), typeIntegerSize: new EnumOption( "integer-size", @@ -70,36 +75,36 @@ export const cJSONOptions = { ["int8_t", "int8_t"], ["int16_t", "int16_t"], ["int32_t", "int32_t"], - ["int64_t", "int64_t"] + ["int64_t", "int64_t"], ], "int64_t", - "secondary" + "secondary", ), hashtableSize: new StringOption( "hashtable-size", "Hashtable size, used when maps are created (64 by default)", "SIZE", - "64" + "64", ), addTypedefAlias: new EnumOption( "typedef-alias", "Add typedef alias to unions, structs, and enums (no typedef by default)", [ ["no-typedef", false], - ["add-typedef", true] + ["add-typedef", true], ], "no-typedef", - "secondary" + "secondary", ), printStyle: new EnumOption( "print-style", "Which cJSON print should be used (formatted by default)", [ ["print-formatted", false], - ["print-unformatted", true] + ["print-unformatted", true], ], "print-formatted", - "secondary" + "secondary", ), typeNamingStyle: new EnumOption("type-style", "Naming style for types", [ pascalValue, @@ -107,7 +112,7 @@ export const cJSONOptions = { camelValue, upperUnderscoreValue, pascalUpperAcronymsValue, - camelUpperAcronymsValue + camelUpperAcronymsValue, ]), memberNamingStyle: new EnumOption("member-style", "Naming style for members", [ underscoreValue, @@ -115,7 +120,7 @@ export const cJSONOptions = { camelValue, upperUnderscoreValue, pascalUpperAcronymsValue, - camelUpperAcronymsValue + camelUpperAcronymsValue, ]), enumeratorNamingStyle: new EnumOption("enumerator-style", "Naming style for enumerators", [ upperUnderscoreValue, @@ -123,8 +128,8 @@ export const cJSONOptions = { pascalValue, camelValue, pascalUpperAcronymsValue, - camelUpperAcronymsValue - ]) + camelUpperAcronymsValue, + ]), }; /* cJSON generator target language */ @@ -135,7 +140,7 @@ export class CJSONTargetLanguage extends TargetLanguage { * @params names: names * @param extension: extension of files */ - constructor(displayName = "C (cJSON)", names: string[] = ["cjson", "cJSON"], extension = "h") { + constructor (displayName = "C (cJSON)", names: string[] = ["cjson", "cJSON"], extension = "h") { super(displayName, names, extension); } @@ -143,7 +148,7 @@ export class CJSONTargetLanguage extends TargetLanguage { * Return cJSON generator options * @return cJSON generator options array */ - protected getOptions(): Option[] { + protected getOptions (): Array> { return [ cJSONOptions.typeSourceStyle, cJSONOptions.typeIntegerSize, @@ -152,7 +157,7 @@ export class CJSONTargetLanguage extends TargetLanguage { cJSONOptions.hashtableSize, cJSONOptions.typeNamingStyle, cJSONOptions.memberNamingStyle, - cJSONOptions.enumeratorNamingStyle + cJSONOptions.enumeratorNamingStyle, ]; } @@ -160,7 +165,7 @@ export class CJSONTargetLanguage extends TargetLanguage { * Indicate if language support union with both number types * @return true */ - get supportsUnionsWithBothNumberTypes(): boolean { + get supportsUnionsWithBothNumberTypes (): boolean { return true; } @@ -168,7 +173,7 @@ export class CJSONTargetLanguage extends TargetLanguage { * Indicate if language support optional class properties * @return true */ - get supportsOptionalClassProperties(): boolean { + get supportsOptionalClassProperties (): boolean { return true; } @@ -178,7 +183,7 @@ export class CJSONTargetLanguage extends TargetLanguage { * @param untypedOptionValues * @return cJSON renderer */ - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): CJSONRenderer { + protected makeRenderer (renderContext: RenderContext, untypedOptionValues: { [name: string]: any, }): CJSONRenderer { return new CJSONRenderer(this, renderContext, getOptionValues(cJSONOptions, untypedOptionValues)); } } @@ -306,7 +311,7 @@ const keywords = [ "String", "StringArray", "StringReference", - "True" + "True", ]; /* Used to build forbidden global names */ @@ -328,46 +333,53 @@ export enum IncludeKind { } /* Used to map includes */ -export type IncludeRecord = { +export interface IncludeRecord { kind: IncludeKind | undefined /* How to include that */; typeKind: TypeKind | undefined /* What exactly to include */; -}; +} /* Used to map includes */ -export type TypeRecord = { +export interface TypeRecord { + forceInclude: boolean; + level: number; name: Name; type: Type; - level: number; variant: boolean; - forceInclude: boolean; -}; +} /* Map each and every unique type to a include kind, e.g. how to include the given type */ export type IncludeMap = Map; /* cJSON type */ -export type TypeCJSON = { +export interface TypeCJSON { + addToObject: Sourcelike /* cJSON add to object function */; cType: Sourcelike /* C type */; - optionalQualifier: string /* C optional qualifier, empty string if not defined */; cjsonType: string /* cJSON type */; - isType: Sourcelike /* cJSON check type function */; - getValue: Sourcelike /* cJSON get value function */; - addToObject: Sourcelike /* cJSON add to object function */; createObject: Sourcelike /* cJSON create object function */; deleteType: Sourcelike /* cJSON delete function */; - items: TypeCJSON | undefined /* Sub-items, used for arrays and map */; + getValue: Sourcelike /* cJSON get value function */; isNullable: boolean /* True if the field is nullable */; -}; + isType: Sourcelike /* cJSON check type function */; + items: TypeCJSON | undefined /* Sub-items, used for arrays and map */; + optionalQualifier: string /* C optional qualifier, empty string if not defined */; +} /* cJSON renderer */ export class CJSONRenderer extends ConvenienceRenderer { private currentFilename: string | undefined; /* Current filename */ - private memberNameStyle: NameStyle; /* Member name style */ - private namedTypeNameStyle: NameStyle; /* Named type name style */ - private forbiddenGlobalNames: string[]; /* Forbidden global names */ + + private readonly memberNameStyle: NameStyle; /* Member name style */ + + private readonly namedTypeNameStyle: NameStyle; /* Named type name style */ + + private readonly forbiddenGlobalNames: string[]; /* Forbidden global names */ + protected readonly typeIntegerSize: string; /* Integer code generation type */ + protected readonly hashtableSize: string; /* Hashtable default size */ + protected readonly typeNamingStyle: NamingStyle; /* Type naming style */ + protected readonly enumeratorNamingStyle: NamingStyle; /* Enum naming style */ /** @@ -376,10 +388,10 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param renderContext: render context * @param _options: renderer options */ - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues + private readonly _options: OptionValues, ) { super(targetLanguage, renderContext); this.typeIntegerSize = _options.typeIntegerSize; @@ -399,7 +411,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Build forbidden names for namespace * @return Forbidden names for namespace */ - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace (): string[] { return [...keywords, ...this.forbiddenGlobalNames]; } @@ -407,7 +419,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Build forbidden names for enums * @return Forbidden names for enums */ - protected forbiddenForEnumCases(_enumType: EnumType, _enumName: Name): ForbiddenWordsInfo { + protected forbiddenForEnumCases (_enumType: EnumType, _enumName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } @@ -415,7 +427,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Build forbidden names for unions members * @return Forbidden names for unions members */ - protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { + protected forbiddenForUnionMembers (_u: UnionType, _unionName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } @@ -423,7 +435,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Build forbidden names for objects * @return Forbidden names for objects */ - protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties (_c: ClassType, _className: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } @@ -431,7 +443,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Build types member names * @return types member namer */ - protected makeNamedTypeNamer(): Namer { + protected makeNamedTypeNamer (): Namer { return funPrefixNamer("types", this.namedTypeNameStyle); } @@ -439,7 +451,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Build object properties member names * @return object properties member namer */ - protected namerForObjectProperty(): Namer { + protected namerForObjectProperty (): Namer { return funPrefixNamer("members", this.memberNameStyle); } @@ -447,7 +459,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Build union member names * @return union member namer */ - protected makeUnionMemberNamer(): Namer { + protected makeUnionMemberNamer (): Namer { return funPrefixNamer("members", this.memberNameStyle); } @@ -455,7 +467,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Build enum member names * @return enum member namer */ - protected makeEnumCaseNamer(): Namer { + protected makeEnumCaseNamer (): Namer { return funPrefixNamer("enumerators", makeNameStyle(this.enumeratorNamingStyle, legalizeName)); } @@ -467,11 +479,11 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param lookup: Lookup function * @return Proposed union member name */ - protected proposeUnionMemberName( + protected proposeUnionMemberName ( unionType: UnionType, unionName: Name, fieldType: Type, - lookup: (n: Name) => string + lookup: (n: Name) => string, ): string { let fieldName = super.proposeUnionMemberName(unionType, unionName, fieldType, lookup); if ("bool" === fieldName) { @@ -479,6 +491,7 @@ export class CJSONRenderer extends ConvenienceRenderer { } else if ("double" === fieldName) { fieldName = "number"; } + return fieldName; } @@ -487,7 +500,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param fieldType: the variable type * @param fieldName: name of the variable */ - protected emitTypdefAlias(fieldType: Type, fieldName: Name) { + protected emitTypdefAlias (fieldType: Type, fieldName: Name) { if (this._options.addTypedefAlias) { this.emitLine("typedef ", this.quicktypeTypeToCJSON(fieldType, false).cType, " ", fieldName, ";"); this.ensureBlankLine(); @@ -498,7 +511,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Function called to create header file(s) * @param proposedFilename: source filename provided from stdin */ - protected emitSourceStructure(proposedFilename: string): void { + protected emitSourceStructure (proposedFilename: string): void { /* Depending of source style option, generate a unique header or multiple header files */ if (this._options.typeSourceStyle) { this.emitSingleSourceStructure(proposedFilename); @@ -511,7 +524,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Function called to create a single header file with types and generators * @param proposedFilename: source filename provided from stdin */ - protected emitSingleSourceStructure(proposedFilename: string): void { + protected emitSingleSourceStructure (proposedFilename: string): void { /* Create file */ this.startFile(proposedFilename); @@ -539,12 +552,12 @@ export class CJSONRenderer extends ConvenienceRenderer { this.forEachTopLevel( "leading", (type: Type, className: Name) => this.emitTopLevelTypedef(type, className), - type => this.namedTypeToNameForTopLevel(type) === undefined + type => this.namedTypeToNameForTopLevel(type) === undefined, ); /* Create enum prototypes */ this.forEachEnum("leading-and-interposing", (enumType: EnumType, _enumName: Name) => - this.emitEnumPrototypes(enumType) + this.emitEnumPrototypes(enumType), ); /* Create union prototypes */ @@ -552,19 +565,19 @@ export class CJSONRenderer extends ConvenienceRenderer { /* Create class prototypes */ this.forEachObject("leading-and-interposing", (classType: ClassType, _className: Name) => - this.emitClassPrototypes(classType) + this.emitClassPrototypes(classType), ); /* Create top level prototypes */ this.forEachTopLevel( "leading", (type: Type, className: Name) => this.emitTopLevelPrototypes(type, className), - type => this.namedTypeToNameForTopLevel(type) === undefined + type => this.namedTypeToNameForTopLevel(type) === undefined, ); /* Create enum functions */ this.forEachEnum("leading-and-interposing", (enumType: EnumType, _enumName: Name) => - this.emitEnumFunctions(enumType) + this.emitEnumFunctions(enumType), ); /* Create union functions */ @@ -572,14 +585,14 @@ export class CJSONRenderer extends ConvenienceRenderer { /* Create class functions */ this.forEachObject("leading-and-interposing", (classType: ClassType, _className: Name) => - this.emitClassFunctions(classType) + this.emitClassFunctions(classType), ); /* Create top level functions */ this.forEachTopLevel( "leading", (type: Type, className: Name) => this.emitTopLevelFunctions(type, className), - type => this.namedTypeToNameForTopLevel(type) === undefined + type => this.namedTypeToNameForTopLevel(type) === undefined, ); /* Close file */ @@ -589,7 +602,7 @@ export class CJSONRenderer extends ConvenienceRenderer { /** * Function called to create a multiple header files with types and generators */ - protected emitMultiSourceStructure(): void { + protected emitMultiSourceStructure (): void { /* Array of includes */ let includes: string[]; @@ -604,14 +617,14 @@ export class CJSONRenderer extends ConvenienceRenderer { }, (unionType, _name) => { this.emitUnion(unionType, includes); - } + }, ); /* Create top level file */ this.forEachTopLevel( "leading", (type: Type, className: Name) => this.emitTopLevel(type, className, includes), - type => this.namedTypeToNameForTopLevel(type) === undefined + type => this.namedTypeToNameForTopLevel(type) === undefined, ); } @@ -620,7 +633,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param enumType: enum type * @param includes: Array of includes */ - protected emitEnum(enumType: EnumType, includes: string[]): void { + protected emitEnum (enumType: EnumType, includes: string[]): void { /* Create file */ const enumName = this.nameForNamedType(enumType); const filename = this.sourcelikeToString(enumName).concat(".h"); @@ -647,7 +660,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Function called to create enum typedef * @param enumType: enum type */ - protected emitEnumTypedef(enumType: EnumType): void { + protected emitEnumTypedef (enumType: EnumType): void { /* FIXME: Now there is a language with need of global enum name, see FIXME in makeNameForEnumCase of ConvenienceRenderer.ts, should simplify here when fixed */ const enumName = this.nameForNamedType(enumType); @@ -672,7 +685,7 @@ export class CJSONRenderer extends ConvenienceRenderer { }); }, "", - true + true, ); this.ensureBlankLine(); this.emitTypdefAlias(enumType, enumName); @@ -682,7 +695,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Function called to create enum prototypes * @param enumType: enum type */ - protected emitEnumPrototypes(enumType: EnumType): void { + protected emitEnumPrototypes (enumType: EnumType): void { const enumName = this.nameForNamedType(enumType); this.emitLine("enum ", enumName, " cJSON_Get", enumName, "Value(", this.withConst("cJSON"), " * j);"); @@ -694,7 +707,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Function called to create enum functions * @param enumType: enum type */ - protected emitEnumFunctions(enumType: EnumType): void { + protected emitEnumFunctions (enumType: EnumType): void { const enumName = this.nameForNamedType(enumType); /* Create cJSON to enumName generator function */ @@ -706,13 +719,13 @@ export class CJSONRenderer extends ConvenienceRenderer { this.forEachEnumCase(enumType, "none", (name, jsonName) => { this.emitLine( onFirst ? "" : "else ", - 'if (!strcmp(cJSON_GetStringValue(j), "', + "if (!strcmp(cJSON_GetStringValue(j), \"", jsonName, - '")) x = ', + "\")) x = ", combinedName, "_", name, - ";" + ";", ); onFirst = false; }); @@ -732,9 +745,9 @@ export class CJSONRenderer extends ConvenienceRenderer { combinedName, "_", name, - ': j = cJSON_CreateString("', + ": j = cJSON_CreateString(\"", jsonName, - '"); break;' + "\"); break;", ); }); }); @@ -748,7 +761,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param unionType: union type * @param includes: Array of includes */ - protected emitUnion(unionType: UnionType, includes: string[]): void { + protected emitUnion (unionType: UnionType, includes: string[]): void { /* Create file */ const unionName = this.nameForNamedType(unionType); const filename = this.sourcelikeToString(unionName).concat(".h"); @@ -775,7 +788,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Function called to create union typedef * @param unionType: union type */ - protected emitUnionTypedef(unionType: UnionType): void { + protected emitUnionTypedef (unionType: UnionType): void { const [_hasNull, nonNulls] = removeNullFromUnion(unionType); const unionName = this.nameForNamedType(unionType); @@ -795,16 +808,16 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.optionalQualifier, " ", this.nameForUnionMember(unionType, type), - ";" + ";", ); } }, "value", - true + true, ); }, "", - true + true, ); this.ensureBlankLine(); this.emitTypdefAlias(unionType, unionName); @@ -814,7 +827,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Function called to create union prototypes * @param unionType: union type */ - protected emitUnionPrototypes(unionType: UnionType): void { + protected emitUnionPrototypes (unionType: UnionType): void { const unionName = this.nameForNamedType(unionType); this.emitLine("struct ", unionName, " * cJSON_Get", unionName, "Value(const cJSON * j);"); @@ -827,7 +840,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Function called to create union functions * @param unionType: union type */ - protected emitUnionFunctions(unionType: UnionType): void { + protected emitUnionFunctions (unionType: UnionType): void { const [hasNull, nonNulls] = removeNullFromUnion(unionType); const unionName = this.nameForNamedType(unionType); @@ -843,6 +856,7 @@ export class CJSONRenderer extends ConvenienceRenderer { }); onFirst = false; } + for (const type of nonNulls) { const cJSON = this.quicktypeTypeToCJSON(type, false); this.emitBlock([onFirst === true ? "if (" : "else if (", cJSON.isType, "(j))"], () => { @@ -859,7 +873,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ", j", level > 0 ? level.toString() : "", - ")" + ")", ], () => { const add = (cJSON: TypeCJSON, level: number, child_level: number) => { @@ -878,7 +892,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.cType, " *)0xDEADBEEF, sizeof(", cJSON.items!.cType, - " *));" + " *));", ); } else if (cJSON.items!.cjsonType === "cJSON_String") { this.emitLine( @@ -890,7 +904,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ")), sizeof(", cJSON.items!.cType, - " *));" + " *));", ); } else if ( cJSON.items!.cjsonType === "cJSON_Object" || @@ -905,7 +919,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "), sizeof(", cJSON.items!.cType, - " *));" + " *));", ); } else { this.emitLine( @@ -914,7 +928,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", " = cJSON_malloc(sizeof(", cJSON.items!.cType, - "));" + "));", ); this.emitBlock( ["if (NULL != tmp", level > 0 ? level.toString() : "", ")"], @@ -926,7 +940,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.getValue, "(e", child_level.toString(), - ");" + ");", ); this.emitLine( "list_add_tail(x", @@ -935,37 +949,38 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", ", sizeof(", cJSON.items!.cType, - " *));" + " *));", ); - } + }, ); } }; + if (cJSON.items!.isNullable) { this.emitBlock( ["if (!cJSON_IsNull(e", child_level.toString(), "))"], () => { add(cJSON, level, child_level); - } + }, ); this.emitBlock(["else"], () => { this.emitLine( "list_add_tail(x", child_level.toString(), - ", (void *)0xDEADBEEF, sizeof(void *));" + ", (void *)0xDEADBEEF, sizeof(void *));", ); }); } else { add(cJSON, level, child_level); } - } + }, ); this.emitLine( "x->value.", this.nameForUnionMember(unionType, type), " = x", child_level.toString(), - ";" + ";", ); }); } else if (cJSON.cjsonType === "cJSON_Map" && cJSON.items !== undefined) { @@ -977,7 +992,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), " = hashtable_create(", this.hashtableSize, - ", false);" + ", false);", ); this.emitBlock(["if (NULL != x", child_level.toString(), ")"], () => { this.emitLine("cJSON * e", child_level.toString(), " = NULL;"); @@ -987,7 +1002,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ", j", level > 0 ? level.toString() : "", - ")" + ")", ], () => { const add = (cJSON: TypeCJSON, level: number, child_level: number) => { @@ -1008,7 +1023,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.cType, " *)0xDEADBEEF, sizeof(", cJSON.items!.cType, - " *));" + " *));", ); } else if (cJSON.items!.cjsonType === "cJSON_String") { this.emitLine( @@ -1022,7 +1037,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ")), sizeof(", cJSON.items!.cType, - " *));" + " *));", ); } else if ( cJSON.items!.cjsonType === "cJSON_Object" || @@ -1039,7 +1054,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "), sizeof(", cJSON.items!.cType, - " *));" + " *));", ); } else { this.emitLine( @@ -1048,7 +1063,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", " = cJSON_malloc(sizeof(", cJSON.items!.cType, - "));" + "));", ); this.emitBlock( ["if (NULL != tmp", level > 0 ? level.toString() : "", ")"], @@ -1060,7 +1075,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.getValue, "(e", child_level.toString(), - ");" + ");", ); this.emitLine( "hashtable_add(x", @@ -1071,18 +1086,19 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", ", sizeof(", cJSON.items!.cType, - " *));" + " *));", ); - } + }, ); } }; + if (cJSON.items!.isNullable) { this.emitBlock( ["if (!cJSON_IsNull(e", child_level.toString(), "))"], () => { add(cJSON, level, child_level); - } + }, ); this.emitBlock(["else"], () => { this.emitLine( @@ -1090,20 +1106,20 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ", e", child_level.toString(), - "->string, (void *)0xDEADBEEF, sizeof(void *));" + "->string, (void *)0xDEADBEEF, sizeof(void *));", ); }); } else { add(cJSON, level, child_level); } - } + }, ); this.emitLine( "x->value.", this.nameForUnionMember(unionType, type), " = x", child_level.toString(), - ";" + ";", ); }); } else if (cJSON.cjsonType === "cJSON_Invalid" || cJSON.cjsonType === "cJSON_NULL") { @@ -1112,7 +1128,7 @@ export class CJSONRenderer extends ConvenienceRenderer { this.nameForUnionMember(unionType, type), " = (", cJSON.cType, - " *)0xDEADBEEF;" + " *)0xDEADBEEF;", ); } else if (cJSON.cjsonType === "cJSON_String") { this.emitLine( @@ -1120,7 +1136,7 @@ export class CJSONRenderer extends ConvenienceRenderer { this.nameForUnionMember(unionType, type), " = strdup(", cJSON.getValue, - "(j));" + "(j));", ); } else { this.emitLine( @@ -1128,7 +1144,7 @@ export class CJSONRenderer extends ConvenienceRenderer { this.nameForUnionMember(unionType, type), " = ", cJSON.getValue, - "(j);" + "(j);", ); } }); @@ -1152,6 +1168,7 @@ export class CJSONRenderer extends ConvenienceRenderer { }); onFirst = false; } + for (const type of nonNulls) { const cJSON = this.quicktypeTypeToCJSON(type, false); this.emitBlock( @@ -1165,7 +1182,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), " = ", cJSON.createObject, - "();" + "();", ); this.emitBlock(["if (NULL != j", child_level.toString(), ")"], () => { this.emitLine( @@ -1176,7 +1193,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->value.", this.nameForUnionMember(unionType, type), - ");" + ");", ); this.emitBlock(["while (NULL != x", child_level.toString(), ")"], () => { const add = (cJSON: TypeCJSON, child_level: number) => { @@ -1192,7 +1209,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ", ", cJSON.items!.createObject, - "());" + "());", ); } else if ( cJSON.items!.cjsonType === "cJSON_String" || @@ -1206,7 +1223,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.createObject, "(x", child_level.toString(), - "));" + "));", ); } else { this.emitLine( @@ -1216,27 +1233,29 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.createObject, "(*x", child_level.toString(), - "));" + "));", ); } }; + if (cJSON.items!.isNullable) { this.emitBlock( ["if ((void *)0xDEADBEEF != x", child_level.toString(), ")"], () => { add(cJSON, child_level); - } + }, ); this.emitBlock(["else"], () => { this.emitLine( "cJSON_AddItemToArray(j", child_level.toString(), - ", cJSON_CreateNull());" + ", cJSON_CreateNull());", ); }); } else { add(cJSON, child_level); } + this.emitLine( "x", child_level.toString(), @@ -1244,7 +1263,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->value.", this.nameForUnionMember(unionType, type), - ");" + ");", ); }); this.emitLine("j = j", child_level.toString(), ";"); @@ -1257,7 +1276,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), " = ", cJSON.createObject, - "();" + "();", ); this.emitBlock(["if (NULL != j", child_level.toString(), ")"], () => { this.emitLine("char **keys", child_level.toString(), " = NULL;"); @@ -1270,7 +1289,7 @@ export class CJSONRenderer extends ConvenienceRenderer { this.nameForUnionMember(unionType, type), ", &keys", child_level.toString(), - ");" + ");", ); this.emitBlock(["if (NULL != keys", child_level.toString(), ")"], () => { this.emitBlock( @@ -1283,7 +1302,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "; index", child_level.toString(), - "++)" + "++)", ], () => { this.emitLine( @@ -1298,7 +1317,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "[index", child_level.toString(), - "]);" + "]);", ); const add = (cJSON: TypeCJSON, child_level: number) => { if (cJSON.items!.cjsonType === "cJSON_Array") { @@ -1318,7 +1337,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "], ", cJSON.items!.createObject, - "());" + "());", ); } else if ( cJSON.items!.cjsonType === "cJSON_String" || @@ -1337,7 +1356,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.createObject, "(x", child_level.toString(), - "));" + "));", ); } else { this.emitLine( @@ -1352,20 +1371,21 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.createObject, "(*x", child_level.toString(), - "));" + "));", ); } }; + if (cJSON.items!.isNullable) { this.emitBlock( [ "if ((void *)0xDEADBEEF != x", child_level.toString(), - ")" + ")", ], () => { add(cJSON, child_level); - } + }, ); this.emitBlock(["else"], () => { this.emitLine( @@ -1376,13 +1396,13 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "[index", child_level.toString(), - "], cJSON_CreateNull());" + "], cJSON_CreateNull());", ); }); } else { add(cJSON, child_level); } - } + }, ); this.emitLine("cJSON_free(keys", child_level.toString(), ");"); }); @@ -1398,16 +1418,16 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.createObject, "(x->value.", this.nameForUnionMember(unionType, type), - ");" + ");", ); } - } + }, ); onFirst = false; } }); this.emitLine("return j;"); - } + }, ); this.ensureBlankLine(); @@ -1427,7 +1447,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->value.", this.nameForUnionMember(unionType, type), - ")" + ")", ], () => { this.emitLine( @@ -1438,7 +1458,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->value.", this.nameForUnionMember(unionType, type), - ");" + ");", ); this.emitBlock(["while (NULL != x", child_level.toString(), ")"], () => { if (cJSON.items!.cjsonType === "cJSON_Array") { @@ -1459,19 +1479,20 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.deleteType, "(x", child_level.toString(), - ");" + ");", ); - } + }, ); } else { this.emitLine( cJSON.items!.deleteType, "(x", child_level.toString(), - ");" + ");", ); } } + this.emitLine( "x", child_level.toString(), @@ -1479,7 +1500,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->value.", this.nameForUnionMember(unionType, type), - ");" + ");", ); }); this.emitLine( @@ -1488,9 +1509,9 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->value.", this.nameForUnionMember(unionType, type), - ");" + ");", ); - } + }, ); } else if (cJSON.cjsonType === "cJSON_Map" && cJSON.items !== undefined) { const level = 0; @@ -1501,7 +1522,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->value.", this.nameForUnionMember(unionType, type), - ")" + ")", ], () => { this.emitLine("char **keys", child_level.toString(), " = NULL;"); @@ -1514,7 +1535,7 @@ export class CJSONRenderer extends ConvenienceRenderer { this.nameForUnionMember(unionType, type), ", &keys", child_level.toString(), - ");" + ");", ); this.emitBlock(["if (NULL != keys", child_level.toString(), ")"], () => { this.emitBlock( @@ -1527,7 +1548,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "; index", child_level.toString(), - "++)" + "++)", ], () => { this.emitLine( @@ -1542,7 +1563,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "[index", child_level.toString(), - "]);" + "]);", ); this.emitBlock(["if (NULL != x", child_level.toString(), ")"], () => { if (cJSON.items!.cjsonType === "cJSON_Array") { @@ -1560,28 +1581,28 @@ export class CJSONRenderer extends ConvenienceRenderer { [ "if ((void *)0xDEADBEEF != x", child_level.toString(), - ")" + ")", ], () => { this.emitLine( cJSON.items!.deleteType, "(x", child_level.toString(), - ");" + ");", ); - } + }, ); } else { this.emitLine( cJSON.items!.deleteType, "(x", child_level.toString(), - ");" + ");", ); } } }); - } + }, ); this.emitLine("cJSON_free(keys", child_level.toString(), ");"); }); @@ -1591,9 +1612,9 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->value.", this.nameForUnionMember(unionType, type), - ");" + ");", ); - } + }, ); } else if (cJSON.cjsonType === "cJSON_Invalid" || cJSON.cjsonType === "cJSON_NULL") { /* Nothing to do */ @@ -1606,7 +1627,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.deleteType, "(x->value.", this.nameForUnionMember(unionType, type), - ");" + ");", ); } else { /* Nothing to do */ @@ -1614,6 +1635,7 @@ export class CJSONRenderer extends ConvenienceRenderer { }); onFirst = false; } + this.emitLine("cJSON_free(x);"); }); }); @@ -1625,7 +1647,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param classType: class type * @param includes: Array of includes */ - protected emitClass(classType: ClassType, includes: string[]): void { + protected emitClass (classType: ClassType, includes: string[]): void { /* Create file */ const className = this.nameForNamedType(classType); const filename = this.sourcelikeToString(className).concat(".h"); @@ -1652,7 +1674,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Function called to create class typedef * @param classType: class type */ - protected emitClassTypedef(classType: ClassType): void { + protected emitClassTypedef (classType: ClassType): void { const className = this.nameForNamedType(classType); this.emitDescription(this.descriptionForType(classType)); @@ -1668,12 +1690,12 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.optionalQualifier, " ", name, - ";" + ";", ); }); }, "", - true + true, ); this.ensureBlankLine(); this.emitTypdefAlias(classType, className); @@ -1683,7 +1705,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Function called to create class prototypes * @param classType: class type */ - protected emitClassPrototypes(classType: ClassType): void { + protected emitClassPrototypes (classType: ClassType): void { const className = this.nameForNamedType(classType); this.emitLine("struct ", className, " * cJSON_Parse", className, "(", this.withConst("char"), " * s);"); @@ -1698,7 +1720,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Function called to create class functions * @param classType: class type */ - protected emitClassFunctions(classType: ClassType): void { + protected emitClassFunctions (classType: ClassType): void { const className = this.nameForNamedType(classType); /* Create string to className generator function */ @@ -1714,7 +1736,7 @@ export class CJSONRenderer extends ConvenienceRenderer { }); }); this.emitLine("return x;"); - } + }, ); this.ensureBlankLine(); @@ -1746,7 +1768,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level2.toString(), ", sizeof(", cJSON.items!.cType, - " *));" + " *));", ); } else if (cJSON.cjsonType === "cJSON_Map") { /* Not supported */ @@ -1761,7 +1783,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.cType, " *)0xDEADBEEF, sizeof(", cJSON.cType, - " *));" + " *));", ); } else if (cJSON.cjsonType === "cJSON_String") { this.emitLine( @@ -1773,7 +1795,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ")), sizeof(", cJSON.cType, - " *));" + " *));", ); } else if ( cJSON.cjsonType === "cJSON_Object" || @@ -1788,7 +1810,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "), sizeof(", cJSON.cType, - " *));" + " *));", ); } else { this.emitLine( @@ -1797,7 +1819,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", " = cJSON_malloc(sizeof(", cJSON.cType, - "));" + "));", ); this.emitBlock( ["if (NULL != tmp", level > 0 ? level.toString() : "", ")"], @@ -1809,7 +1831,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.getValue, "(e", child_level.toString(), - ");" + ");", ); this.emitLine( "list_add_tail(x", @@ -1818,12 +1840,12 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", ", sizeof(", cJSON.cType, - " *));" + " *));", ); - } + }, ); } - } + }, ); }); } else if (type instanceof ClassType) { @@ -1832,23 +1854,23 @@ export class CJSONRenderer extends ConvenienceRenderer { this.emitBlock( !cJSON.isNullable ? [ - "if (cJSON_HasObjectItem(j", - level > 0 ? level.toString() : "", - ', "', - jsonName, - '"))' - ] + "if (cJSON_HasObjectItem(j", + level > 0 ? level.toString() : "", + ", \"", + jsonName, + "\"))", + ] : [ - "if ((cJSON_HasObjectItem(j", - level > 0 ? level.toString() : "", - ', "', - jsonName, - '")) && (!cJSON_IsNull(cJSON_GetObjectItemCaseSensitive(j', - level > 0 ? level.toString() : "", - ', "', - jsonName, - '"))))' - ], + "if ((cJSON_HasObjectItem(j", + level > 0 ? level.toString() : "", + ", \"", + jsonName, + "\")) && (!cJSON_IsNull(cJSON_GetObjectItemCaseSensitive(j", + level > 0 ? level.toString() : "", + ", \"", + jsonName, + "\"))))", + ], () => { if (cJSON.cjsonType === "cJSON_Array" && cJSON.items !== undefined) { const child_level = level + 1; @@ -1856,7 +1878,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.cType, " * x", child_level.toString(), - " = list_create(false, NULL);" + " = list_create(false, NULL);", ); this.emitBlock(["if (NULL != x", child_level.toString(), ")"], () => { this.emitLine("cJSON * e", child_level.toString(), " = NULL;"); @@ -1865,9 +1887,9 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), " = cJSON_GetObjectItemCaseSensitive(j", level > 0 ? level.toString() : "", - ', "', + ", \"", jsonName, - '");' + "\");", ); this.emitBlock( [ @@ -1875,14 +1897,14 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ", j", child_level.toString(), - ")" + ")", ], () => { const add = ( type: Type, cJSON: TypeCJSON, level: number, - child_level: number + child_level: number, ) => { if (cJSON.items!.cjsonType === "cJSON_Array") { if (type instanceof ArrayType) { @@ -1895,7 +1917,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level2.toString(), ", sizeof(", cJSON.items!.cType, - " *));" + " *));", ); } else { panic("Invalid type"); @@ -1913,7 +1935,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.cType, " *)0xDEADBEEF, sizeof(", cJSON.items!.cType, - " *));" + " *));", ); } else if (cJSON.items!.cjsonType === "cJSON_String") { this.emitLine( @@ -1925,7 +1947,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ")), sizeof(", cJSON.items!.cType, - " *));" + " *));", ); } else if ( cJSON.items!.cjsonType === "cJSON_Object" || @@ -1940,7 +1962,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "), sizeof(", cJSON.items!.cType, - " *));" + " *));", ); } else { this.emitLine( @@ -1949,13 +1971,13 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", " = cJSON_malloc(sizeof(", cJSON.items!.cType, - "));" + "));", ); this.emitBlock( [ "if (NULL != tmp", level > 0 ? level.toString() : "", - ")" + ")", ], () => { this.emitLine( @@ -1965,7 +1987,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.getValue, "(e", child_level.toString(), - ");" + ");", ); this.emitLine( "list_add_tail(x", @@ -1974,34 +1996,35 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", ", sizeof(", cJSON.items!.cType, - " *));" + " *));", ); - } + }, ); } }; + if (cJSON.items!.isNullable) { this.emitBlock( [ "if (!cJSON_IsNull(e", child_level.toString(), - "))" + "))", ], () => { add(property.type, cJSON, level, child_level); - } + }, ); this.emitBlock(["else"], () => { this.emitLine( "list_add_tail(x", child_level.toString(), - ", (void *)0xDEADBEEF, sizeof(void *));" + ", (void *)0xDEADBEEF, sizeof(void *));", ); }); } else { add(property.type, cJSON, level, child_level); } - } + }, ); this.emitLine( "x", @@ -2010,7 +2033,7 @@ export class CJSONRenderer extends ConvenienceRenderer { name, " = x", child_level.toString(), - ";" + ";", ); }); } else if (cJSON.cjsonType === "cJSON_Map" && cJSON.items !== undefined) { @@ -2021,7 +2044,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), " = hashtable_create(", this.hashtableSize, - ", false);" + ", false);", ); this.emitBlock(["if (NULL != x", child_level.toString(), ")"], () => { this.emitLine("cJSON * e", child_level.toString(), " = NULL;"); @@ -2030,9 +2053,9 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), " = cJSON_GetObjectItemCaseSensitive(j", level > 0 ? level.toString() : "", - ', "', + ", \"", jsonName, - '");' + "\");", ); this.emitBlock( [ @@ -2040,14 +2063,14 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ", j", child_level.toString(), - ")" + ")", ], () => { const add = ( type: Type, cJSON: TypeCJSON, level: number, - child_level: number + child_level: number, ) => { if (cJSON.items!.cjsonType === "cJSON_Array") { if (type instanceof MapType) { @@ -2062,7 +2085,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level2.toString(), ", sizeof(", cJSON.items!.cType, - " *));" + " *));", ); } else { panic("Invalid type"); @@ -2082,7 +2105,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.cType, " *)0xDEADBEEF, sizeof(", cJSON.items!.cType, - " *));" + " *));", ); } else if (cJSON.items!.cjsonType === "cJSON_String") { this.emitLine( @@ -2096,7 +2119,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ")), sizeof(", cJSON.items!.cType, - " *));" + " *));", ); } else if ( cJSON.items!.cjsonType === "cJSON_Object" || @@ -2113,7 +2136,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "), sizeof(", cJSON.items!.cType, - " *));" + " *));", ); } else { this.emitLine( @@ -2122,13 +2145,13 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", " = cJSON_malloc(sizeof(", cJSON.items!.cType, - "));" + "));", ); this.emitBlock( [ "if (NULL != tmp", level > 0 ? level.toString() : "", - ")" + ")", ], () => { this.emitLine( @@ -2138,7 +2161,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.getValue, "(e", child_level.toString(), - ");" + ");", ); this.emitLine( "hashtable_add(x", @@ -2149,22 +2172,23 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", ", sizeof(", cJSON.items!.cType, - " *));" + " *));", ); - } + }, ); } }; + if (cJSON.items!.isNullable) { this.emitBlock( [ "if (!cJSON_IsNull(e", child_level.toString(), - "))" + "))", ], () => { add(property.type, cJSON, level, child_level); - } + }, ); this.emitBlock(["else"], () => { this.emitLine( @@ -2172,13 +2196,13 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ", e", child_level.toString(), - "->string, (void *)0xDEADBEEF, sizeof(void *));" + "->string, (void *)0xDEADBEEF, sizeof(void *));", ); }); } else { add(property.type, cJSON, level, child_level); } - } + }, ); this.emitLine( "x", @@ -2187,7 +2211,7 @@ export class CJSONRenderer extends ConvenienceRenderer { name, " = x", child_level.toString(), - ";" + ";", ); }); } else if ( @@ -2201,7 +2225,7 @@ export class CJSONRenderer extends ConvenienceRenderer { name, " = (", cJSON.cType, - " *)0xDEADBEEF;" + " *)0xDEADBEEF;", ); } else if (cJSON.cjsonType === "cJSON_String") { this.emitLine( @@ -2213,9 +2237,9 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.getValue, "(cJSON_GetObjectItemCaseSensitive(j", level > 0 ? level.toString() : "", - ', "', + ", \"", jsonName, - '")));' + "\")));", ); } else if ( cJSON.cjsonType === "cJSON_Object" || @@ -2230,9 +2254,9 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.getValue, "(cJSON_GetObjectItemCaseSensitive(j", level > 0 ? level.toString() : "", - ', "', + ", \"", jsonName, - '"));' + "\"));", ); } else { if (property.isOptional || cJSON.isNullable) { @@ -2244,7 +2268,7 @@ export class CJSONRenderer extends ConvenienceRenderer { name, " = cJSON_malloc(sizeof(", cJSON.cType, - "))))" + "))))", ], () => { this.emitLine( @@ -2256,11 +2280,11 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.getValue, "(cJSON_GetObjectItemCaseSensitive(j", level > 0 ? level.toString() : "", - ', "', + ", \"", jsonName, - '"));' + "\"));", ); - } + }, ); } else { this.emitLine( @@ -2272,13 +2296,13 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.getValue, "(cJSON_GetObjectItemCaseSensitive(j", level > 0 ? level.toString() : "", - ', "', + ", \"", jsonName, - '"));' + "\"));", ); } } - } + }, ); if (!property.isOptional && !cJSON.isNullable) { if (cJSON.cjsonType === "cJSON_Array") { @@ -2288,7 +2312,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->", name, - " = list_create(false, NULL);" + " = list_create(false, NULL);", ); }); } else if (cJSON.cjsonType === "cJSON_Map") { @@ -2300,7 +2324,7 @@ export class CJSONRenderer extends ConvenienceRenderer { name, " = hashtable_create(", this.hashtableSize, - ", false);" + ", false);", ); }); } else if ( @@ -2315,7 +2339,7 @@ export class CJSONRenderer extends ConvenienceRenderer { name, " = (", cJSON.cType, - " *)0xDEADBEEF;" + " *)0xDEADBEEF;", ); }); } else if (cJSON.cjsonType === "cJSON_String") { @@ -2328,7 +2352,7 @@ export class CJSONRenderer extends ConvenienceRenderer { name, " = cJSON_malloc(sizeof(", cJSON.cType, - "))))" + "))))", ], () => { this.emitLine( @@ -2336,9 +2360,9 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->", name, - "[0] = '\\0';" + "[0] = '\\0';", ); - } + }, ); }); } else { @@ -2348,11 +2372,12 @@ export class CJSONRenderer extends ConvenienceRenderer { }); } }; + recur(classType, 0); }); }); this.emitLine("return x;"); - } + }, ); this.ensureBlankLine(); @@ -2375,7 +2400,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), " = list_get_head(x", level.toString(), - ");" + ");", ); this.emitBlock(["while (NULL != x", child_level.toString(), ")"], () => { if (cJSON.cjsonType === "cJSON_Array") { @@ -2386,7 +2411,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ", j", child_level2.toString(), - ");" + ");", ); } else if (cJSON.cjsonType === "cJSON_Map") { /* Not supported */ @@ -2398,7 +2423,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ", ", cJSON.createObject, - "());" + "());", ); } else if ( cJSON.cjsonType === "cJSON_String" || @@ -2412,7 +2437,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.createObject, "(x", child_level.toString(), - "));" + "));", ); } else { this.emitLine( @@ -2422,15 +2447,16 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.createObject, "(*x", child_level.toString(), - "));" + "));", ); } + this.emitLine( "x", child_level.toString(), " = list_get_next(x", level.toString(), - ");" + ");", ); }); }); @@ -2447,9 +2473,9 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), " = cJSON_AddArrayToObject(j", level > 0 ? level.toString() : "", - ', "', + ", \"", jsonName, - '");' + "\");", ); this.emitBlock(["if (NULL != j", child_level.toString(), ")"], () => { this.emitLine( @@ -2460,7 +2486,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->", name, - ");" + ");", ); this.emitBlock( ["while (NULL != x", child_level.toString(), ")"], @@ -2468,7 +2494,7 @@ export class CJSONRenderer extends ConvenienceRenderer { const add = ( type: Type, cJSON: TypeCJSON, - child_level: number + child_level: number, ) => { if (cJSON.items!.cjsonType === "cJSON_Array") { if (type instanceof ArrayType) { @@ -2479,7 +2505,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ", j", child_level2.toString(), - ");" + ");", ); } else { panic("Invalid type"); @@ -2494,7 +2520,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ", ", cJSON.items!.createObject, - "());" + "());", ); } else if ( cJSON.items!.cjsonType === "cJSON_String" || @@ -2508,7 +2534,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.createObject, "(x", child_level.toString(), - "));" + "));", ); } else { this.emitLine( @@ -2518,31 +2544,33 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.createObject, "(*x", child_level.toString(), - "));" + "));", ); } }; + if (cJSON.items!.isNullable) { this.emitBlock( [ "if ((void *)0xDEADBEEF != x", child_level.toString(), - ")" + ")", ], () => { add(property.type, cJSON, child_level); - } + }, ); this.emitBlock(["else"], () => { this.emitLine( "cJSON_AddItemToArray(j", child_level.toString(), - ", cJSON_CreateNull());" + ", cJSON_CreateNull());", ); }); } else { add(property.type, cJSON, child_level); } + this.emitLine( "x", child_level.toString(), @@ -2550,12 +2578,12 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->", name, - ");" + ");", ); - } + }, ); }); - } + }, ); } else if (cJSON.cjsonType === "cJSON_Map" && cJSON.items !== undefined) { const child_level = level + 1; @@ -2567,7 +2595,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), " = ", cJSON.createObject, - "();" + "();", ); this.emitBlock(["if (NULL != j", child_level.toString(), ")"], () => { this.emitLine("char **keys", child_level.toString(), " = NULL;"); @@ -2580,7 +2608,7 @@ export class CJSONRenderer extends ConvenienceRenderer { name, ", &keys", child_level.toString(), - ");" + ");", ); this.emitBlock( ["if (NULL != keys", child_level.toString(), ")"], @@ -2595,7 +2623,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "; index", child_level.toString(), - "++)" + "++)", ], () => { this.emitLine( @@ -2610,12 +2638,12 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "[index", child_level.toString(), - "]);" + "]);", ); const add = ( type: Type, cJSON: TypeCJSON, - child_level: number + child_level: number, ) => { if (cJSON.items!.cjsonType === "cJSON_Array") { if (type instanceof MapType) { @@ -2631,7 +2659,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "], j", child_level2.toString(), - ");" + ");", ); } else { panic("Invalid type"); @@ -2657,7 +2685,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "], ", cJSON.items!.createObject, - "());" + "());", ); } else if ( cJSON.items!.cjsonType === "cJSON_String" || @@ -2676,7 +2704,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.createObject, "(x", child_level.toString(), - "));" + "));", ); } else { this.emitLine( @@ -2691,20 +2719,21 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.createObject, "(*x", child_level.toString(), - "));" + "));", ); } }; + if (cJSON.items!.isNullable) { this.emitBlock( [ "if ((void *)0xDEADBEEF != x", child_level.toString(), - ")" + ")", ], () => { add(property.type, cJSON, child_level); - } + }, ); this.emitBlock(["else"], () => { this.emitLine( @@ -2715,33 +2744,33 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "[index", child_level.toString(), - "], cJSON_CreateNull());" + "], cJSON_CreateNull());", ); }); } else { add(property.type, cJSON, child_level); } - } + }, ); this.emitLine( "cJSON_free(keys", child_level.toString(), - ");" + ");", ); - } + }, ); this.emitLine( cJSON.addToObject, "(j", level > 0 ? level.toString() : "", - ', "', + ", \"", jsonName, - '", j', + "\", j", child_level.toString(), - ");" + ");", ); }); - } + }, ); } else if (cJSON.cjsonType === "cJSON_Invalid") { /* Nothing to do */ @@ -2754,20 +2783,20 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.addToObject, "(j", level > 0 ? level.toString() : "", - ', "', + ", \"", jsonName, - '");' + "\");", ); - } + }, ); } else { this.emitLine( cJSON.addToObject, "(j", level > 0 ? level.toString() : "", - ', "', + ", \"", jsonName, - '");' + "\");", ); } } else if (cJSON.cjsonType === "cJSON_String") { @@ -2778,15 +2807,15 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.addToObject, "(j", level > 0 ? level.toString() : "", - ', "', + ", \"", jsonName, - '", x', + "\", x", level > 0 ? level.toString() : "", "->", name, - ");" + ");", ); - } + }, ); if (!property.isOptional && !cJSON.isNullable) { this.emitBlock(["else"], () => { @@ -2794,9 +2823,9 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.addToObject, "(j", level > 0 ? level.toString() : "", - ', "', + ", \"", jsonName, - '", "");' + "\", \"\");", ); }); } @@ -2812,32 +2841,32 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.addToObject, "(j", level > 0 ? level.toString() : "", - ', "', + ", \"", jsonName, - '", ', + "\", ", cJSON.createObject, "(x", level > 0 ? level.toString() : "", "->", name, - "));" + "));", ); - } + }, ); } else { this.emitLine( cJSON.addToObject, "(j", level > 0 ? level.toString() : "", - ', "', + ", \"", jsonName, - '", ', + "\", ", cJSON.createObject, "(x", level > 0 ? level.toString() : "", "->", name, - "));" + "));", ); } } else if (cJSON.cjsonType === "cJSON_Enum") { @@ -2849,32 +2878,32 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.addToObject, "(j", level > 0 ? level.toString() : "", - ', "', + ", \"", jsonName, - '", ', + "\", ", cJSON.createObject, "(*x", level > 0 ? level.toString() : "", "->", name, - "));" + "));", ); - } + }, ); } else { this.emitLine( cJSON.addToObject, "(j", level > 0 ? level.toString() : "", - ', "', + ", \"", jsonName, - '", ', + "\", ", cJSON.createObject, "(x", level > 0 ? level.toString() : "", "->", name, - "));" + "));", ); } } else { @@ -2886,50 +2915,52 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.addToObject, "(j", level > 0 ? level.toString() : "", - ', "', + ", \"", jsonName, - '", *x', + "\", *x", level > 0 ? level.toString() : "", "->", name, - ");" + ");", ); - } + }, ); } else { this.emitLine( cJSON.addToObject, "(j", level > 0 ? level.toString() : "", - ', "', + ", \"", jsonName, - '", x', + "\", x", level > 0 ? level.toString() : "", "->", name, - ");" + ");", ); } } + if (cJSON.isNullable) { this.emitBlock(["else"], () => { this.emitLine( "cJSON_AddNullToObject(j", level > 0 ? level.toString() : "", - ', "', + ", \"", jsonName, - '");' + "\");", ); }); } }); } }; + recur(classType, 0); }); }); this.emitLine("return j;"); - } + }, ); this.ensureBlankLine(); @@ -2960,7 +2991,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), " = list_get_head(x", level.toString(), - ");" + ");", ); this.emitBlock(["while (NULL != x", child_level.toString(), ")"], () => { if (cJSON.cjsonType === "cJSON_Array") { @@ -2973,6 +3004,7 @@ export class CJSONRenderer extends ConvenienceRenderer { } else { this.emitLine(cJSON.deleteType, "(x", child_level.toString(), ");"); } + this.emitLine("x", child_level.toString(), " = list_get_next(x", level.toString(), ");"); }); } else if (type instanceof ClassType) { @@ -2991,7 +3023,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->", name, - ");" + ");", ); this.emitBlock(["while (NULL != x", child_level.toString(), ")"], () => { if (cJSON.items!.cjsonType === "cJSON_Array") { @@ -3001,7 +3033,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.deleteType, "(x", child_level.toString(), - ");" + ");", ); } else { panic("Invalid type"); @@ -3022,19 +3054,20 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.deleteType, "(x", child_level.toString(), - ");" + ");", ); - } + }, ); } else { this.emitLine( cJSON.items!.deleteType, "(x", child_level.toString(), - ");" + ");", ); } } + this.emitLine( "x", child_level.toString(), @@ -3042,7 +3075,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->", name, - ");" + ");", ); }); this.emitLine( @@ -3051,9 +3084,9 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->", name, - ");" + ");", ); - } + }, ); } else if (cJSON.cjsonType === "cJSON_Map" && cJSON.items !== undefined) { const child_level = level + 1; @@ -3070,7 +3103,7 @@ export class CJSONRenderer extends ConvenienceRenderer { name, ", &keys", child_level.toString(), - ");" + ");", ); this.emitBlock(["if (NULL != keys", child_level.toString(), ")"], () => { this.emitBlock( @@ -3083,7 +3116,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "; index", child_level.toString(), - "++)" + "++)", ], () => { this.emitLine( @@ -3098,7 +3131,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "[index", child_level.toString(), - "]);" + "]);", ); this.emitBlock( ["if (NULL != x", child_level.toString(), ")"], @@ -3110,7 +3143,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.deleteType, "(x", child_level.toString(), - ");" + ");", ); } else { panic("Invalid type"); @@ -3128,29 +3161,29 @@ export class CJSONRenderer extends ConvenienceRenderer { [ "if ((void *)0xDEADBEEF != x", child_level.toString(), - ")" + ")", ], () => { this.emitLine( cJSON.items!.deleteType, "(x", child_level.toString(), - ");" + ");", ); - } + }, ); } else { this.emitLine( cJSON.items!.deleteType, "(x", child_level.toString(), - ");" + ");", ); } } - } + }, ); - } + }, ); this.emitLine("cJSON_free(keys", child_level.toString(), ");"); }); @@ -3160,9 +3193,9 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->", name, - ");" + ");", ); - } + }, ); } else if (cJSON.cjsonType === "cJSON_Invalid" || cJSON.cjsonType === "cJSON_NULL") { /* Nothing to do */ @@ -3180,9 +3213,9 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->", name, - ");" + ");", ); - } + }, ); } else { if (property.isOptional || cJSON.isNullable) { @@ -3195,15 +3228,16 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->", name, - ");" + ");", ); - } + }, ); } } }); } }; + recur(classType, 0); this.emitLine("cJSON_free(x);"); }); @@ -3217,7 +3251,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param className: top level class name * @param includes: Array of includes */ - protected emitTopLevel(type: Type, className: Name, includes: string[]): void { + protected emitTopLevel (type: Type, className: Name, includes: string[]): void { /* Create file */ const filename = this.sourcelikeToString(className).concat(".h"); this.startFile(filename); @@ -3246,7 +3280,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param type: type of the top level element * @param className: top level class name */ - protected emitTopLevelTypedef(type: Type, className: Name): void { + protected emitTopLevelTypedef (type: Type, className: Name): void { this.emitBlock( ["struct ", className], () => { @@ -3255,11 +3289,11 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.cType, cJSON.optionalQualifier !== "" ? " " : "", cJSON.optionalQualifier, - " value;" + " value;", ); }, "", - true + true, ); this.ensureBlankLine(); this.emitTypdefAlias(type, className); @@ -3270,7 +3304,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param type: type of the top level element * @param className: top level class name */ - protected emitTopLevelPrototypes(_type: Type, className: Name): void { + protected emitTopLevelPrototypes (_type: Type, className: Name): void { this.emitLine("struct ", className, " * cJSON_Parse", className, "(", this.withConst("char"), " * s);"); this.emitLine("struct ", className, " * cJSON_Get", className, "Value(", this.withConst("cJSON"), " * j);"); this.emitLine("cJSON * cJSON_Create", className, "(", this.withConst(["struct ", className]), " * x);"); @@ -3284,7 +3318,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param type: type of the top level element * @param className: top level class name */ - protected emitTopLevelFunctions(type: Type, className: Name): void { + protected emitTopLevelFunctions (type: Type, className: Name): void { /* Create string to className generator function */ this.emitBlock( ["struct ", className, " * cJSON_Parse", className, "(", this.withConst("char"), " * s)"], @@ -3298,7 +3332,7 @@ export class CJSONRenderer extends ConvenienceRenderer { }); }); this.emitLine("return x;"); - } + }, ); this.ensureBlankLine(); @@ -3330,7 +3364,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.cType, " *)0xDEADBEAF, sizeof(", cJSON.items!.cType, - " *));" + " *));", ); } else if (cJSON.items!.cjsonType === "cJSON_String") { this.emitLine( @@ -3338,7 +3372,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.getValue, "(e)), sizeof(", cJSON.items!.cType, - " *));" + " *));", ); } else { this.emitLine( @@ -3346,17 +3380,18 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.getValue, "(e), sizeof(", cJSON.items!.cType, - " *));" + " *));", ); } }; + if (cJSON.items!.isNullable) { this.emitBlock(["if (!cJSON_IsNull(e))"], () => { add(cJSON); }); this.emitBlock(["else"], () => { this.emitLine( - "list_add_tail(x->value, (void *)0xDEADBEEF, sizeof(void *));" + "list_add_tail(x->value, (void *)0xDEADBEEF, sizeof(void *));", ); }); } else { @@ -3383,7 +3418,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.cType, " *)0xDEADBEEF, sizeof(", cJSON.items!.cType, - " *));" + " *));", ); } else if (cJSON.items!.cjsonType === "cJSON_String") { this.emitLine( @@ -3391,7 +3426,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.getValue, "(e)), sizeof(", cJSON.items!.cType, - " *));" + " *));", ); } else { this.emitLine( @@ -3399,17 +3434,18 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.getValue, "(e), sizeof(", cJSON.items!.cType, - " *));" + " *));", ); } }; + if (cJSON.items!.isNullable) { this.emitBlock(["if (!cJSON_IsNull(e))"], () => { add(cJSON); }); this.emitBlock(["else"], () => { this.emitLine( - "hashtable_add(x->value, e->string, (void *)0xDEADBEEF, sizeof(void *));" + "hashtable_add(x->value, e->string, (void *)0xDEADBEEF, sizeof(void *));", ); }); } else { @@ -3429,7 +3465,7 @@ export class CJSONRenderer extends ConvenienceRenderer { }); }); this.emitLine("return x;"); - } + }, ); this.ensureBlankLine(); @@ -3457,7 +3493,7 @@ export class CJSONRenderer extends ConvenienceRenderer { this.emitLine( "cJSON_AddItemToArray(j, ", cJSON.items!.createObject, - "());" + "());", ); } else if ( cJSON.items!.cjsonType === "cJSON_String" || @@ -3467,16 +3503,17 @@ export class CJSONRenderer extends ConvenienceRenderer { this.emitLine( "cJSON_AddItemToArray(j, ", cJSON.items!.createObject, - "(x1));" + "(x1));", ); } else { this.emitLine( "cJSON_AddItemToArray(j, ", cJSON.items!.createObject, - "(*x1));" + "(*x1));", ); } }; + if (cJSON.items!.isNullable) { this.emitBlock(["if ((void *)0xDEADBEEF != x1)"], () => { add(cJSON); @@ -3487,6 +3524,7 @@ export class CJSONRenderer extends ConvenienceRenderer { } else { add(cJSON); } + this.emitLine("x1 = list_get_next(x->value);"); }); }); @@ -3501,7 +3539,7 @@ export class CJSONRenderer extends ConvenienceRenderer { this.emitBlock(["for (size_t index = 0; index < count; index++)"], () => { this.emitLine( cJSON.items!.cType, - " *x2 = hashtable_lookup(x->value, keys[index]);" + " *x2 = hashtable_lookup(x->value, keys[index]);", ); const add = (cJSON: TypeCJSON) => { if (cJSON.items!.cjsonType === "cJSON_Array") { @@ -3515,7 +3553,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.addToObject, "(j, keys[index], ", cJSON.items!.createObject, - "());" + "());", ); } else if ( cJSON.items!.cjsonType === "cJSON_String" || @@ -3526,17 +3564,18 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.addToObject, "(j, keys[index], ", cJSON.items!.createObject, - "(x2));" + "(x2));", ); } else { this.emitLine( cJSON.addToObject, "(j, keys[index], ", cJSON.items!.createObject, - "(*x2));" + "(*x2));", ); } }; + if (cJSON.items!.isNullable) { this.emitBlock(["if ((void *)0xDEADBEEF != x2)"], () => { add(cJSON); @@ -3544,7 +3583,7 @@ export class CJSONRenderer extends ConvenienceRenderer { this.emitBlock(["else"], () => { this.emitLine( cJSON.addToObject, - "(j, keys[index], cJSON_CreateNull());" + "(j, keys[index], cJSON_CreateNull());", ); }); } else { @@ -3564,7 +3603,7 @@ export class CJSONRenderer extends ConvenienceRenderer { } }); this.emitLine("return j;"); - } + }, ); this.ensureBlankLine(); @@ -3597,6 +3636,7 @@ export class CJSONRenderer extends ConvenienceRenderer { } else { this.emitLine(cJSON.items!.deleteType, "(x1);"); } + this.emitLine("x1 = list_get_next(x->value);"); }); this.emitLine(cJSON.deleteType, "(x->value);"); @@ -3633,6 +3673,7 @@ export class CJSONRenderer extends ConvenienceRenderer { } else { /* Nothing to do */ } + this.emitLine("cJSON_free(x);"); }); }); @@ -3646,7 +3687,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param isNullable: true if the field is nullable * @return cJSON type */ - protected quicktypeTypeToCJSON(t: Type, isOptional: boolean, isNullable = false): TypeCJSON { + protected quicktypeTypeToCJSON (t: Type, isOptional: boolean, isNullable = false): TypeCJSON { /* Compute cJSON type */ return matchType( t, @@ -3661,7 +3702,7 @@ export class CJSONRenderer extends ConvenienceRenderer { createObject: "", deleteType: "", items: undefined, - isNullable + isNullable, }; }, _nullType => { @@ -3675,7 +3716,7 @@ export class CJSONRenderer extends ConvenienceRenderer { createObject: "cJSON_CreateNull", deleteType: "cJSON_free", items: undefined, - isNullable + isNullable, }; }, _boolType => { @@ -3689,7 +3730,7 @@ export class CJSONRenderer extends ConvenienceRenderer { createObject: "cJSON_CreateBool", deleteType: "cJSON_free", items: undefined, - isNullable + isNullable, }; }, _integerType => { @@ -3703,7 +3744,7 @@ export class CJSONRenderer extends ConvenienceRenderer { createObject: "cJSON_CreateNumber", deleteType: "cJSON_free", items: undefined, - isNullable + isNullable, }; }, _doubleType => { @@ -3717,7 +3758,7 @@ export class CJSONRenderer extends ConvenienceRenderer { createObject: "cJSON_CreateNumber", deleteType: "cJSON_free", items: undefined, - isNullable + isNullable, }; }, _stringType => { @@ -3731,7 +3772,7 @@ export class CJSONRenderer extends ConvenienceRenderer { createObject: "cJSON_CreateString", deleteType: "cJSON_free", items: undefined, - isNullable + isNullable, }; }, arrayType => { @@ -3746,7 +3787,7 @@ export class CJSONRenderer extends ConvenienceRenderer { createObject: "cJSON_CreateArray", deleteType: "list_release", items, - isNullable + isNullable, }; }, classType => { @@ -3760,7 +3801,7 @@ export class CJSONRenderer extends ConvenienceRenderer { createObject: ["cJSON_Create", this.nameForNamedType(classType)], deleteType: ["cJSON_Delete", this.nameForNamedType(classType)], items: undefined, - isNullable + isNullable, }; }, mapType => { @@ -3775,7 +3816,7 @@ export class CJSONRenderer extends ConvenienceRenderer { createObject: "cJSON_CreateObject", deleteType: "hashtable_release", items, - isNullable + isNullable, }; }, enumType => { @@ -3789,7 +3830,7 @@ export class CJSONRenderer extends ConvenienceRenderer { createObject: ["cJSON_Create", this.nameForNamedType(enumType)], deleteType: "cJSON_free", items: undefined, - isNullable + isNullable, }; }, unionType => { @@ -3807,10 +3848,10 @@ export class CJSONRenderer extends ConvenienceRenderer { createObject: ["cJSON_Create", this.nameForNamedType(unionType)], deleteType: ["cJSON_Delete", this.nameForNamedType(unionType)], items: undefined, - isNullable + isNullable, }; } - } + }, ); } @@ -3818,7 +3859,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Function called to create a file * @param proposedFilename: source filename provided from stdin */ - protected startFile(proposedFilename: Sourcelike): void { + protected startFile (proposedFilename: Sourcelike): void { /* Check if previous file is closed, create a new file */ assert(this.currentFilename === undefined, "Previous file wasn't finished"); if (proposedFilename !== undefined) { @@ -3836,7 +3877,7 @@ export class CJSONRenderer extends ConvenienceRenderer { "To get json data from cJSON object use the following: struct * data = cJSON_GetValue();", "To get cJSON object from json data use the following: cJSON * cjson = cJSON_Create();", "To print json string from json data use the following: char * string = cJSON_Print();", - "To delete json data use the following: cJSON_Delete();" + "To delete json data use the following: cJSON_Delete();", ]); this.ensureBlankLine(); @@ -3844,18 +3885,18 @@ export class CJSONRenderer extends ConvenienceRenderer { this.emitLine( "#ifndef __", allUpperWordStyle(this.currentFilename.replace(new RegExp(/[^a-zA-Z0-9]+/, "g"), "_")), - "__" + "__", ); this.emitLine( "#define __", allUpperWordStyle(this.currentFilename.replace(new RegExp(/[^a-zA-Z0-9]+/, "g"), "_")), - "__" + "__", ); this.ensureBlankLine(); /* Write C++ guard */ this.emitLine("#ifdef __cplusplus"); - this.emitLine('extern "C" {'); + this.emitLine("extern \"C\" {"); this.emitLine("#endif"); this.ensureBlankLine(); @@ -3886,7 +3927,7 @@ export class CJSONRenderer extends ConvenienceRenderer { /** * Function called to close current file */ - protected finishFile(): void { + protected finishFile (): void { /* Check if file has been created */ if (this.currentFilename !== undefined) { /* Write C++ guard */ @@ -3899,7 +3940,7 @@ export class CJSONRenderer extends ConvenienceRenderer { this.emitLine( "#endif /* __", allUpperWordStyle(this.currentFilename.replace(new RegExp(/[^a-zA-Z0-9]+/, "g"), "_")), - "__ */" + "__ */", ); this.ensureBlankLine(); @@ -3914,7 +3955,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @note If returning true, canBeForwardDeclared must be declared * @return Always returns true */ - protected get needsTypeDeclarationBeforeUse(): boolean { + protected get needsTypeDeclarationBeforeUse (): boolean { return true; } @@ -3922,7 +3963,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Check if type can be forward declared * @return true for classes, false otherwise */ - protected canBeForwardDeclared(type: Type): boolean { + protected canBeForwardDeclared (type: Type): boolean { return type.kind === "class"; } @@ -3930,7 +3971,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Add const to wanted Sourcelike * @return Const Sourcelike */ - protected withConst(s: Sourcelike): Sourcelike { + protected withConst (s: Sourcelike): Sourcelike { return ["const ", s]; } @@ -3939,15 +3980,15 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param name: filename to include * @pram global: true if global include, false otherwise (default) */ - protected emitIncludeLine(name: Sourcelike, global = false): void { - this.emitLine("#include ", global ? "<" : '"', name, global ? ">" : '"'); + protected emitIncludeLine (name: Sourcelike, global = false): void { + this.emitLine("#include ", global ? "<" : "\"", name, global ? ">" : "\""); } /** * Emit description block * @param lines: description block lines */ - protected emitDescriptionBlock(lines: Sourcelike[]): void { + protected emitDescriptionBlock (lines: Sourcelike[]): void { this.emitCommentLines(lines, { lineStart: " * ", beforeComment: "/**", afterComment: " */" }); } @@ -3959,12 +4000,12 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param withSemicolon: true to add semicolon at the end of the block, false otherwise * @param withIndent: true to indent the block (default), false otherwise */ - protected emitBlock( + protected emitBlock ( line: Sourcelike, f: () => void, withName = "", withSemicolon = false, - withIndent = true + withIndent = true, ): void { this.emitLine(line, " {"); this.preventBlankLine(); @@ -3973,6 +4014,7 @@ export class CJSONRenderer extends ConvenienceRenderer { } else { f(); } + this.preventBlankLine(); if (withSemicolon) { if (withName !== "") { @@ -3994,7 +4036,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param type: class, union or enum type * @param filename: current file name */ - protected emitIncludes(type: ClassType | UnionType | EnumType, filename: string): void { + protected emitIncludes (type: ClassType | UnionType | EnumType, filename: string): void { /* List required includes */ const includes: IncludeMap = new Map(); if (type instanceof UnionType) { @@ -4014,6 +4056,7 @@ export class CJSONRenderer extends ConvenienceRenderer { } }); } + this.ensureBlankLine(); } @@ -4023,7 +4066,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param includes: include map * @param propertyType: property type */ - protected updateIncludes(isClassMember: boolean, includes: IncludeMap, propertyType: Type): void { + protected updateIncludes (isClassMember: boolean, includes: IncludeMap, propertyType: Type): void { const propTypes = this.generatedTypes(isClassMember, propertyType); for (const t of propTypes) { const typeName = this.sourcelikeToString(t.name); @@ -4054,6 +4097,7 @@ export class CJSONRenderer extends ConvenienceRenderer { } } } + if (includes.has(typeName)) { const incKind = includes.get(typeName); /* If we already include the type as typed include, do not write it over with forward declare */ @@ -4072,7 +4116,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param type: type * @return Type record array */ - protected generatedTypes(isClassMember: boolean, type: Type): TypeRecord[] { + protected generatedTypes (isClassMember: boolean, type: Type): TypeRecord[] { const result: TypeRecord[] = []; const recur = (forceInclude: boolean, isVariant: boolean, l: number, t: Type) => { if (t instanceof ArrayType) { @@ -4083,7 +4127,7 @@ export class CJSONRenderer extends ConvenienceRenderer { type: t, level: l, variant: isVariant, - forceInclude + forceInclude, }); } else if (t instanceof MapType) { recur(forceInclude, isVariant, l + 1, t.values); @@ -4093,7 +4137,7 @@ export class CJSONRenderer extends ConvenienceRenderer { type: t, level: l, variant: isVariant, - forceInclude: false + forceInclude: false, }); } else if (t instanceof UnionType) { /** @@ -4117,7 +4161,7 @@ export class CJSONRenderer extends ConvenienceRenderer { type: t, level: l, variant: true, - forceInclude + forceInclude, }); /** intentional "fall-through", add all subtypes as well - but forced include */ } @@ -4130,6 +4174,7 @@ export class CJSONRenderer extends ConvenienceRenderer { } } }; + recur(false, false, 0, type); return result; } diff --git a/packages/quicktype-core/src/language/CPlusPlus.ts b/packages/quicktype-core/src/language/CPlusPlus.ts index 5adff56d2..c486c7827 100644 --- a/packages/quicktype-core/src/language/CPlusPlus.ts +++ b/packages/quicktype-core/src/language/CPlusPlus.ts @@ -5,32 +5,39 @@ import { iterableFirst, iterableFind, iterableSome, - withDefault + withDefault, } from "collection-utils"; import { TargetLanguage } from "../TargetLanguage"; -import { Type, TypeKind, ClassType, ClassProperty, ArrayType, MapType, EnumType, UnionType } from "../Type"; +import { type Type, type TypeKind, type ClassProperty} from "../Type"; +import { ClassType, ArrayType, MapType, EnumType, UnionType } from "../Type"; import { nullableFromUnion, matchType, removeNullFromUnion, isNamedType, directlyReachableTypes } from "../TypeUtils"; -import { NameStyle, Name, Namer, funPrefixNamer, DependencyName } from "../Naming"; -import { Sourcelike, maybeAnnotated } from "../Source"; +import { type NameStyle, type Name, type Namer} from "../Naming"; +import { funPrefixNamer, DependencyName } from "../Naming"; +import { type Sourcelike} from "../Source"; +import { maybeAnnotated } from "../Source"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; +import { + type NamingStyle} from "../support/Strings"; import { legalizeCharacters, isAscii, isLetterOrUnderscoreOrDigit, stringEscape, - NamingStyle, - makeNameStyle + makeNameStyle, } from "../support/Strings"; import { defined, assertNever, panic, numberEnumValues } from "../support/Support"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { StringOption, EnumOption, BooleanOption, Option, getOptionValues, OptionValues } from "../RendererOptions"; +import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { ConvenienceRenderer } from "../ConvenienceRenderer"; +import { type Option, type OptionValues } from "../RendererOptions"; +import { StringOption, EnumOption, BooleanOption, getOptionValues } from "../RendererOptions"; import { assert } from "../support/Support"; -import { Declaration } from "../DeclarationIR"; -import { RenderContext } from "../Renderer"; +import { type Declaration } from "../DeclarationIR"; +import { type RenderContext } from "../Renderer"; import { getAccessorName } from "../attributes/AccessorNames"; import { enumCaseValues } from "../attributes/EnumValues"; -import { minMaxValueForType, minMaxLengthForType, patternForType, MinMaxConstraint } from "../attributes/Constraints"; +import { type MinMaxConstraint } from "../attributes/Constraints"; +import { minMaxValueForType, minMaxLengthForType, patternForType } from "../attributes/Constraints"; const pascalValue: [string, NamingStyle] = ["pascal-case", "pascal"]; const underscoreValue: [string, NamingStyle] = ["underscore-case", "underscore"]; @@ -45,47 +52,47 @@ export const cPlusPlusOptions = { "Source code generation type, whether to generate single or multiple source files", [ ["single-source", true], - ["multi-source", false] + ["multi-source", false], ], "single-source", - "secondary" + "secondary", ), includeLocation: new EnumOption( "include-location", "Whether json.hpp is to be located globally or locally", [ ["local-include", true], - ["global-include", false] + ["global-include", false], ], "local-include", - "secondary" + "secondary", ), codeFormat: new EnumOption( "code-format", "Generate classes with getters/setters, instead of structs", [ ["with-struct", false], - ["with-getter-setter", true] + ["with-getter-setter", true], ], - "with-getter-setter" + "with-getter-setter", ), wstring: new EnumOption( "wstring", "Store strings using Utf-16 std::wstring, rather than Utf-8 std::string", [ ["use-string", false], - ["use-wstring", true] + ["use-wstring", true], ], - "use-string" + "use-string", ), westConst: new EnumOption( "const-style", "Put const to the left/west (const T) or right/east (T const)", [ ["west-const", true], - ["east-const", false] + ["east-const", false], ], - "west-const" + "west-const", ), justTypes: new BooleanOption("just-types", "Plain types only", false), namespace: new StringOption("namespace", "Name of the generated namespace(s)", "NAME", "quicktype"), @@ -96,7 +103,7 @@ export const cPlusPlusOptions = { camelValue, upperUnderscoreValue, pascalUpperAcronymsValue, - camelUpperAcronymsValue + camelUpperAcronymsValue, ]), memberNamingStyle: new EnumOption("member-style", "Naming style for members", [ underscoreValue, @@ -104,7 +111,7 @@ export const cPlusPlusOptions = { camelValue, upperUnderscoreValue, pascalUpperAcronymsValue, - camelUpperAcronymsValue + camelUpperAcronymsValue, ]), enumeratorNamingStyle: new EnumOption("enumerator-style", "Naming style for enumerators", [ upperUnderscoreValue, @@ -112,18 +119,18 @@ export const cPlusPlusOptions = { pascalValue, camelValue, pascalUpperAcronymsValue, - camelUpperAcronymsValue + camelUpperAcronymsValue, ]), boost: new BooleanOption("boost", "Require a dependency on boost. Without boost, C++17 is required", true), - hideNullOptional: new BooleanOption("hide-null-optional", "Hide null value for optional field", false) + hideNullOptional: new BooleanOption("hide-null-optional", "Hide null value for optional field", false), }; export class CPlusPlusTargetLanguage extends TargetLanguage { - constructor(displayName = "C++", names: string[] = ["c++", "cpp", "cplusplus"], extension = "cpp") { + constructor (displayName = "C++", names: string[] = ["c++", "cpp", "cplusplus"], extension = "cpp") { super(displayName, names, extension); } - protected getOptions(): Option[] { + protected getOptions (): Array> { return [ cPlusPlusOptions.justTypes, cPlusPlusOptions.namespace, @@ -137,33 +144,33 @@ export class CPlusPlusTargetLanguage extends TargetLanguage { cPlusPlusOptions.enumeratorNamingStyle, cPlusPlusOptions.enumType, cPlusPlusOptions.boost, - cPlusPlusOptions.hideNullOptional + cPlusPlusOptions.hideNullOptional, ]; } - get supportsUnionsWithBothNumberTypes(): boolean { + get supportsUnionsWithBothNumberTypes (): boolean { return true; } - get supportsOptionalClassProperties(): boolean { + get supportsOptionalClassProperties (): boolean { return true; } - protected makeRenderer( + protected makeRenderer ( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } + untypedOptionValues: { [name: string]: any, }, ): CPlusPlusRenderer { return new CPlusPlusRenderer(this, renderContext, getOptionValues(cPlusPlusOptions, untypedOptionValues)); } } -function constraintsForType(t: Type): - | { - minMax?: MinMaxConstraint; - minMaxLength?: MinMaxConstraint; - pattern?: string; - } - | undefined { +function constraintsForType (t: Type): +| { + minMax?: MinMaxConstraint, + minMaxLength?: MinMaxConstraint, + pattern?: string, +} +| undefined { const minMax = minMaxValueForType(t); const minMaxLength = minMaxLengthForType(t); const pattern = patternForType(t); @@ -273,7 +280,7 @@ const keywords = [ "final", "transaction_safe", "transaction_safe_dynamic", - "NULL" + "NULL", ]; /// Type to use as an optional if cycle breaking is required @@ -326,26 +333,26 @@ export enum MemberNames { SetPattern } -type ConstraintMember = { - name: MemberNames; +interface ConstraintMember { + cppConstType?: string; + cppType: string; getter: MemberNames; + name: MemberNames; setter: MemberNames; - cppType: string; - cppConstType?: string; -}; +} -export type IncludeRecord = { +export interface IncludeRecord { kind: IncludeKind | undefined /** How to include that */; typeKind: TypeKind | undefined /** What exactly to include */; -}; +} -export type TypeRecord = { +export interface TypeRecord { + forceInclude: boolean; + level: number; name: Name; type: Type; - level: number; variant: boolean; - forceInclude: boolean; -}; +} /** * We map each and every unique type to a include kind, e.g. how @@ -353,57 +360,65 @@ export type TypeRecord = { */ export type IncludeMap = Map; -export type TypeContext = { +export interface TypeContext { + inJsonNamespace: boolean; needsForwardIndirection: boolean; needsOptionalIndirection: boolean; - inJsonNamespace: boolean; -}; +} interface StringType { - getType(): string; - getConstType(): string; - getSMatch(): string; - getRegex(): string; - createStringLiteral(inner: Sourcelike): Sourcelike; - wrapToString(inner: Sourcelike): Sourcelike; - wrapEncodingChange( + createStringLiteral: (inner: Sourcelike) => Sourcelike; + emitHelperFunctions: () => void; + getConstType: () => string; + getRegex: () => string; + getSMatch: () => string; + getType: () => string; + wrapEncodingChange: ( qualifier: Sourcelike[], fromType: Sourcelike, toType: Sourcelike, inner: Sourcelike - ): Sourcelike; - emitHelperFunctions(): void; + ) => Sourcelike; + wrapToString: (inner: Sourcelike) => Sourcelike; } -function addQualifier(qualifier: Sourcelike, qualified: Sourcelike[]): Sourcelike[] { +function addQualifier (qualifier: Sourcelike, qualified: Sourcelike[]): Sourcelike[] { if (qualified.length === 0) { return []; } + return [qualifier, qualified]; } class WrappingCode { - constructor( + constructor ( private readonly start: Sourcelike[], - private readonly end: Sourcelike[] + private readonly end: Sourcelike[], ) {} - wrap(qualifier: Sourcelike, inner: Sourcelike): Sourcelike { + wrap (qualifier: Sourcelike, inner: Sourcelike): Sourcelike { return [addQualifier(qualifier, this.start), inner, this.end]; } } class BaseString { public _stringType: string; + public _constStringType: string; + public _smatch: string; + public _regex: string; + public _stringLiteralPrefix: string; + public _toString: WrappingCode; + public _encodingClass: Sourcelike; + public _encodingFunction: Sourcelike; - constructor( + constructor ( stringType: string, constStringType: string, smatch: string, @@ -411,7 +426,7 @@ class BaseString { stringLiteralPrefix: string, toString: WrappingCode, encodingClass: string, - encodingFunction: string + encodingFunction: string, ) { this._stringType = stringType; this._constStringType = constStringType; @@ -423,27 +438,27 @@ class BaseString { this._encodingFunction = encodingFunction; } - public getType(): string { + public getType (): string { return this._stringType; } - public getConstType(): string { + public getConstType (): string { return this._constStringType; } - public getSMatch(): string { + public getSMatch (): string { return this._smatch; } - public getRegex(): string { + public getRegex (): string { return this._regex; } - public createStringLiteral(inner: Sourcelike): Sourcelike { - return [this._stringLiteralPrefix, '"', inner, '"']; + public createStringLiteral (inner: Sourcelike): Sourcelike { + return [this._stringLiteralPrefix, "\"", inner, "\""]; } - public wrapToString(inner: Sourcelike): Sourcelike { + public wrapToString (inner: Sourcelike): Sourcelike { return this._toString.wrap([], inner); } } @@ -455,31 +470,48 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { private readonly _enumType: string; private readonly _generatedFiles: Set; + private _currentFilename: string | undefined; + private _allTypeNames: Set; + private readonly _gettersAndSettersForPropertyName = new Map(); - private readonly _namespaceNames: ReadonlyArray; + + private readonly _namespaceNames: readonly string[]; + private readonly _memberNameStyle: NameStyle; + private readonly _namedTypeNameStyle: NameStyle; + private readonly _generatedGlobalNames: Map; + private readonly _generatedMemberNames: Map; + private readonly _forbiddenGlobalNames: string[]; + private readonly _memberNamingFunction: Namer; + private readonly _stringType: StringType; + /// The type to use as an optional (std::optional or std::shared) private readonly _optionalType: string; + private readonly _optionalFactory: string; + private readonly _nulloptType: string; + private readonly _variantType: string; + private readonly _variantIndexMethodName: string; protected readonly typeNamingStyle: NamingStyle; + protected readonly enumeratorNamingStyle: NamingStyle; - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues + private readonly _options: OptionValues, ) { super(targetLanguage, renderContext); @@ -524,14 +556,14 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } // union typeguard - isUnion(t: Type | UnionType): t is UnionType { + isUnion (t: Type | UnionType): t is UnionType { return t.kind === "union"; } // Returns true if the type can be stored in // a stack based optional type. This requires // that the type does not require forward declaration. - isOptionalAsValuePossible(t: Type): boolean { + isOptionalAsValuePossible (t: Type): boolean { if (this.isForwardDeclaredType(t)) return false; if (this.isUnion(t)) { @@ -589,182 +621,184 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { return !this.isCycleBreakerType(tt); } } + return !this.isCycleBreakerType(t); } - isImplicitCycleBreaker(t: Type): boolean { + isImplicitCycleBreaker (t: Type): boolean { const kind = t.kind; return kind === "array" || kind === "map"; } // Is likely to return std::optional or boost::optional - optionalTypeStack(): string { + optionalTypeStack (): string { return this._optionalType; } // Is likely to return std::make_optional or boost::optional - optionalFactoryStack(): string { + optionalFactoryStack (): string { return this._optionalFactory; } // Is likely to return std::shared_ptr - optionalTypeHeap(): string { + optionalTypeHeap (): string { return optionalAsSharedType; } // Is likely to return std::make_shared - optionalFactoryHeap(): string { + optionalFactoryHeap (): string { return optionalFactoryAsSharedType; } // Returns the optional type most suitable for the given type. // Classes that don't require forward declarations can be stored // in std::optional ( or boost::optional ) - optionalType(t: Type): string { + optionalType (t: Type): string { if (this.isOptionalAsValuePossible(t)) return this.optionalTypeStack(); else return this.optionalTypeHeap(); } // Returns a label that can be used to distinguish between // heap and stack based optional handling methods - optionalTypeLabel(t: Type): string { + optionalTypeLabel (t: Type): string { if (this.isOptionalAsValuePossible(t)) return "stack"; else return "heap"; } - protected getConstraintMembers(): ConstraintMember[] { + protected getConstraintMembers (): ConstraintMember[] { return [ { name: MemberNames.MinIntValue, getter: MemberNames.GetMinIntValue, setter: MemberNames.SetMinIntValue, - cppType: "int64_t" + cppType: "int64_t", }, { name: MemberNames.MaxIntValue, getter: MemberNames.GetMaxIntValue, setter: MemberNames.SetMaxIntValue, - cppType: "int64_t" + cppType: "int64_t", }, { name: MemberNames.MinDoubleValue, getter: MemberNames.GetMinDoubleValue, setter: MemberNames.SetMinDoubleValue, - cppType: "double" + cppType: "double", }, { name: MemberNames.MaxDoubleValue, getter: MemberNames.GetMaxDoubleValue, setter: MemberNames.SetMaxDoubleValue, - cppType: "double" + cppType: "double", }, { name: MemberNames.MinLength, getter: MemberNames.GetMinLength, setter: MemberNames.SetMinLength, - cppType: "size_t" + cppType: "size_t", }, { name: MemberNames.MaxLength, getter: MemberNames.GetMaxLength, setter: MemberNames.SetMaxLength, - cppType: "size_t" + cppType: "size_t", }, { name: MemberNames.Pattern, getter: MemberNames.GetPattern, setter: MemberNames.SetPattern, cppType: this._stringType.getType(), - cppConstType: this._stringType.getConstType() - } + cppConstType: this._stringType.getConstType(), + }, ]; } - protected lookupGlobalName(type: GlobalNames): string { + protected lookupGlobalName (type: GlobalNames): string { return defined(this._generatedGlobalNames.get(type)); } - protected lookupMemberName(type: MemberNames): string { + protected lookupMemberName (type: MemberNames): string { return defined(this._generatedMemberNames.get(type)); } - protected addGlobalName(type: GlobalNames): void { + protected addGlobalName (type: GlobalNames): void { const genName = this._namedTypeNameStyle(GlobalNames[type]); this._generatedGlobalNames.set(type, genName); this._forbiddenGlobalNames.push(genName); } - protected addMemberName(type: MemberNames): void { + protected addMemberName (type: MemberNames): void { this._generatedMemberNames.set(type, this._memberNameStyle(MemberNames[type])); } - protected setupGlobalNames(): void { + protected setupGlobalNames (): void { for (const v of numberEnumValues(GlobalNames)) { this.addGlobalName(v); } + for (const v of numberEnumValues(MemberNames)) { this.addMemberName(v); } } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace (): string[] { return [...keywords, ...this._forbiddenGlobalNames]; } - protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties (_c: ClassType, _className: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { + protected forbiddenForEnumCases (_e: EnumType, _enumName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected makeNamedTypeNamer(): Namer { + protected makeNamedTypeNamer (): Namer { return funPrefixNamer("types", this._namedTypeNameStyle); } - protected namerForObjectProperty(): Namer { + protected namerForObjectProperty (): Namer { return this._memberNamingFunction; } - protected makeUnionMemberNamer(): null { + protected makeUnionMemberNamer (): null { return null; } - protected makeEnumCaseNamer(): Namer { + protected makeEnumCaseNamer (): Namer { return funPrefixNamer("enumerators", makeNameStyle(this.enumeratorNamingStyle, legalizeName)); } - protected makeNamesForPropertyGetterAndSetter( + protected makeNamesForPropertyGetterAndSetter ( _c: ClassType, _className: Name, _p: ClassProperty, _jsonName: string, - name: Name + name: Name, ): [Name, Name, Name] { const getterName = new DependencyName(this._memberNamingFunction, name.order, lookup => `get_${lookup(name)}`); const mutableGetterName = new DependencyName( this._memberNamingFunction, name.order, - lookup => `getMutable_${lookup(name)}` + lookup => `getMutable_${lookup(name)}`, ); const setterName = new DependencyName(this._memberNamingFunction, name.order, lookup => `set_${lookup(name)}`); return [getterName, mutableGetterName, setterName]; } - protected makePropertyDependencyNames( + protected makePropertyDependencyNames ( c: ClassType, className: Name, p: ClassProperty, jsonName: string, - name: Name + name: Name, ): Name[] { const getterAndSetterNames = this.makeNamesForPropertyGetterAndSetter(c, className, p, jsonName, name); this._gettersAndSettersForPropertyName.set(name, getterAndSetterNames); return getterAndSetterNames; } - protected withConst(s: Sourcelike): Sourcelike { + protected withConst (s: Sourcelike): Sourcelike { if (this._options.westConst) { return ["const ", s]; } else { @@ -772,11 +806,11 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } - protected emitInclude(global: boolean, name: Sourcelike): void { - this.emitLine("#include ", global ? "<" : '"', name, global ? ">" : '"'); + protected emitInclude (global: boolean, name: Sourcelike): void { + this.emitLine("#include ", global ? "<" : "\"", name, global ? ">" : "\""); } - protected startFile(basename: Sourcelike, includeHelper = true): void { + protected startFile (basename: Sourcelike, includeHelper = true): void { assert(this._currentFilename === undefined, "Previous file wasn't finished"); if (basename !== undefined) { this._currentFilename = this.sourcelikeToString(basename); @@ -789,11 +823,12 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { if (this._options.boost) { this.emitCommentLines([" Boost http://www.boost.org"]); } + this.emitCommentLines([ " json.hpp https://github.com/nlohmann/json", "", " Then include this file, and then do", - "" + "", ]); if (this._options.typeSourceStyle) { @@ -803,6 +838,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } else { this.emitLine("// ", basename, " data = nlohmann::json::parse(jsonString);"); } + if (this._options.wstring) { this.emitLine("//"); this.emitLine("// You can get std::wstring data back out using"); @@ -812,6 +848,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { }); } } + this.ensureBlankLine(); this.emitLine("#pragma once"); @@ -824,6 +861,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.emitInclude(true, "optional"); } } + if (this.haveNamedUnions) { if (this._options.boost) { this.emitInclude(true, "boost/variant.hpp"); @@ -831,6 +869,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.emitInclude(true, "variant"); } } + if (!this._options.justTypes) { if (!this._options.includeLocation) { this.emitInclude(true, "nlohmann/json.hpp"); @@ -842,28 +881,29 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.emitInclude(false, "helper.hpp"); } } + this.ensureBlankLine(); } - protected finishFile(): void { + protected finishFile (): void { super.finishFile(defined(this._currentFilename)); this._currentFilename = undefined; } - protected get needsTypeDeclarationBeforeUse(): boolean { + protected get needsTypeDeclarationBeforeUse (): boolean { return true; } - protected canBeForwardDeclared(t: Type): boolean { + protected canBeForwardDeclared (t: Type): boolean { const kind = t.kind; return kind === "class"; } - protected emitDescriptionBlock(lines: Sourcelike[]): void { + protected emitDescriptionBlock (lines: Sourcelike[]): void { this.emitCommentLines(lines, { lineStart: " * ", beforeComment: "/**", afterComment: " */" }); } - protected emitBlock(line: Sourcelike, withSemicolon: boolean, f: () => void, withIndent = true): void { + protected emitBlock (line: Sourcelike, withSemicolon: boolean, f: () => void, withIndent = true): void { this.emitLine(line, " {"); this.preventBlankLine(); if (withIndent) { @@ -871,6 +911,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } else { f(); } + this.preventBlankLine(); if (withSemicolon) { this.emitLine("};"); @@ -879,7 +920,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } - protected emitNamespaces(namespaceNames: Iterable, f: () => void): void { + protected emitNamespaces (namespaceNames: Iterable, f: () => void): void { const namesArray = toReadonlyArray(namespaceNames); const first = namesArray[0]; if (first === undefined) { @@ -889,43 +930,46 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { ["namespace ", first], false, () => this.emitNamespaces(namesArray.slice(1), f), - namesArray.length === 1 + namesArray.length === 1, ); } } - protected cppTypeInOptional( + protected cppTypeInOptional ( nonNulls: ReadonlySet, ctx: TypeContext, withIssues: boolean, - forceNarrowString: boolean + forceNarrowString: boolean, ): Sourcelike { if (nonNulls.size === 1) { return this.cppType(defined(iterableFirst(nonNulls)), ctx, withIssues, forceNarrowString, false); } + const typeList: Sourcelike = []; for (const t of nonNulls) { if (typeList.length !== 0) { typeList.push(", "); } + typeList.push( this.cppType( t, { needsForwardIndirection: true, needsOptionalIndirection: false, - inJsonNamespace: ctx.inJsonNamespace + inJsonNamespace: ctx.inJsonNamespace, }, withIssues, false, - false - ) + false, + ), ); } + return [this._variantType, "<", typeList, ">"]; } - protected variantType(u: UnionType, inJsonNamespace: boolean): Sourcelike { + protected variantType (u: UnionType, inJsonNamespace: boolean): Sourcelike { const [maybeNull, nonNulls] = removeNullFromUnion(u, true); assert(nonNulls.size >= 2, "Variant not needed for less than two types."); const indirection = maybeNull !== null; @@ -934,36 +978,37 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: !indirection, needsOptionalIndirection: !indirection, - inJsonNamespace + inJsonNamespace, }, true, - false + false, ); if (!indirection) { return variant; } + return [this.optionalType(u), "<", variant, ">"]; } - protected ourQualifier(inJsonNamespace: boolean): Sourcelike { + protected ourQualifier (inJsonNamespace: boolean): Sourcelike { return inJsonNamespace ? [arrayIntercalate("::", this._namespaceNames), "::"] : []; } - protected jsonQualifier(inJsonNamespace: boolean): Sourcelike { + protected jsonQualifier (inJsonNamespace: boolean): Sourcelike { return inJsonNamespace ? [] : "nlohmann::"; } - protected variantIndirection(type: Type, needIndirection: boolean, typeSrc: Sourcelike): Sourcelike { + protected variantIndirection (type: Type, needIndirection: boolean, typeSrc: Sourcelike): Sourcelike { if (!needIndirection) return typeSrc; return [this.optionalType(type), "<", typeSrc, ">"]; } - protected cppType( + protected cppType ( t: Type, ctx: TypeContext, withIssues: boolean, forceNarrowString: boolean, - isOptional: boolean + isOptional: boolean, ): Sourcelike { const inJsonNamespace = ctx.inJsonNamespace; if (isOptional && t instanceof UnionType) { @@ -975,20 +1020,21 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } } + const typeSource = matchType( t, _anyType => { isOptional = false; return maybeAnnotated(withIssues, anyTypeIssueAnnotation, [ this.jsonQualifier(inJsonNamespace), - "json" + "json", ]); }, _nullType => { isOptional = false; return maybeAnnotated(withIssues, nullTypeIssueAnnotation, [ this.jsonQualifier(inJsonNamespace), - "json" + "json", ]); }, _boolType => "bool", @@ -1008,25 +1054,26 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: false, needsOptionalIndirection: true, - inJsonNamespace + inJsonNamespace, }, withIssues, forceNarrowString, - false + false, ), - ">" + ">", ], classType => this.variantIndirection( classType, ctx.needsForwardIndirection && this.isForwardDeclaredType(classType) && !isOptional, - [this.ourQualifier(inJsonNamespace), this.nameForNamedType(classType)] + [this.ourQualifier(inJsonNamespace), this.nameForNamedType(classType)], ), mapType => { let keyType = this._stringType.getType(); if (forceNarrowString) { keyType = "std::string"; } + return [ "std::map<", keyType, @@ -1036,13 +1083,13 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: false, needsOptionalIndirection: true, - inJsonNamespace + inJsonNamespace, }, withIssues, forceNarrowString, - false + false, ), - ">" + ">", ]; }, enumType => [this.ourQualifier(inJsonNamespace), this.nameForNamedType(enumType)], @@ -1055,16 +1102,16 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: false, needsOptionalIndirection: false, - inJsonNamespace + inJsonNamespace, }, withIssues, forceNarrowString, - false + false, ); } else { return [this.ourQualifier(inJsonNamespace), this.nameForNamedType(unionType)]; } - } + }, ); if (!isOptional) return typeSource; return [this.optionalType(t), "<", typeSource, ">"]; @@ -1074,7 +1121,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { * similar to cppType, it practically gathers all the generated types within * 't'. It also records, whether a given sub-type is part of a variant or not. */ - protected generatedTypes(isClassMember: boolean, theType: Type): TypeRecord[] { + protected generatedTypes (isClassMember: boolean, theType: Type): TypeRecord[] { const result: TypeRecord[] = []; const recur = (forceInclude: boolean, isVariant: boolean, l: number, t: Type) => { if (t instanceof ArrayType) { @@ -1085,7 +1132,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { type: t, level: l, variant: isVariant, - forceInclude + forceInclude, }); } else if (t instanceof MapType) { recur(true, isVariant, l + 1, t.values); @@ -1095,7 +1142,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { type: t, level: l, variant: isVariant, - forceInclude: false + forceInclude: false, }); } else if (t instanceof UnionType) { /** @@ -1119,7 +1166,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { type: t, level: l, variant: true, - forceInclude + forceInclude, }); /** intentional "fall-through", add all subtypes as well - but forced include */ } @@ -1132,19 +1179,20 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } }; + recur(false, false, 0, theType); return result; } - protected constraintMember(jsonName: string): string { + protected constraintMember (jsonName: string): string { return this._memberNameStyle(`${jsonName}Constraint`); } - protected emitMember(cppType: Sourcelike, name: Sourcelike): void { + protected emitMember (cppType: Sourcelike, name: Sourcelike): void { this.emitLine(cppType, " ", name, ";"); } - protected emitClassMembers(c: ClassType, constraints: Map | undefined): void { + protected emitClassMembers (c: ClassType, constraints: Map | undefined): void { if (this._options.codeFormat) { this.emitLine("private:"); @@ -1155,13 +1203,13 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false + inJsonNamespace: false, }, true, false, - property.isOptional + property.isOptional, ), - name + name, ); if (constraints?.has(jsonName)) { /** FIXME!!! NameStyle will/can collide with other Names */ @@ -1183,28 +1231,28 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false + inJsonNamespace: false, }, true, false, - property.isOptional + property.isOptional, ), - name + name, ); } else { const [getterName, mutableGetterName, setterName] = defined( - this._gettersAndSettersForPropertyName.get(name) + this._gettersAndSettersForPropertyName.get(name), ); const rendered = this.cppType( property.type, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false + inJsonNamespace: false, }, true, false, - property.isOptional + property.isOptional, ); /** @@ -1214,8 +1262,8 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { */ const checkConst = this.lookupGlobalName(GlobalNames.CheckConstraint); if ( - (property.type instanceof UnionType && property.type.findMember("null") !== undefined) || - (property.isOptional && property.type.kind !== "null" && property.type.kind !== "any") + property.type instanceof UnionType && property.type.findMember("null") !== undefined || + property.isOptional && property.type.kind !== "null" && property.type.kind !== "any" ) { this.emitLine(rendered, " ", getterName, "() const { return ", name, "; }"); if (constraints?.has(jsonName)) { @@ -1232,7 +1280,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.constraintMember(jsonName), ", *value); this->", name, - " = value; }" + " = value; }", ); } else { this.emitLine("void ", setterName, "(", rendered, " value) { this->", name, " = value; }"); @@ -1254,7 +1302,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.constraintMember(jsonName), ", value); this->", name, - " = value; }" + " = value; }", ); } else { this.emitLine( @@ -1264,16 +1312,17 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.withConst(rendered), " & value) { this->", name, - " = value; }" + " = value; }", ); } } + this.ensureBlankLine(); } }); } - protected generateClassConstraints(c: ClassType): Map | undefined { + protected generateClassConstraints (c: ClassType): Map | undefined { const res: Map = new Map(); this.forEachClassProperty(c, "none", (_name, jsonName, property) => { const constraints = constraintsForType(property.type); @@ -1286,11 +1335,11 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false + inJsonNamespace: false, }, true, false, - property.isOptional + property.isOptional, ); res.set(jsonName, [ @@ -1311,19 +1360,19 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { pattern === undefined ? this._nulloptType : [ - this._stringType.getType(), - "(", - this._stringType.createStringLiteral([stringEscape(pattern)]), - ")" - ], - ")" + this._stringType.getType(), + "(", + this._stringType.createStringLiteral([stringEscape(pattern)]), + ")", + ], + ")", ]); }); return res.size === 0 ? undefined : res; } - protected emitClass(c: ClassType, className: Name): void { + protected emitClass (c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); this.emitBlock([this._options.codeFormat ? "class " : "struct ", className], true, () => { const constraints = this.generateClassConstraints(c); @@ -1355,7 +1404,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { }); } - protected emitTopLevelHeaders(t: Type, className: Name): void { + protected emitTopLevelHeaders (t: Type, className: Name): void { // Forward declarations for std::map (need to convert UTF16 <-> UTF8) if (t instanceof MapType && this._stringType !== this.NarrowString) { const ourQualifier = this.ourQualifier(true); @@ -1368,21 +1417,21 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { " & j, ", ourQualifier, className, - " & x);" + " & x);", ); this.emitLine("static void to_json(json & j, ", this.withConst([ourQualifier, className]), " & x);"); }); } } - protected emitClassHeaders(className: Name): void { + protected emitClassHeaders (className: Name): void { const ourQualifier = this.ourQualifier(false); this.emitLine("void from_json(", this.withConst("json"), " & j, ", ourQualifier, className, " & x);"); this.emitLine("void to_json(json & j, ", this.withConst([ourQualifier, className]), " & x);"); } - protected emitTopLevelFunction(t: Type, className: Name): void { + protected emitTopLevelFunction (t: Type, className: Name): void { // Function definitions for std::map (need to convert UTF16 <-> UTF8) if (t instanceof MapType && this._stringType !== this.NarrowString) { const ourQualifier = this.ourQualifier(true); @@ -1399,7 +1448,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { " & j, ", ourQualifier, className, - "& x)" + "& x)", ], false, () => { @@ -1408,22 +1457,22 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true + inJsonNamespace: true, }, false, true, - false + false, ); toType = this.cppType( t, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true + inJsonNamespace: true, }, false, false, - false + false, ); this.emitLine([ @@ -1431,11 +1480,11 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, [ "j.get<", cppType, - ">()" + ">()", ]), - ";" + ";", ]); - } + }, ); this.emitBlock( @@ -1445,7 +1494,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { className, ">::to_json(json & j, ", this.withConst([ourQualifier, className]), - " & x)" + " & x)", ], false, () => { @@ -1454,35 +1503,35 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true + inJsonNamespace: true, }, false, false, - false + false, ); toType = this.cppType( t, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true + inJsonNamespace: true, }, false, true, - false + false, ); this.emitLine([ "j = ", this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, "x"), - ";" + ";", ]); - } + }, ); } } - protected emitClassFunctions(c: ClassType, className: Name): void { + protected emitClassFunctions (c: ClassType, className: Name): void { const ourQualifier = this.ourQualifier(false); let cppType: Sourcelike; let toType: Sourcelike; @@ -1513,15 +1562,16 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { [ourQualifier], this._stringType.getType(), this.NarrowString.getType(), - [this._stringType.createStringLiteral([stringEscape(json)])] + [this._stringType.createStringLiteral([stringEscape(json)])], ), - ")" - ] + ")", + ], ), - ";" + ";", ); return; } + if (p.isOptional || propType instanceof UnionType) { const [nullOrOptional, typeSet] = (function (): [boolean, ReadonlySet] { if (propType instanceof UnionType) { @@ -1539,20 +1589,20 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: false, needsOptionalIndirection: false, - inJsonNamespace: false + inJsonNamespace: false, }, false, - true + true, ); toType = this.cppTypeInOptional( typeSet, { needsForwardIndirection: false, needsOptionalIndirection: false, - inJsonNamespace: false + inJsonNamespace: false, }, false, - false + false, ); this.emitLine( assignment.wrap( @@ -1571,39 +1621,40 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { [ourQualifier], this._stringType.getType(), this.NarrowString.getType(), - [this._stringType.createStringLiteral([stringEscape(json)])] + [this._stringType.createStringLiteral([stringEscape(json)])], ), - ")" - ] - ) - ] + ")", + ], + ), + ], ), - ";" + ";", ); return; } } + cppType = this.cppType( propType, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false + inJsonNamespace: false, }, false, true, - p.isOptional + p.isOptional, ); toType = this.cppType( propType, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false + inJsonNamespace: false, }, false, false, - p.isOptional + p.isOptional, ); this.emitLine( assignment.wrap( @@ -1614,17 +1665,17 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { [ourQualifier], this._stringType.getType(), this.NarrowString.getType(), - this._stringType.createStringLiteral([stringEscape(json)]) + this._stringType.createStringLiteral([stringEscape(json)]), ), ").get<", cppType, - ">()" - ]) + ">()", + ]), ), - ";" + ";", ); }); - } + }, ); this.ensureBlankLine(); @@ -1640,22 +1691,22 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false + inJsonNamespace: false, }, false, false, - p.isOptional + p.isOptional, ); toType = this.cppType( propType, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false + inJsonNamespace: false, }, false, true, - p.isOptional + p.isOptional, ); const [getterName, ,] = defined(this._gettersAndSettersForPropertyName.get(name)); let getter: Sourcelike[]; @@ -1664,39 +1715,40 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } else { getter = [name]; } + const assignment: Sourcelike[] = [ "j[", this._stringType.wrapEncodingChange( [ourQualifier], this._stringType.getType(), this.NarrowString.getType(), - this._stringType.createStringLiteral([stringEscape(json)]) + this._stringType.createStringLiteral([stringEscape(json)]), ), "] = ", this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, ["x.", getter]), - ";" + ";", ]; if (p.isOptional && this._options.hideNullOptional) { this.emitBlock( [ "if (", this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, ["x.", getter]), - ")" + ")", ], false, () => { this.emitLine(assignment); - } + }, ); } else { this.emitLine(assignment); } }); - } + }, ); } - protected emitEnum(e: EnumType, enumName: Name): void { + protected emitEnum (e: EnumType, enumName: Name): void { const caseNames: Sourcelike[] = []; const enumValues = enumCaseValues(e, this.targetLanguage.name); @@ -1715,11 +1767,11 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.emitLine("enum class ", enumName, " : ", this._enumType, " { ", caseNames, " };"); } - protected emitUnionTypedefs(u: UnionType, unionName: Name): void { + protected emitUnionTypedefs (u: UnionType, unionName: Name): void { this.emitLine("using ", unionName, " = ", this.variantType(u, false), ";"); } - protected emitUnionHeaders(u: UnionType): void { + protected emitUnionHeaders (u: UnionType): void { // Forward declarations for boost::variant. If none of the Ts were defined by us (e.g. if we have // boost::variant) then we need to specialize nlohmann::adl_serializer for our // variant type. If at least one of the Ts is our type then we could get away with regular adl definitions, @@ -1732,10 +1784,10 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: false, needsOptionalIndirection: false, - inJsonNamespace: true + inJsonNamespace: true, }, false, - false + false, ); this.emitLine("template <>"); @@ -1745,12 +1797,12 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { }); } - protected emitUnionFunctions(u: UnionType): void { + protected emitUnionFunctions (u: UnionType): void { // Function definitions for boost::variant. const ourQualifier = this.ourQualifier(true) as string; - const functionForKind: [string, string][] = [ + const functionForKind: Array<[string, string]> = [ ["bool", "is_boolean"], ["integer", "is_number_integer"], ["double", "is_number"], @@ -1758,7 +1810,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { ["class", "is_object"], ["map", "is_object"], ["array", "is_array"], - ["enum", "is_string"] + ["enum", "is_string"], ]; const nonNulls = removeNullFromUnion(u, true)[1]; const variantType = this.cppTypeInOptional( @@ -1766,10 +1818,10 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: false, needsOptionalIndirection: false, - inJsonNamespace: true + inJsonNamespace: true, }, false, - false + false, ); this.emitBlock( @@ -1780,7 +1832,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.withConst("json"), " & j, ", variantType, - " & x)" + " & x)", ], false, () => { @@ -1795,37 +1847,38 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true + inJsonNamespace: true, }, false, true, - false + false, ); const toType = this.cppType( typeForKind, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true + inJsonNamespace: true, }, false, false, - false + false, ); this.emitLine( "x = ", this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, [ "j.get<", cppType, - ">()" + ">()", ]), - ";" + ";", ); }); onFirst = false; } - this.emitLine('else throw std::runtime_error("Could not deserialise!");'); - } + + this.emitLine("else throw std::runtime_error(\"Could not deserialise!\");"); + }, ); this.ensureBlankLine(); @@ -1843,56 +1896,57 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true + inJsonNamespace: true, }, false, false, - false + false, ); const toType = this.cppType( t, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true + inJsonNamespace: true, }, false, true, - false + false, ); this.emitLine( "j = ", this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, [ this._options.boost ? "boost::get<" : "std::get<", cppType, - ">(x)" + ">(x)", ]), - ";" + ";", ); this.emitLine("break;"); }); i++; } - this.emitLine('default: throw std::runtime_error("Input JSON does not conform to schema!");'); + + this.emitLine("default: throw std::runtime_error(\"Input JSON does not conform to schema!\");"); }); - } + }, ); } - protected emitEnumHeaders(enumName: Name): void { + protected emitEnumHeaders (enumName: Name): void { const ourQualifier = this.ourQualifier(false); this.emitLine("void from_json(", this.withConst("json"), " & j, ", ourQualifier, enumName, " & x);"); this.emitLine("void to_json(json & j, ", this.withConst([ourQualifier, enumName]), " & x);"); } - private isLargeEnum(e: EnumType) { + private isLargeEnum (e: EnumType) { // This is just an estimation. Someone might want to do some // benchmarks to find the optimum value here return e.cases.size > 15; } - protected emitEnumFunctions(e: EnumType, enumName: Name): void { + protected emitEnumFunctions (e: EnumType, enumName: Name): void { const ourQualifier = this.ourQualifier(false); this.emitBlock( @@ -1907,7 +1961,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { ", ", ourQualifier, enumName, - "> enumValues" + "> enumValues", ], true, () => { @@ -1918,17 +1972,17 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { [ourQualifier], this._stringType.getType(), this.NarrowString.getType(), - [this._stringType.createStringLiteral([stringEscape(jsonName)])] + [this._stringType.createStringLiteral([stringEscape(jsonName)])], ), ", ", ourQualifier, enumName, "::", name, - "}," + "},", ); }); - } + }, ); this.emitLine(`auto iter = enumValues.find(j.get<${this._stringType.getType()}>());`); @@ -1946,20 +2000,20 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { [ourQualifier], this._stringType.getType(), this.NarrowString.getType(), - [this._stringType.createStringLiteral([stringEscape(jsonName)])] + [this._stringType.createStringLiteral([stringEscape(jsonName)])], ), ") x = ", ourQualifier, enumName, "::", name, - ";" + ";", ); onFirst = false; }); - this.emitLine('else { throw std::runtime_error("Input JSON does not conform to schema!"); }'); + this.emitLine("else { throw std::runtime_error(\"Input JSON does not conform to schema!\"); }"); } - } + }, ); this.ensureBlankLine(); @@ -1980,20 +2034,20 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { [ourQualifier], this._stringType.getType(), this.NarrowString.getType(), - [this._stringType.createStringLiteral([stringEscape(jsonName)])] + [this._stringType.createStringLiteral([stringEscape(jsonName)])], ), - "; break;" + "; break;", ); }); this.emitLine( - `default: throw std::runtime_error("Unexpected value in enumeration \\"${enumName}\\": " + std::to_string(static_cast(x)));` + `default: throw std::runtime_error("Unexpected value in enumeration \\"${enumName}\\": " + std::to_string(static_cast(x)));`, ); }); - } + }, ); } - protected emitTopLevelTypedef(t: Type, name: Name): void { + protected emitTopLevelTypedef (t: Type, name: Name): void { this.emitLine( "using ", name, @@ -2003,17 +2057,17 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false + inJsonNamespace: false, }, true, false, - false + false, ), - ";" + ";", ); } - protected emitAllUnionFunctions(): void { + protected emitAllUnionFunctions (): void { this.forEachUniqueUnion( "leading-and-interposing", u => @@ -2023,17 +2077,17 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: false, needsOptionalIndirection: false, - inJsonNamespace: true + inJsonNamespace: true, }, false, - false - ) + false, + ), ), - (u: UnionType) => this.emitUnionFunctions(u) + (u: UnionType) => this.emitUnionFunctions(u), ); } - protected emitAllUnionHeaders(): void { + protected emitAllUnionHeaders (): void { this.forEachUniqueUnion( "interposing", u => @@ -2043,17 +2097,17 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: false, needsOptionalIndirection: false, - inJsonNamespace: true + inJsonNamespace: true, }, false, - false - ) + false, + ), ), - (u: UnionType) => this.emitUnionHeaders(u) + (u: UnionType) => this.emitUnionHeaders(u), ); } - protected emitOptionalHelpers(): void { + protected emitOptionalHelpers (): void { this.emitLine("#ifndef NLOHMANN_OPT_HELPER"); this.emitLine("#define NLOHMANN_OPT_HELPER"); @@ -2066,7 +2120,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { false, () => { this.emitLine("if (!opt) j = nullptr; else j = *opt;"); - } + }, ); this.ensureBlankLine(); @@ -2076,12 +2130,13 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { false, () => { this.emitLine( - `if (j.is_null()) return ${factory}(); else return ${factory}(j.get());` + `if (j.is_null()) return ${factory}(); else return ${factory}(j.get());`, ); - } + }, ); }); }; + emitAdlStruct(this.optionalTypeHeap(), this.optionalFactoryHeap()); emitAdlStruct(this.optionalTypeStack(), this.optionalFactoryStack()); }); @@ -2089,7 +2144,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.emitLine("#endif"); } - protected emitDeclaration(decl: Declaration): void { + protected emitDeclaration (decl: Declaration): void { if (decl.kind === "forward") { if (this._options.codeFormat) { this.emitLine("class ", this.nameForNamedType(decl.type), ";"); @@ -2113,17 +2168,17 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } - protected emitGetterSetter(t: string, getterName: string, setterName: string, memberName: string): void { + protected emitGetterSetter (t: string, getterName: string, setterName: string, memberName: string): void { this.emitLine("void ", setterName, "(", t, " ", memberName, ") { this->", memberName, " = ", memberName, "; }"); this.emitLine("auto ", getterName, "() const { return ", memberName, "; }"); } - protected emitNumericCheckConstraints( + protected emitNumericCheckConstraints ( checkConst: string, classConstraint: string, getterMinValue: string, getterMaxValue: string, - cppType: string + cppType: string, ): void { this.emitBlock( [ @@ -2135,7 +2190,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.withConst(classConstraint), " & c, ", cppType, - " value)" + " value)", ], false, () => { @@ -2158,9 +2213,9 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this._stringType.wrapToString(["*c.", getterMinValue, "()"]), " + ", this._stringType.createStringLiteral([")"]), - ");" + ");", ); - } + }, ); this.ensureBlankLine(); @@ -2183,17 +2238,17 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this._stringType.wrapToString(["*c.", getterMaxValue, "()"]), " + ", this._stringType.createStringLiteral([")"]), - ");" + ");", ); - } + }, ); this.ensureBlankLine(); - } + }, ); this.ensureBlankLine(); } - protected emitConstraintClasses(): void { + protected emitConstraintClasses (): void { const ourQualifier = this.ourQualifier(false) as string; const getterMinIntValue = this.lookupMemberName(MemberNames.GetMinIntValue); @@ -2211,6 +2266,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { for (const member of constraintMembers) { this.emitMember([this._optionalType, "<", member.cppType, ">"], this.lookupMemberName(member.name)); } + this.ensureBlankLine(); this.emitLine("public:"); this.emitLine(classConstraint, "("); @@ -2235,7 +2291,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { withDefault(member.cppConstType, member.cppType), this.lookupMemberName(member.getter), this.lookupMemberName(member.setter), - this.lookupMemberName(member.name) + this.lookupMemberName(member.name), ); } }); @@ -2253,9 +2309,9 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { [ourQualifier], this._stringType.getType(), this.NarrowString.getType(), - ["msg"] + ["msg"], ), - ") {}" + ") {}", ); }); this.ensureBlankLine(); @@ -2265,7 +2321,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { GlobalNames.ValueTooHighException, GlobalNames.ValueTooShortException, GlobalNames.ValueTooLongException, - GlobalNames.InvalidPatternException + GlobalNames.InvalidPatternException, ]; for (const ex of exceptions) { @@ -2284,7 +2340,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { classConstraint, getterMinDoubleValue, getterMaxDoubleValue, - "double" + "double", ); this.emitBlock( @@ -2297,7 +2353,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.withConst(classConstraint), " & c, ", this._stringType.getConstType(), - " value)" + " value)", ], false, () => { @@ -2309,7 +2365,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this._nulloptType, " && value.length() < *c.", getterMinLength, - "())" + "())", ], false, () => { @@ -2328,9 +2384,9 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this._stringType.wrapToString(["*c.", getterMinLength, "()"]), " + ", this._stringType.createStringLiteral([")"]), - ");" + ");", ); - } + }, ); this.ensureBlankLine(); @@ -2342,7 +2398,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this._nulloptType, " && value.length() > *c.", getterMaxLength, - "())" + "())", ], false, () => { @@ -2361,9 +2417,9 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this._stringType.wrapToString(["*c.", getterMaxLength, "()"]), " + ", this._stringType.createStringLiteral([")"]), - ");" + ");", ); - } + }, ); this.ensureBlankLine(); @@ -2374,7 +2430,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this._stringType.getRegex(), "( *c.", getterPattern, - "() ));" + "() ));", ); this.emitBlock(["if (result.empty())"], false, () => { this.emitLine( @@ -2390,16 +2446,16 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { getterPattern, "() + ", this._stringType.createStringLiteral([")"]), - ");" + ");", ); }); }); this.ensureBlankLine(); - } + }, ); } - protected emitHelperFunctions(): void { + protected emitHelperFunctions (): void { this._stringType.emitHelperFunctions(); if ( @@ -2437,7 +2493,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.emitLine("return j.at(property).get();"); }); this.emitLine("return json();"); - } + }, ); this.ensureBlankLine(); @@ -2447,7 +2503,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { false, () => { this.emitLine("return get_untyped(j, property.data());"); - } + }, ); this.emitLine("#endif"); @@ -2470,7 +2526,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.withConst("json"), " & j, ", this.withConst("char"), - " * property)" + " * property)", ], false, () => { @@ -2479,7 +2535,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.emitLine("return j.at(property).get<", optionalType, ">();"); }); this.emitLine("return ", optionalType, "();"); - } + }, ); this.ensureBlankLine(); @@ -2491,14 +2547,15 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { optionalType, ` get_${label}_optional(`, this.withConst("json"), - " & j, std::string property)" + " & j, std::string property)", ], false, () => { this.emitLine(`return get_${label}_optional(j, property.data());`); - } + }, ); }; + emitGetOptional(this.optionalTypeHeap(), "heap"); emitGetOptional(this.optionalTypeStack(), "stack"); @@ -2508,7 +2565,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } - protected emitExtraIncludes(): void { + protected emitExtraIncludes (): void { this.ensureBlankLine(); if (this._options.codeFormat) { @@ -2517,6 +2574,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } else { this.emitInclude(true, "optional"); } + this.emitInclude(true, "stdexcept"); this.emitInclude(true, "regex"); } @@ -2534,7 +2592,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.ensureBlankLine(); } - protected emitHelper(): void { + protected emitHelper (): void { this.startFile("helper.hpp", false); this.emitExtraIncludes(); @@ -2555,35 +2613,36 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.finishFile(); } - protected emitTypes(): void { + protected emitTypes (): void { if (!this._options.justTypes) { this.emitLine("using nlohmann::json;"); this.ensureBlankLine(); this.emitHelperFunctions(); } + this.forEachDeclaration("interposing", decl => this.emitDeclaration(decl)); if (this._options.justTypes) return; this.forEachTopLevel( "leading", (t: Type, name: Name) => this.emitTopLevelTypedef(t, name), - t => this.namedTypeToNameForTopLevel(t) === undefined + t => this.namedTypeToNameForTopLevel(t) === undefined, ); } - protected gatherUserNamespaceForwardDecls(): Sourcelike[] { + protected gatherUserNamespaceForwardDecls (): Sourcelike[] { return this.gatherSource(() => { this.forEachObject("leading-and-interposing", (_: any, className: Name) => - this.emitClassHeaders(className) + this.emitClassHeaders(className), ); this.forEachEnum("leading-and-interposing", (_: any, enumName: Name) => this.emitEnumHeaders(enumName)); }); } - protected gatherNlohmannNamespaceForwardDecls(): Sourcelike[] { + protected gatherNlohmannNamespaceForwardDecls (): Sourcelike[] { return this.gatherSource(() => { this.forEachTopLevel("leading-and-interposing", (t: Type, className: Name) => - this.emitTopLevelHeaders(t, className) + this.emitTopLevelHeaders(t, className), ); this.ensureBlankLine(); @@ -2592,21 +2651,21 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { }); } - protected emitUserNamespaceImpls(): void { + protected emitUserNamespaceImpls (): void { this.forEachObject("leading-and-interposing", (c: ClassType, className: Name) => - this.emitClassFunctions(c, className) + this.emitClassFunctions(c, className), ); this.forEachEnum("leading-and-interposing", (e: EnumType, enumName: Name) => - this.emitEnumFunctions(e, enumName) + this.emitEnumFunctions(e, enumName), ); } - protected emitNlohmannNamespaceImpls(): void { + protected emitNlohmannNamespaceImpls (): void { this.forEachTopLevel( "leading-and-interposing", (t: Type, name: Name) => this.emitTopLevelFunction(t, name), - t => this.namedTypeToNameForTopLevel(t) === undefined + t => this.namedTypeToNameForTopLevel(t) === undefined, ); this.ensureBlankLine(); @@ -2614,7 +2673,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.emitAllUnionFunctions(); } - protected emitGenerators(): void { + protected emitGenerators (): void { if (this._options.justTypes) { let didEmit = false; const gathered = this.gatherSource(() => @@ -2622,9 +2681,9 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { didEmit = this.forEachTopLevel( "none", (t: Type, name: Name) => this.emitTopLevelTypedef(t, name), - t => this.namedTypeToNameForTopLevel(t) === undefined + t => this.namedTypeToNameForTopLevel(t) === undefined, ); - }) + }), ); if (didEmit) { this.emitGatheredSource(gathered); @@ -2661,7 +2720,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } - protected emitSingleSourceStructure(proposedFilename: string): void { + protected emitSingleSourceStructure (proposedFilename: string): void { this.startFile(proposedFilename); this._generatedFiles.add(proposedFilename); @@ -2674,6 +2733,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.emitOptionalHelpers(); this.ensureBlankLine(); } + this.emitNamespaces(this._namespaceNames, () => this.emitTypes()); } @@ -2684,7 +2744,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.finishFile(); } - protected updateIncludes(isClassMember: boolean, includes: IncludeMap, propertyType: Type, _defName: string): void { + protected updateIncludes (isClassMember: boolean, includes: IncludeMap, propertyType: Type, _defName: string): void { const propTypes = this.generatedTypes(isClassMember, propertyType); for (const t of propTypes) { @@ -2737,7 +2797,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } - protected emitIncludes(c: ClassType | UnionType | EnumType, defName: string): void { + protected emitIncludes (c: ClassType | UnionType | EnumType, defName: string): void { /** * Need to generate "includes", in terms 'c' has members, which * are defined by others @@ -2804,7 +2864,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } - protected emitDefinition(d: ClassType | EnumType | UnionType, defName: Name): void { + protected emitDefinition (d: ClassType | EnumType | UnionType, defName: Name): void { const name = `${this.sourcelikeToString(defName)}.hpp`; this.startFile(name, true); this._generatedFiles.add(name); @@ -2828,7 +2888,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.finishFile(); } - protected emitMultiSourceStructure(proposedFilename: string): void { + protected emitMultiSourceStructure (proposedFilename: string): void { if (!this._options.justTypes && this.haveNamedTypes) { this.emitHelper(); @@ -2854,7 +2914,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { }, (u, n) => { this.emitDefinition(u, n); - } + }, ); /** @@ -2876,7 +2936,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.forEachTopLevel( "leading", (t: Type, name: Name) => this.emitTopLevelTypedef(t, name), - t => this.namedTypeToNameForTopLevel(t) === undefined + t => this.namedTypeToNameForTopLevel(t) === undefined, ); }); @@ -2884,7 +2944,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } - protected emitSourceStructure(proposedFilename: string): void { + protected emitSourceStructure (proposedFilename: string): void { this._generatedFiles.clear(); /** Gather all the unique/custom types used by the schema */ @@ -2899,13 +2959,13 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: false, needsOptionalIndirection: false, - inJsonNamespace: false + inJsonNamespace: false, }, true, false, - false - ) - ) + false, + ), + ), ]); } @@ -2922,17 +2982,17 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } - protected isConversionRequired(t: Type) { + protected isConversionRequired (t: Type) { const originalType = this.cppType( t, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true + inJsonNamespace: true, }, false, false, - false + false, ); const newType = this.cppType( @@ -2940,18 +3000,18 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true + inJsonNamespace: true, }, false, true, - false + false, ); return originalType !== newType; } - public NarrowString = new (class extends BaseString implements StringType { - constructor() { + public NarrowString = new class extends BaseString implements StringType { + constructor () { super( "std::string", "const std::string & ", @@ -2960,26 +3020,26 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { "", new WrappingCode(["std::to_string("], [")"]), "", - "" + "", ); } - public wrapEncodingChange( + public wrapEncodingChange ( _qualifier: Sourcelike[], _fromType: Sourcelike, _toType: Sourcelike, - inner: Sourcelike + inner: Sourcelike, ): Sourcelike { return inner; } - public emitHelperFunctions(): void { + public emitHelperFunctions (): void { return; } - })(); + }(); - public WideString = new (class extends BaseString implements StringType { - constructor(public superThis: CPlusPlusRenderer) { + public WideString = new class extends BaseString implements StringType { + constructor (public superThis: CPlusPlusRenderer) { super( "std::wstring", "const std::wstring & ", @@ -2988,15 +3048,15 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { "L", new WrappingCode(["std::to_wstring("], [")"]), "Utf16_Utf8", - "convert" + "convert", ); } - public wrapEncodingChange( + public wrapEncodingChange ( qualifier: Sourcelike[], fromType: Sourcelike, toType: Sourcelike, - inner: Sourcelike + inner: Sourcelike, ): Sourcelike { if (this.superThis.sourcelikeToString(fromType) === this.superThis.sourcelikeToString(toType)) { return inner; @@ -3012,11 +3072,11 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this._encodingFunction, "(", inner, - ")" + ")", ]; } - public emitHelperFunctions(): void { + public emitHelperFunctions (): void { this.superThis.emitLine("template"); this.superThis.emitLine("struct tag {};"); this.superThis.ensureBlankLine(); @@ -3030,9 +3090,9 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { false, () => { this.superThis.emitLine( - "if (ptr == nullptr) return std::unique_ptr(); else return std::unique_ptr(new TT(Utf16_Utf8::convert(*ptr)));" + "if (ptr == nullptr) return std::unique_ptr(); else return std::unique_ptr(new TT(Utf16_Utf8::convert(*ptr)));", ); - } + }, ); this.superThis.ensureBlankLine(); @@ -3048,7 +3108,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.superThis.emitLine("it++;"); }); this.superThis.emitLine("return newVector;"); - } + }, ); this.superThis.ensureBlankLine(); @@ -3061,12 +3121,12 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.superThis.emitLine("auto newMap = std::map();"); this.superThis.emitBlock(["while (it != m.end())"], false, () => { this.superThis.emitLine( - "newMap.insert(std::pair(Utf16_Utf8::convert(it->first), Utf16_Utf8::convert(it->second)));" + "newMap.insert(std::pair(Utf16_Utf8::convert(it->first), Utf16_Utf8::convert(it->second)));", ); this.superThis.emitLine("it++;"); }); this.superThis.emitLine("return newMap;"); - } + }, ); this.superThis.ensureBlankLine(); @@ -3081,9 +3141,9 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { false, () => { this.superThis.emitLine( - "return std::wstring_convert, wchar_t>{}.from_bytes(str.data());" + "return std::wstring_convert, wchar_t>{}.from_bytes(str.data());", ); - } + }, ); this.superThis.ensureBlankLine(); @@ -3092,9 +3152,9 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { false, () => { this.superThis.emitLine( - "return std::wstring_convert, wchar_t>{}.to_bytes(str.data());" + "return std::wstring_convert, wchar_t>{}.to_bytes(str.data());", ); - } + }, ); this.superThis.ensureBlankLine(); @@ -3112,10 +3172,10 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.superThis.emitLine( "return ", this.superThis.ourQualifier(false), - "Utf16_Utf8::convert(s.str()); " + "Utf16_Utf8::convert(s.str()); ", ); }); this.superThis.ensureBlankLine(); } - })(this); + }(this); } diff --git a/packages/quicktype-core/src/language/CSharp.ts b/packages/quicktype-core/src/language/CSharp.ts index 627e387be..9ffc68669 100644 --- a/packages/quicktype-core/src/language/CSharp.ts +++ b/packages/quicktype-core/src/language/CSharp.ts @@ -1,18 +1,24 @@ import { arrayIntercalate } from "collection-utils"; import { - Type, + type Type, + type ClassProperty, + type TransformedStringTypeKind, + type PrimitiveStringTypeKind, + type PrimitiveType, +} from "../Type"; +import { EnumType, UnionType, ClassType, - ClassProperty, ArrayType, - TransformedStringTypeKind, - PrimitiveStringTypeKind, - PrimitiveType } from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion, directlyReachableSingleNamedType } from "../TypeUtils"; -import { Sourcelike, maybeAnnotated, modifySource } from "../Source"; +import { type Sourcelike} from "../Source"; +import { maybeAnnotated, modifySource } from "../Source"; +import { + type WordInName, +} from "../support/Strings"; import { utf16LegalizeCharacters, utf16StringEscape, @@ -20,19 +26,23 @@ import { combineWords, firstUpperWordStyle, camelCase, - WordInName } from "../support/Strings"; import { defined, assert, panic, assertNever } from "../support/Support"; -import { Name, DependencyName, Namer, funPrefixNamer, SimpleName } from "../Naming"; -import { ConvenienceRenderer, ForbiddenWordsInfo, inferredNameOrder } from "../ConvenienceRenderer"; +import { type Name, type Namer} from "../Naming"; +import { DependencyName, funPrefixNamer, SimpleName } from "../Naming"; +import { type ForbiddenWordsInfo} from "../ConvenienceRenderer"; +import { ConvenienceRenderer, inferredNameOrder } from "../ConvenienceRenderer"; import { TargetLanguage } from "../TargetLanguage"; -import { StringOption, EnumOption, Option, BooleanOption, OptionValues, getOptionValues } from "../RendererOptions"; +import { type Option, type OptionValues} from "../RendererOptions"; +import { StringOption, EnumOption, BooleanOption, getOptionValues } from "../RendererOptions"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { StringTypeMapping } from "../TypeBuilder"; +import { type StringTypeMapping } from "../TypeBuilder"; +import { + type Transformer, + type Transformation} from "../Transformers"; import { followTargetType, transformationForType, - Transformer, DecodingTransformer, DecodingChoiceTransformer, UnionInstantiationTransformer, @@ -43,13 +53,12 @@ import { StringProducerTransformer, ParseStringTransformer, StringifyTransformer, - Transformation, ArrayDecodingTransformer, ArrayEncodingTransformer, MinMaxLengthCheckTransformer, - MinMaxValueTransformer + MinMaxValueTransformer, } from "../Transformers"; -import { RenderContext } from "../Renderer"; +import { type RenderContext } from "../Renderer"; import { minMaxLengthForType, minMaxValueForType } from "../attributes/Constraints"; import unicode from "unicode-properties"; @@ -59,7 +68,9 @@ export enum Framework { } export type Version = 5 | 6; -export type OutputFeatures = { helpers: boolean; attributes: boolean }; +export interface OutputFeatures { + attributes: boolean; helpers: boolean; +} export enum AccessModifier { None, @@ -69,32 +80,35 @@ export enum AccessModifier { export type CSharpTypeForAny = "object" | "dynamic"; -function noFollow(t: Type): Type { +function noFollow (t: Type): Type { return t; } -function needTransformerForType(t: Type): "automatic" | "manual" | "nullable" | "none" { +function needTransformerForType (t: Type): "automatic" | "manual" | "nullable" | "none" { if (t instanceof UnionType) { const maybeNullable = nullableFromUnion(t); if (maybeNullable === null) return "automatic"; if (needTransformerForType(maybeNullable) === "manual") return "nullable"; return "none"; } + if (t instanceof ArrayType) { const itemsNeed = needTransformerForType(t.items); if (itemsNeed === "manual" || itemsNeed === "nullable") return "automatic"; return "none"; } + if (t instanceof EnumType) return "automatic"; if (t.kind === "double") return minMaxValueForType(t) !== undefined ? "manual" : "none"; if (t.kind === "integer-string" || t.kind === "bool-string") return "manual"; if (t.kind === "string") { return minMaxLengthForType(t) !== undefined ? "manual" : "none"; } + return "none"; } -function alwaysApplyTransformation(xf: Transformation): boolean { +function alwaysApplyTransformation (xf: Transformation): boolean { const t = xf.targetType; if (t instanceof EnumType) return true; if (t instanceof UnionType) return nullableFromUnion(t) === null; @@ -104,7 +118,7 @@ function alwaysApplyTransformation(xf: Transformation): boolean { /** * The C# type for a given transformed string type. */ -function csTypeForTransformedStringType(t: PrimitiveType): Sourcelike { +function csTypeForTransformedStringType (t: PrimitiveType): Sourcelike { switch (t.kind) { case "date-time": return "DateTimeOffset"; @@ -123,23 +137,23 @@ export const cSharpOptions = { "Serialization framework", [ ["NewtonSoft", Framework.Newtonsoft], - ["SystemTextJson", Framework.SystemTextJson] + ["SystemTextJson", Framework.SystemTextJson], ], - "NewtonSoft" + "NewtonSoft", ), useList: new EnumOption("array-type", "Use T[] or List", [ ["array", false], - ["list", true] + ["list", true], ]), dense: new EnumOption( "density", "Property density", [ ["normal", false], - ["dense", true] + ["dense", true], ], "normal", - "secondary" + "secondary", ), // FIXME: Do this via a configurable named eventually. namespace: new StringOption("namespace", "Generated namespace", "NAME", "QuickType"), @@ -148,58 +162,58 @@ export const cSharpOptions = { "C# version", [ ["5", 5], - ["6", 6] + ["6", 6], ], "6", - "secondary" + "secondary", ), virtual: new BooleanOption("virtual", "Generate virtual properties", false), typeForAny: new EnumOption( "any-type", - 'Type to use for "any"', + "Type to use for \"any\"", [ ["object", "object"], - ["dynamic", "dynamic"] + ["dynamic", "dynamic"], ], "object", - "secondary" + "secondary", ), useDecimal: new EnumOption( "number-type", "Type to use for numbers", [ ["double", false], - ["decimal", true] + ["decimal", true], ], "double", - "secondary" + "secondary", ), features: new EnumOption("features", "Output features", [ ["complete", { namespaces: true, helpers: true, attributes: true }], ["attributes-only", { namespaces: true, helpers: false, attributes: true }], ["just-types-and-namespace", { namespaces: true, helpers: false, attributes: false }], - ["just-types", { namespaces: true, helpers: false, attributes: false }] + ["just-types", { namespaces: true, helpers: false, attributes: false }], ]), baseclass: new EnumOption( "base-class", "Base class", [ ["EntityData", "EntityData"], - ["Object", undefined] + ["Object", undefined], ], "Object", - "secondary" + "secondary", ), checkRequired: new BooleanOption("check-required", "Fail if required properties are missing", false), - keepPropertyName: new BooleanOption("keep-property-name", "Keep original field name generate", false) + keepPropertyName: new BooleanOption("keep-property-name", "Keep original field name generate", false), }; export class CSharpTargetLanguage extends TargetLanguage { - constructor() { + constructor () { super("C#", ["cs", "csharp"], "cs"); } - protected getOptions(): Option[] { + protected getOptions (): Array> { return [ cSharpOptions.framework, cSharpOptions.namespace, @@ -212,11 +226,11 @@ export class CSharpTargetLanguage extends TargetLanguage { cSharpOptions.features, cSharpOptions.baseclass, cSharpOptions.checkRequired, - cSharpOptions.keepPropertyName + cSharpOptions.keepPropertyName, ]; } - get stringTypeMapping(): StringTypeMapping { + get stringTypeMapping (): StringTypeMapping { const mapping: Map = new Map(); mapping.set("date", "date-time"); mapping.set("time", "date-time"); @@ -228,22 +242,22 @@ export class CSharpTargetLanguage extends TargetLanguage { return mapping; } - get supportsUnionsWithBothNumberTypes(): boolean { + get supportsUnionsWithBothNumberTypes (): boolean { return true; } - get supportsOptionalClassProperties(): boolean { + get supportsOptionalClassProperties (): boolean { return true; } - needsTransformerForType(t: Type): boolean { + needsTransformerForType (t: Type): boolean { const need = needTransformerForType(t); return need !== "none" && need !== "nullable"; } - protected makeRenderer( + protected makeRenderer ( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } + untypedOptionValues: { [name: string]: any, }, ): ConvenienceRenderer { const options = getOptionValues(cSharpOptions, untypedOptionValues); @@ -252,13 +266,13 @@ export class CSharpTargetLanguage extends TargetLanguage { return new NewtonsoftCSharpRenderer( this, renderContext, - getOptionValues(newtonsoftCSharpOptions, untypedOptionValues) + getOptionValues(newtonsoftCSharpOptions, untypedOptionValues), ); case Framework.SystemTextJson: return new SystemTextJsonCSharpRenderer( this, renderContext, - getOptionValues(systemTextJsonCSharpOptions, untypedOptionValues) + getOptionValues(systemTextJsonCSharpOptions, untypedOptionValues), ); default: return assertNever(options.framework); @@ -274,24 +288,26 @@ const denseJsonPropertyName = "J"; const denseRequiredEnumName = "R"; const denseNullValueHandlingEnumName = "N"; -function isStartCharacter(utf16Unit: number): boolean { +function isStartCharacter (utf16Unit: number): boolean { if (unicode.isAlphabetic(utf16Unit)) { return true; } + return utf16Unit === 0x5f; // underscore } -function isPartCharacter(utf16Unit: number): boolean { +function isPartCharacter (utf16Unit: number): boolean { const category: string = unicode.getCategory(utf16Unit); - if (["Nd", "Pc", "Mn", "Mc"].indexOf(category) >= 0) { + if (["Nd", "Pc", "Mn", "Mc"].includes(category)) { return true; } + return isStartCharacter(utf16Unit); } const legalizeName = utf16LegalizeCharacters(isPartCharacter); -function csNameStyle(original: string): string { +function csNameStyle (original: string): string { const words = splitIntoWords(original); return combineWords( words, @@ -301,11 +317,11 @@ function csNameStyle(original: string): string { firstUpperWordStyle, firstUpperWordStyle, "", - isStartCharacter + isStartCharacter, ); } -function csNameStyleKeep(original: string): string { +function csNameStyleKeep (original: string): string { const keywords = [ "abstract", "as", @@ -383,14 +399,14 @@ function csNameStyleKeep(original: string): string { "virtual", "void", "volatile", - "while" + "while", ]; const words: WordInName[] = [ { word: original, - isAcronym: false - } + isAcronym: false, + }, ]; const result = combineWords( @@ -401,33 +417,34 @@ function csNameStyleKeep(original: string): string { x => x, x => x, "", - isStartCharacter + isStartCharacter, ); return keywords.includes(result) ? "@" + result : result; } -function isValueType(t: Type): boolean { +function isValueType (t: Type): boolean { if (t instanceof UnionType) { return nullableFromUnion(t) === null; } - return ["integer", "double", "bool", "enum", "date-time", "uuid"].indexOf(t.kind) >= 0; + + return ["integer", "double", "bool", "enum", "date-time", "uuid"].includes(t.kind); } export class CSharpRenderer extends ConvenienceRenderer { - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _csOptions: OptionValues + private readonly _csOptions: OptionValues, ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace (): string[] { return ["QuickType", "Type", "System", "Console", "Exception", "DateTimeOffset", "Guid", "Uri"]; } - protected forbiddenForObjectProperties(_: ClassType, classNamed: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties (_: ClassType, classNamed: Name): ForbiddenWordsInfo { return { names: [ classNamed, @@ -437,54 +454,54 @@ export class CSharpRenderer extends ConvenienceRenderer { "Equals", "GetType", "MemberwiseClone", - "ReferenceEquals" + "ReferenceEquals", ], - includeGlobalForbidden: false + includeGlobalForbidden: false, }; } - protected forbiddenForUnionMembers(_: UnionType, unionNamed: Name): ForbiddenWordsInfo { + protected forbiddenForUnionMembers (_: UnionType, unionNamed: Name): ForbiddenWordsInfo { return { names: [unionNamed], includeGlobalForbidden: true }; } - protected makeNamedTypeNamer(): Namer { + protected makeNamedTypeNamer (): Namer { return namingFunction; } - protected namerForObjectProperty(): Namer { + protected namerForObjectProperty (): Namer { return this._csOptions.keepPropertyName ? namingFunctionKeep : namingFunction; } - protected makeUnionMemberNamer(): Namer { + protected makeUnionMemberNamer (): Namer { return namingFunction; } - protected makeEnumCaseNamer(): Namer { + protected makeEnumCaseNamer (): Namer { return namingFunction; } - protected unionNeedsName(u: UnionType): boolean { + protected unionNeedsName (u: UnionType): boolean { return nullableFromUnion(u) === null; } - protected namedTypeToNameForTopLevel(type: Type): Type | undefined { + protected namedTypeToNameForTopLevel (type: Type): Type | undefined { // If the top-level type doesn't contain any classes or unions // we have to define a class just for the `FromJson` method, in // emitFromJsonForTopLevel. return directlyReachableSingleNamedType(type); } - protected emitBlock(f: () => void, semicolon = false): void { + protected emitBlock (f: () => void, semicolon = false): void { this.emitLine("{"); this.indent(f); this.emitLine("}", semicolon ? ";" : ""); } - protected get doubleType(): string { + protected get doubleType (): string { return this._csOptions.useDecimal ? "decimal" : "double"; } - protected csType(t: Type, follow: (t: Type) => Type = followTargetType, withIssues = false): Sourcelike { + protected csType (t: Type, follow: (t: Type) => Type = followTargetType, withIssues = false): Sourcelike { const actualType = follow(t); return matchType( actualType, @@ -510,11 +527,11 @@ export class CSharpRenderer extends ConvenienceRenderer { if (nullable !== null) return this.nullableCSType(nullable, noFollow); return this.nameForNamedType(unionType); }, - transformedStringType => csTypeForTransformedStringType(transformedStringType) + transformedStringType => csTypeForTransformedStringType(transformedStringType), ); } - protected nullableCSType(t: Type, follow: (t: Type) => Type = followTargetType, withIssues = false): Sourcelike { + protected nullableCSType (t: Type, follow: (t: Type) => Type = followTargetType, withIssues = false): Sourcelike { t = followTargetType(t); const csType = this.csType(t, follow, withIssues); if (isValueType(t)) { @@ -523,16 +540,18 @@ export class CSharpRenderer extends ConvenienceRenderer { return csType; } } - protected baseclassForType(_t: Type): Sourcelike | undefined { + + protected baseclassForType (_t: Type): Sourcelike | undefined { return undefined; } - protected emitType( + + protected emitType ( description: string[] | undefined, accessModifier: AccessModifier, declaration: Sourcelike, name: Sourcelike, baseclass: Sourcelike | undefined, - emitter: () => void + emitter: () => void, ): void { switch (accessModifier) { case AccessModifier.Public: @@ -544,25 +563,27 @@ export class CSharpRenderer extends ConvenienceRenderer { default: break; } + this.emitDescription(description); if (baseclass === undefined) { this.emitLine(declaration, " ", name); } else { this.emitLine(declaration, " ", name, " : ", baseclass); } + this.emitBlock(emitter); } - protected attributesForProperty( + protected attributesForProperty ( _property: ClassProperty, _name: Name, _c: ClassType, - _jsonName: string + _jsonName: string, ): Sourcelike[] | undefined { return undefined; } - protected propertyDefinition(property: ClassProperty, name: Name, _c: ClassType, _jsonName: string): Sourcelike { + protected propertyDefinition (property: ClassProperty, name: Name, _c: ClassType, _jsonName: string): Sourcelike { const t = property.type; const csType = property.isOptional ? this.nullableCSType(t, followTargetType, true) @@ -575,7 +596,7 @@ export class CSharpRenderer extends ConvenienceRenderer { return [...propertyArray, csType, " ", name, " { get; set; }"]; } - protected emitDescriptionBlock(lines: Sourcelike[]): void { + protected emitDescriptionBlock (lines: Sourcelike[]): void { const start = "/// "; if (this._csOptions.dense) { this.emitLine(start, lines.join("; "), ""); @@ -584,11 +605,11 @@ export class CSharpRenderer extends ConvenienceRenderer { } } - protected blankLinesBetweenAttributes(): boolean { + protected blankLinesBetweenAttributes (): boolean { return false; } - private emitClassDefinition(c: ClassType, className: Name): void { + private emitClassDefinition (c: ClassType, className: Name): void { this.emitType( this.descriptionForType(c), AccessModifier.Public, @@ -608,12 +629,13 @@ export class CSharpRenderer extends ConvenienceRenderer { if (attributes === undefined) { if ( // Descriptions should be preceded by an empty line - (!isFirstProperty && description !== undefined) || + !isFirstProperty && description !== undefined || // If the previous property has a description, leave an empty line previousDescription !== undefined ) { this.ensureBlankLine(); } + this.emitDescription(description); this.emitLine(property); } else if (this._csOptions.dense && attributes.length > 0) { @@ -624,6 +646,7 @@ export class CSharpRenderer extends ConvenienceRenderer { for (const attribute of attributes) { this.emitLine(attribute); } + this.emitLine(property); } @@ -633,11 +656,11 @@ export class CSharpRenderer extends ConvenienceRenderer { if (columns.length > 0) { this.emitTable(columns); } - } + }, ); } - private emitUnionDefinition(u: UnionType, unionName: Name): void { + private emitUnionDefinition (u: UnionType, unionName: Name): void { const nonNulls = removeNullFromUnion(u, true)[1]; this.emitType( this.descriptionForType(u), @@ -653,23 +676,23 @@ export class CSharpRenderer extends ConvenienceRenderer { this.ensureBlankLine(); const nullTests: Sourcelike[] = Array.from(nonNulls).map(t => [ this.nameForUnionMember(u, t), - " == null" + " == null", ]); this.ensureBlankLine(); this.forEachUnionMember(u, nonNulls, "none", null, (fieldName, t) => { const csType = this.csType(t); this.emitExpressionMember( ["public static implicit operator ", unionName, "(", csType, " ", fieldName, ")"], - ["new ", unionName, " { ", fieldName, " = ", fieldName, " }"] + ["new ", unionName, " { ", fieldName, " = ", fieldName, " }"], ); }); if (u.findMember("null") === undefined) return; this.emitExpressionMember("public bool IsNull", arrayIntercalate(" && ", nullTests), true); - } + }, ); } - private emitEnumDefinition(e: EnumType, enumName: Name): void { + private emitEnumDefinition (e: EnumType, enumName: Name): void { const caseNames: Sourcelike[] = []; this.forEachEnumCase(e, "none", name => { if (caseNames.length > 0) caseNames.push(", "); @@ -679,7 +702,7 @@ export class CSharpRenderer extends ConvenienceRenderer { this.emitLine("public enum ", enumName, " { ", caseNames, " };"); } - protected emitExpressionMember(declare: Sourcelike, define: Sourcelike, isProperty = false): void { + protected emitExpressionMember (declare: Sourcelike, define: Sourcelike, isProperty = false): void { if (this._csOptions.version === 5) { this.emitLine(declare); this.emitBlock(() => { @@ -701,7 +724,7 @@ export class CSharpRenderer extends ConvenienceRenderer { condition: (t: T) => Sourcelike, withBlock: boolean, withReturn: boolean, - f: (t: T) => void + f: (t: T) => void, ): void { assert(!withReturn || withBlock, "Can only have return with block"); for (const t of types) { @@ -719,40 +742,40 @@ export class CSharpRenderer extends ConvenienceRenderer { } } - protected emitUsing(ns: Sourcelike): void { + protected emitUsing (ns: Sourcelike): void { this.emitLine("using ", ns, ";"); } - protected emitUsings(): void { + protected emitUsings (): void { for (const ns of ["System", "System.Collections.Generic"]) { this.emitUsing(ns); } } - protected emitRequiredHelpers(): void { + protected emitRequiredHelpers (): void { return; } - private emitTypesAndSupport(): void { + private emitTypesAndSupport (): void { this.forEachObject("leading-and-interposing", (c: ClassType, name: Name) => this.emitClassDefinition(c, name)); this.forEachEnum("leading-and-interposing", (e, name) => this.emitEnumDefinition(e, name)); this.forEachUnion("leading-and-interposing", (u, name) => this.emitUnionDefinition(u, name)); this.emitRequiredHelpers(); } - protected emitDefaultLeadingComments(): void { + protected emitDefaultLeadingComments (): void { return; } - protected emitDefaultFollowingComments(): void { + protected emitDefaultFollowingComments (): void { return; } - protected needNamespace(): boolean { + protected needNamespace (): boolean { return true; } - protected emitSourceStructure(): void { + protected emitSourceStructure (): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } else { @@ -781,13 +804,15 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { private readonly _enumExtensionsNames = new Map(); private readonly _needHelpers: boolean; + private readonly _needAttributes: boolean; + private readonly _needNamespaces: boolean; - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues + private readonly _options: OptionValues, ) { super(targetLanguage, renderContext, _options); this._needHelpers = _options.features.helpers; @@ -795,7 +820,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { this._needNamespaces = _options.features.namespaces; } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace (): string[] { const forbidden = [ "Converter", "JsonConverter", @@ -807,47 +832,51 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { "MetadataPropertyHandling", "DateParseHandling", "FromJson", - "Required" + "Required", ]; if (this._options.dense) { forbidden.push("J", "R", "N"); } + if (this._options.baseclass !== undefined) { forbidden.push(this._options.baseclass); } + return super.forbiddenNamesForGlobalNamespace().concat(forbidden); } - protected forbiddenForObjectProperties(c: ClassType, className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties (c: ClassType, className: Name): ForbiddenWordsInfo { const result = super.forbiddenForObjectProperties(c, className); result.names = result.names.concat(["ToJson", "FromJson", "Required"]); return result; } - protected makeNameForTransformation(xf: Transformation, typeName: Name | undefined): Name { + protected makeNameForTransformation (xf: Transformation, typeName: Name | undefined): Name { if (typeName === undefined) { let xfer = xf.transformer; if (xfer instanceof DecodingTransformer && xfer.consumer !== undefined) { xfer = xfer.consumer; } + return new SimpleName([`${xfer.kind}_converter`], namingFunction, inferredNameOrder + 30); } + return new DependencyName(namingFunction, typeName.order + 30, lookup => `${lookup(typeName)}_converter`); } - protected makeNamedTypeDependencyNames(t: Type, name: Name): DependencyName[] { + protected makeNamedTypeDependencyNames (t: Type, name: Name): DependencyName[] { if (!(t instanceof EnumType)) return []; const extensionsName = new DependencyName( namingFunction, name.order + 30, - lookup => `${lookup(name)}_extensions` + lookup => `${lookup(name)}_extensions`, ); this._enumExtensionsNames.set(name, extensionsName); return [extensionsName]; } - protected emitUsings(): void { + protected emitUsings (): void { // FIXME: We need System.Collections.Generic whenever we have maps or use List. if (!this._needAttributes && !this._needHelpers) return; @@ -863,14 +892,17 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { this.emitUsing([denseRequiredEnumName, " = Newtonsoft.Json.Required"]); this.emitUsing([denseNullValueHandlingEnumName, " = Newtonsoft.Json.NullValueHandling"]); } + if (this._options.baseclass === "EntityData") { this.emitUsing("Microsoft.Azure.Mobile.Server"); } } - protected baseclassForType(_t: Type): Sourcelike | undefined { + + protected baseclassForType (_t: Type): Sourcelike | undefined { return this._options.baseclass; } - protected emitDefaultLeadingComments(): void { + + protected emitDefaultLeadingComments (): void { if (!this._needHelpers) return; this.emitLine("// "); @@ -878,7 +910,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { this.emitLine( "// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do", this.topLevels.size === 1 ? "" : " one of these", - ":" + ":", ); this.emitLine("//"); this.emitLine("// using ", this._options.namespace, ";"); @@ -890,11 +922,12 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { } else { rhs = [topLevelName, ".FromJson(jsonString)"]; } + this.emitLine("// var ", modifySource(camelCase, topLevelName), " = ", rhs, ";"); }); } - private converterForType(t: Type): Name | undefined { + private converterForType (t: Type): Name | undefined { let xf = transformationForType(t); if (xf === undefined && t instanceof UnionType) { @@ -912,11 +945,11 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { return defined(this.nameForTransformation(t)); } - protected attributesForProperty( + protected attributesForProperty ( property: ClassProperty, _name: Name, _c: ClassType, - jsonName: string + jsonName: string, ): Sourcelike[] | undefined { if (!this._needAttributes) return undefined; @@ -931,7 +964,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { const nullValueHandling = isOptional && !isNullable ? [", NullValueHandling = ", nullValueHandlingClass, ".Ignore"] : []; let required: Sourcelike; - if (!this._options.checkRequired || (isOptional && isNullable)) { + if (!this._options.checkRequired || isOptional && isNullable) { required = [nullValueHandling]; } else if (isOptional && !isNullable) { required = [", Required = ", requiredClass, ".DisallowNull", nullValueHandling]; @@ -940,7 +973,8 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { } else { required = [", Required = ", requiredClass, ".Always", nullValueHandling]; } - attributes.push(["[", jsonProperty, '("', escapedName, '"', required, ")]"]); + + attributes.push(["[", jsonProperty, "(\"", escapedName, "\"", required, ")]"]); const converter = this.converterForType(property.type); if (converter !== undefined) { @@ -950,16 +984,16 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { return attributes; } - protected blankLinesBetweenAttributes(): boolean { + protected blankLinesBetweenAttributes (): boolean { return this._needAttributes && !this._options.dense; } // The "this" type can't be `dynamic`, so we have to force it to `object`. - private topLevelResultType(t: Type): Sourcelike { + private topLevelResultType (t: Type): Sourcelike { return t.kind === "any" || t.kind === "none" ? "object" : this.csType(t); } - private emitFromJsonForTopLevel(t: Type, name: Name): void { + private emitFromJsonForTopLevel (t: Type, name: Name): void { if (t instanceof EnumType) return; let partial: string; @@ -972,38 +1006,39 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { partial = ""; typeKind = "class"; } + const csType = this.topLevelResultType(t); this.emitType(undefined, AccessModifier.Public, [partial, typeKind], name, this.baseclassForType(t), () => { // FIXME: Make FromJson a Named this.emitExpressionMember( ["public static ", csType, " FromJson(string json)"], - ["JsonConvert.DeserializeObject<", csType, ">(json, ", this._options.namespace, ".Converter.Settings)"] + ["JsonConvert.DeserializeObject<", csType, ">(json, ", this._options.namespace, ".Converter.Settings)"], ); }); } - private emitDecoderSwitch(emitBody: () => void): void { + private emitDecoderSwitch (emitBody: () => void): void { this.emitLine("switch (reader.TokenType)"); this.emitBlock(emitBody); } - private emitTokenCase(tokenType: string): void { + private emitTokenCase (tokenType: string): void { this.emitLine("case JsonToken.", tokenType, ":"); } - private emitThrow(message: Sourcelike): void { + private emitThrow (message: Sourcelike): void { this.emitLine("throw new Exception(", message, ");"); } - private deserializeTypeCode(typeName: Sourcelike): Sourcelike { + private deserializeTypeCode (typeName: Sourcelike): Sourcelike { return ["serializer.Deserialize<", typeName, ">(reader)"]; } - private serializeValueCode(value: Sourcelike): Sourcelike { + private serializeValueCode (value: Sourcelike): Sourcelike { return ["serializer.Serialize(writer, ", value, ")"]; } - private emitSerializeClass(): void { + private emitSerializeClass (): void { // FIXME: Make Serialize a Named this.emitType(undefined, AccessModifier.Public, "static class", "Serialize", undefined, () => { // Sometimes multiple top-levels will resolve to the same type, so we have to take care @@ -1015,39 +1050,39 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { seenTypes.add(t); this.emitExpressionMember( ["public static string ToJson(this ", this.topLevelResultType(t), " self)"], - ["JsonConvert.SerializeObject(self, ", this._options.namespace, ".Converter.Settings)"] + ["JsonConvert.SerializeObject(self, ", this._options.namespace, ".Converter.Settings)"], ); } }); }); } - private emitCanConvert(expr: Sourcelike): void { + private emitCanConvert (expr: Sourcelike): void { this.emitExpressionMember("public override bool CanConvert(Type t)", expr); } - private emitReadJson(emitBody: () => void): void { + private emitReadJson (emitBody: () => void): void { this.emitLine( - "public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)" + "public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)", ); this.emitBlock(emitBody); } - private emitWriteJson(variable: string, emitBody: () => void): void { + private emitWriteJson (variable: string, emitBody: () => void): void { this.emitLine( "public override void WriteJson(JsonWriter writer, object ", variable, - ", JsonSerializer serializer)" + ", JsonSerializer serializer)", ); this.emitBlock(emitBody); } - private converterObject(converterName: Name): Sourcelike { + private converterObject (converterName: Name): Sourcelike { // FIXME: Get a singleton return [converterName, ".Singleton"]; } - private emitConverterClass(): void { + private emitConverterClass (): void { // FIXME: Make Converter a Named const converterName: Sourcelike = ["Converter"]; this.emitType(undefined, AccessModifier.Internal, "static class", converterName, undefined, () => { @@ -1063,25 +1098,27 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { this.emitLine(this.converterObject(converter), ","); } } + this.emitLine("new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }"); }); - this.emitLine(`},`); + this.emitLine("},"); }, true); }); } - private emitDecoderTransformerCase( + private emitDecoderTransformerCase ( tokenCases: string[], variableName: string, xfer: Transformer | undefined, targetType: Type, - emitFinish: (value: Sourcelike) => void + emitFinish: (value: Sourcelike) => void, ): void { if (xfer === undefined) return; for (const tokenCase of tokenCases) { this.emitTokenCase(tokenCase); } + this.indent(() => { const allHandled = this.emitDecodeTransformer(xfer, targetType, emitFinish, variableName); if (!allHandled) { @@ -1090,11 +1127,11 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { }); } - private emitConsume( + private emitConsume ( value: Sourcelike, consumer: Transformer | undefined, targetType: Type, - emitFinish: (variableName: Sourcelike) => void + emitFinish: (variableName: Sourcelike) => void, ): boolean { if (consumer === undefined) { emitFinish(value); @@ -1104,11 +1141,11 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { } } - private emitDecodeTransformer( + private emitDecodeTransformer ( xfer: Transformer, targetType: Type, emitFinish: (value: Sourcelike) => void, - variableName = "value" + variableName = "value", ): boolean { if (xfer instanceof DecodingTransformer) { const source = xfer.sourceType; @@ -1123,18 +1160,20 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { typeSource, ")converter.ReadJson(reader, typeof(", typeSource, - "), null, serializer);" + "), null, serializer);", ); } else if (source.kind !== "null") { let output = targetType.kind === "double" ? targetType : source; this.emitLine("var ", variableName, " = ", this.deserializeTypeCode(this.csType(output)), ";"); } + return this.emitConsume(variableName, xfer.consumer, targetType, emitFinish); } else if (xfer instanceof ArrayDecodingTransformer) { // FIXME: Consume StartArray if (!(targetType instanceof ArrayType)) { return panic("Array decoding must produce an array type"); } + // FIXME: handle EOF this.emitLine("reader.Read();"); this.emitLine("var ", variableName, " = new List<", this.csType(targetType.items), ">();"); @@ -1144,7 +1183,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { xfer.itemTransformer, xfer.itemTargetType, v => this.emitLine(variableName, ".Add(", v, ");"), - "arrayItem" + "arrayItem", ); // FIXME: handle EOF this.emitLine("reader.Read();"); @@ -1153,6 +1192,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { if (!this._options.useList) { result = [result, ".ToArray()"]; } + emitFinish(result); return true; } else if (xfer instanceof DecodingChoiceTransformer) { @@ -1167,19 +1207,20 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { } }); } + this.emitDecoderTransformerCase( ["Integer"], "integerValue", xfer.integerTransformer, targetType, - emitFinish + emitFinish, ); this.emitDecoderTransformerCase( xfer.integerTransformer === undefined ? ["Integer", "Float"] : ["Float"], "doubleValue", xfer.doubleTransformer, targetType, - emitFinish + emitFinish, ); this.emitDecoderTransformerCase(["Boolean"], "boolValue", xfer.boolTransformer, targetType, emitFinish); this.emitDecoderTransformerCase( @@ -1187,21 +1228,21 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { "stringValue", xfer.stringTransformer, targetType, - emitFinish + emitFinish, ); this.emitDecoderTransformerCase( ["StartObject"], "objectValue", xfer.objectTransformer, targetType, - emitFinish + emitFinish, ); this.emitDecoderTransformerCase( ["StartArray"], "arrayValue", xfer.arrayTransformer, targetType, - emitFinish + emitFinish, ); }); return false; @@ -1210,25 +1251,27 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { } } - private stringCaseValue(t: Type, stringCase: string): Sourcelike { + private stringCaseValue (t: Type, stringCase: string): Sourcelike { if (t.kind === "string") { - return ['"', utf16StringEscape(stringCase), '"']; + return ["\"", utf16StringEscape(stringCase), "\""]; } else if (t instanceof EnumType) { return [this.nameForNamedType(t), ".", this.nameForEnumCase(t, stringCase)]; } + return panic(`Type ${t.kind} does not have string cases`); } - private emitTransformer( + private emitTransformer ( variable: Sourcelike, xfer: Transformer, targetType: Type, - emitFinish: (value: Sourcelike) => void + emitFinish: (value: Sourcelike) => void, ): boolean { - function directTargetType(continuation: Transformer | undefined): Type { + function directTargetType (continuation: Transformer | undefined): Type { if (continuation === undefined) { return targetType; } + return followTargetType(continuation.sourceType); } @@ -1241,7 +1284,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { const matchXfer = caseXfer as StringMatchTransformer; const value = this.stringCaseValue( followTargetType(matchXfer.sourceType), - matchXfer.stringCase + matchXfer.stringCase, ); this.emitLine("case ", value, ":"); this.indent(() => { @@ -1249,7 +1292,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { variable, matchXfer.transformer, targetType, - emitFinish + emitFinish, ); if (!allDone) { this.emitLine("break;"); @@ -1285,9 +1328,11 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { member = [variable, ".", memberName]; test = [member, " != null"]; } + if (memberType.kind !== "null" && isValueType(memberType)) { member = [member, ".Value"]; } + this.emitLine("if (", test, ")"); this.emitBlock(() => this.emitTransformer(member, xfer.transformer, targetType, emitFinish)); } else if (xfer instanceof StringMatchTransformer) { @@ -1302,6 +1347,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { } else { this.emitLine(this.serializeValueCode(variable), ";"); } + emitFinish([]); return true; } else if (xfer instanceof ArrayEncodingTransformer) { @@ -1354,23 +1400,23 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { switch (xfer.sourceType.kind) { case "date-time": return this.emitConsume( - [variable, '.ToString("o", System.Globalization.CultureInfo.InvariantCulture)'], + [variable, ".ToString(\"o\", System.Globalization.CultureInfo.InvariantCulture)"], xfer.consumer, targetType, - emitFinish + emitFinish, ); case "uuid": return this.emitConsume( - [variable, '.ToString("D", System.Globalization.CultureInfo.InvariantCulture)'], + [variable, ".ToString(\"D\", System.Globalization.CultureInfo.InvariantCulture)"], xfer.consumer, targetType, - emitFinish + emitFinish, ); case "integer": case "uri": return this.emitConsume([variable, ".ToString()"], xfer.consumer, targetType, emitFinish); case "bool": - this.emitLine("var boolString = ", variable, ' ? "true" : "false";'); + this.emitLine("var boolString = ", variable, " ? \"true\" : \"false\";"); return this.emitConsume("boolString", xfer.consumer, targetType, emitFinish); default: return panic(`Stringifying ${xfer.sourceType.kind} not supported`); @@ -1386,9 +1432,11 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { if (min !== undefined) { conditions.push([variable, ".Length >= ", min.toString()]); } + if (max !== undefined) { conditions.push([variable, ".Length <= ", max.toString()]); } + this.emitLine("if (", arrayIntercalate([" && "], conditions), ")"); this.emitBlock(() => this.emitConsume(variable, xfer.consumer, targetType, emitFinish)); return false; @@ -1400,9 +1448,11 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { if (min !== undefined) { conditions.push([variable, " >= ", min.toString()]); } + if (max !== undefined) { conditions.push([variable, " <= ", max.toString()]); } + this.emitLine("if (", arrayIntercalate([" && "], conditions), ")"); this.emitBlock(() => this.emitConsume(variable, xfer.consumer, targetType, emitFinish)); return false; @@ -1410,6 +1460,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { if (!(targetType instanceof UnionType)) { return panic("Union instantiation transformer must produce a union type"); } + const maybeNullable = nullableFromUnion(targetType); if (maybeNullable !== null) { emitFinish(variable); @@ -1422,16 +1473,19 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { const memberName = this.nameForUnionMember(targetType, xfer.sourceType); initializer = [" ", memberName, " = ", variable, " "]; } + emitFinish(["new ", unionName, " {", initializer, "}"]); } + return true; } else { return panic("Unknown transformer"); } + return false; } - private emitTransformation(converterName: Name, t: Type): void { + private emitTransformation (converterName: Name, t: Type): void { const xf = defined(transformationForType(t)); const reverse = xf.reverse; const targetType = xf.targetType; @@ -1443,6 +1497,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { if (haveNullable) { canConvertExpr = [canConvertExpr, " || t == typeof(", csType, "?)"]; } + this.emitCanConvert(canConvertExpr); this.ensureBlankLine(); this.emitReadJson(() => { @@ -1458,7 +1513,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { const allHandled = this.emitDecodeTransformer(xfer, targetType, v => this.emitLine("return ", v, ";")); if (!allHandled) { - this.emitThrow(['"Cannot unmarshal type ', csType, '"']); + this.emitThrow(["\"Cannot unmarshal type ", csType, "\""]); } }); this.ensureBlankLine(); @@ -1471,12 +1526,13 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { this.emitLine("return;"); }); } + this.emitLine("var value = (", csType, ")untypedValue;"); const allHandled = this.emitTransformer("value", reverse.transformer, reverse.targetType, () => - this.emitLine("return;") + this.emitLine("return;"), ); if (!allHandled) { - this.emitThrow(['"Cannot marshal type ', csType, '"']); + this.emitThrow(["\"Cannot marshal type ", csType, "\""]); } }); this.ensureBlankLine(); @@ -1484,20 +1540,21 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { }); } - protected emitRequiredHelpers(): void { + protected emitRequiredHelpers (): void { if (this._needHelpers) { this.forEachTopLevel("leading-and-interposing", (t, n) => this.emitFromJsonForTopLevel(t, n)); this.ensureBlankLine(); this.emitSerializeClass(); } - if (this._needHelpers || (this._needAttributes && (this.haveNamedUnions || this.haveEnums))) { + + if (this._needHelpers || this._needAttributes && (this.haveNamedUnions || this.haveEnums)) { this.ensureBlankLine(); this.emitConverterClass(); this.forEachTransformation("leading-and-interposing", (n, t) => this.emitTransformation(n, t)); } } - protected needNamespace(): boolean { + protected needNamespace (): boolean { return this._needNamespaces; } } @@ -1508,13 +1565,15 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { private readonly _enumExtensionsNames = new Map(); private readonly _needHelpers: boolean; + private readonly _needAttributes: boolean; + private readonly _needNamespaces: boolean; - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues + private readonly _options: OptionValues, ) { super(targetLanguage, renderContext, _options); this._needHelpers = _options.features.helpers; @@ -1522,7 +1581,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { this._needNamespaces = _options.features.namespaces; } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace (): string[] { const forbidden = [ "Converter", "JsonConverter", @@ -1535,47 +1594,51 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { // "MetadataPropertyHandling", // "DateParseHandling", "FromJson", - "Required" + "Required", ]; if (this._options.dense) { forbidden.push("J", "R", "N"); } + if (this._options.baseclass !== undefined) { forbidden.push(this._options.baseclass); } + return super.forbiddenNamesForGlobalNamespace().concat(forbidden); } - protected forbiddenForObjectProperties(c: ClassType, className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties (c: ClassType, className: Name): ForbiddenWordsInfo { const result = super.forbiddenForObjectProperties(c, className); result.names = result.names.concat(["ToJson", "FromJson", "Required"]); return result; } - protected makeNameForTransformation(xf: Transformation, typeName: Name | undefined): Name { + protected makeNameForTransformation (xf: Transformation, typeName: Name | undefined): Name { if (typeName === undefined) { let xfer = xf.transformer; if (xfer instanceof DecodingTransformer && xfer.consumer !== undefined) { xfer = xfer.consumer; } + return new SimpleName([`${xfer.kind}_converter`], namingFunction, inferredNameOrder + 30); } + return new DependencyName(namingFunction, typeName.order + 30, lookup => `${lookup(typeName)}_converter`); } - protected makeNamedTypeDependencyNames(t: Type, name: Name): DependencyName[] { + protected makeNamedTypeDependencyNames (t: Type, name: Name): DependencyName[] { if (!(t instanceof EnumType)) return []; const extensionsName = new DependencyName( namingFunction, name.order + 30, - lookup => `${lookup(name)}_extensions` + lookup => `${lookup(name)}_extensions`, ); this._enumExtensionsNames.set(name, extensionsName); return [extensionsName]; } - protected emitUsings(): void { + protected emitUsings (): void { // FIXME: We need System.Collections.Generic whenever we have maps or use List. if (!this._needAttributes && !this._needHelpers) return; @@ -1591,16 +1654,17 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { // this.emitUsing([denseRequiredEnumName, " = Newtonsoft.Json.Required"]); this.emitUsing([denseNullValueHandlingEnumName, " = System.Text.Json.Serialization.JsonIgnoreCondition"]); } + if (this._options.baseclass === "EntityData") { this.emitUsing("Microsoft.Azure.Mobile.Server"); } } - protected baseclassForType(_t: Type): Sourcelike | undefined { + protected baseclassForType (_t: Type): Sourcelike | undefined { return this._options.baseclass; } - protected emitDefaultFollowingComments(): void { + protected emitDefaultFollowingComments (): void { if (!this._needHelpers) return; this.emitLine("#pragma warning restore CS8618"); @@ -1608,7 +1672,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { this.emitLine("#pragma warning restore CS8603"); } - protected emitDefaultLeadingComments(): void { + protected emitDefaultLeadingComments (): void { if (!this._needHelpers) return; this.emitLine("// "); @@ -1616,7 +1680,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { this.emitLine( "// To parse this JSON data, add NuGet 'System.Text.Json' then do", this.topLevels.size === 1 ? "" : " one of these", - ":" + ":", ); this.emitLine("//"); this.emitLine("// using ", this._options.namespace, ";"); @@ -1628,6 +1692,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { } else { rhs = [topLevelName, ".FromJson(jsonString)"]; } + this.emitLine("// var ", modifySource(camelCase, topLevelName), " = ", rhs, ";"); }); @@ -1638,7 +1703,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { this.emitLine("#pragma warning disable CS8603"); } - private converterForType(t: Type): Name | undefined { + private converterForType (t: Type): Name | undefined { let xf = transformationForType(t); if (xf === undefined && t instanceof UnionType) { @@ -1656,11 +1721,11 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { return defined(this.nameForTransformation(t)); } - protected attributesForProperty( + protected attributesForProperty ( property: ClassProperty, _name: Name, _c: ClassType, - jsonName: string + jsonName: string, ): Sourcelike[] | undefined { if (!this._needAttributes) return undefined; @@ -1689,7 +1754,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { // required = [", Required = ", requiredClass, ".Always", nullValueHandling]; // } - attributes.push(["[", jsonPropertyName, '("', escapedName, '")]']); + attributes.push(["[", jsonPropertyName, "(\"", escapedName, "\")]"]); const converter = this.converterForType(property.type); if (converter !== undefined) { @@ -1699,16 +1764,16 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { return attributes; } - protected blankLinesBetweenAttributes(): boolean { + protected blankLinesBetweenAttributes (): boolean { return this._needAttributes && !this._options.dense; } // The "this" type can't be `dynamic`, so we have to force it to `object`. - private topLevelResultType(t: Type): Sourcelike { + private topLevelResultType (t: Type): Sourcelike { return t.kind === "any" || t.kind === "none" ? "object" : this.csType(t); } - private emitFromJsonForTopLevel(t: Type, name: Name): void { + private emitFromJsonForTopLevel (t: Type, name: Name): void { if (t instanceof EnumType) return; let partial: string; @@ -1721,30 +1786,31 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { partial = ""; typeKind = "class"; } + const csType = this.topLevelResultType(t); this.emitType(undefined, AccessModifier.Public, [partial, typeKind], name, this.baseclassForType(t), () => { // FIXME: Make FromJson a Named this.emitExpressionMember( ["public static ", csType, " FromJson(string json)"], - ["JsonSerializer.Deserialize<", csType, ">(json, ", this._options.namespace, ".Converter.Settings)"] + ["JsonSerializer.Deserialize<", csType, ">(json, ", this._options.namespace, ".Converter.Settings)"], ); }); } - private emitDecoderSwitch(emitBody: () => void): void { + private emitDecoderSwitch (emitBody: () => void): void { this.emitLine("switch (reader.TokenType)"); this.emitBlock(emitBody); } - private emitTokenCase(tokenType: string): void { + private emitTokenCase (tokenType: string): void { this.emitLine("case JsonTokenType.", tokenType, ":"); } - private emitThrow(message: Sourcelike): void { + private emitThrow (message: Sourcelike): void { this.emitLine("throw new Exception(", message, ");"); } - private deserializeTypeCode(typeName: Sourcelike): Sourcelike { + private deserializeTypeCode (typeName: Sourcelike): Sourcelike { switch (typeName) { case "bool": return ["reader.GetBoolean()"]; @@ -1761,12 +1827,12 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { } } - private serializeValueCode(value: Sourcelike): Sourcelike { + private serializeValueCode (value: Sourcelike): Sourcelike { if (value !== "null") return ["JsonSerializer.Serialize(writer, ", value, ", options)"]; else return ["writer.WriteNullValue()"]; } - private emitSerializeClass(): void { + private emitSerializeClass (): void { // FIXME: Make Serialize a Named this.emitType(undefined, AccessModifier.Public, "static class", "Serialize", undefined, () => { // Sometimes multiple top-levels will resolve to the same type, so we have to take care @@ -1778,49 +1844,49 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { seenTypes.add(t); this.emitExpressionMember( ["public static string ToJson(this ", this.topLevelResultType(t), " self)"], - ["JsonSerializer.Serialize(self, ", this._options.namespace, ".Converter.Settings)"] + ["JsonSerializer.Serialize(self, ", this._options.namespace, ".Converter.Settings)"], ); } }); }); } - private emitCanConvert(expr: Sourcelike): void { + private emitCanConvert (expr: Sourcelike): void { this.emitExpressionMember("public override bool CanConvert(Type t)", expr); } - private emitReadJson(emitBody: () => void, csType: Sourcelike): void { + private emitReadJson (emitBody: () => void, csType: Sourcelike): void { this.emitLine( "public override ", csType, - " Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)" + " Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)", ); this.emitBlock(emitBody); } - private emitWriteJson(variable: string, emitBody: () => void, csType: Sourcelike): void { + private emitWriteJson (variable: string, emitBody: () => void, csType: Sourcelike): void { this.emitLine( "public override void Write(Utf8JsonWriter writer, ", csType, " ", variable, - ", JsonSerializerOptions options)" + ", JsonSerializerOptions options)", ); this.emitBlock(emitBody); } - private converterObject(converterName: Name): Sourcelike { + private converterObject (converterName: Name): Sourcelike { // FIXME: Get a singleton return [converterName, ".Singleton"]; } - private emitConverterClass(): void { + private emitConverterClass (): void { // FIXME: Make Converter a Named const converterName: Sourcelike = ["Converter"]; this.emitType(undefined, AccessModifier.Internal, "static class", converterName, undefined, () => { // Do not use .Web as defaults. That turns on caseInsensitive property names and will fail the keywords test. this.emitLine( - "public static readonly JsonSerializerOptions Settings = new(JsonSerializerDefaults.General)" + "public static readonly JsonSerializerOptions Settings = new(JsonSerializerDefaults.General)", ); this.emitBlock(() => { // this.emitLine("MetadataPropertyHandling = MetadataPropertyHandling.Ignore,"); @@ -1833,28 +1899,30 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { this.emitLine(this.converterObject(converter), ","); } } + this.emitLine("new DateOnlyConverter(),"); this.emitLine("new TimeOnlyConverter(),"); this.emitLine("IsoDateTimeOffsetConverter.Singleton"); // this.emitLine("new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }"); }); - this.emitLine(`},`); + this.emitLine("},"); }, true); }); } - private emitDecoderTransformerCase( + private emitDecoderTransformerCase ( tokenCases: string[], variableName: string, xfer: Transformer | undefined, targetType: Type, - emitFinish: (value: Sourcelike) => void + emitFinish: (value: Sourcelike) => void, ): void { if (xfer === undefined) return; for (const tokenCase of tokenCases) { this.emitTokenCase(tokenCase); } + this.indent(() => { const allHandled = this.emitDecodeTransformer(xfer, targetType, emitFinish, variableName); if (!allHandled) { @@ -1863,11 +1931,11 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { }); } - private emitConsume( + private emitConsume ( value: Sourcelike, consumer: Transformer | undefined, targetType: Type, - emitFinish: (variableName: Sourcelike) => void + emitFinish: (variableName: Sourcelike) => void, ): boolean { if (consumer === undefined) { emitFinish(value); @@ -1877,11 +1945,11 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { } } - private emitDecodeTransformer( + private emitDecodeTransformer ( xfer: Transformer, targetType: Type, emitFinish: (value: Sourcelike) => void, - variableName = "value" + variableName = "value", ): boolean { if (xfer instanceof DecodingTransformer) { const source = xfer.sourceType; @@ -1896,18 +1964,20 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { typeSource, ")converter.ReadJson(reader, typeof(", typeSource, - "), null, serializer);" + "), null, serializer);", ); } else if (source.kind !== "null") { let output = targetType.kind === "double" ? targetType : source; this.emitLine("var ", variableName, " = ", this.deserializeTypeCode(this.csType(output)), ";"); } + return this.emitConsume(variableName, xfer.consumer, targetType, emitFinish); } else if (xfer instanceof ArrayDecodingTransformer) { // FIXME: Consume StartArray if (!(targetType instanceof ArrayType)) { return panic("Array decoding must produce an array type"); } + // FIXME: handle EOF this.emitLine("reader.Read();"); this.emitLine("var ", variableName, " = new List<", this.csType(targetType.items), ">();"); @@ -1917,7 +1987,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { xfer.itemTransformer, xfer.itemTargetType, v => this.emitLine(variableName, ".Add(", v, ");"), - "arrayItem" + "arrayItem", ); // FIXME: handle EOF this.emitLine("reader.Read();"); @@ -1926,6 +1996,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { if (!this._options.useList) { result = [result, ".ToArray()"]; } + emitFinish(result); return true; } else if (xfer instanceof DecodingChoiceTransformer) { @@ -1940,12 +2011,13 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { } }); } + this.emitDecoderTransformerCase( ["Number"], "integerValue", xfer.integerTransformer, targetType, - emitFinish + emitFinish, ); this.emitDecoderTransformerCase( ["Number"], @@ -1953,14 +2025,14 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { "doubleValue", xfer.doubleTransformer, targetType, - emitFinish + emitFinish, ); this.emitDecoderTransformerCase( ["True", "False"], "boolValue", xfer.boolTransformer, targetType, - emitFinish + emitFinish, ); this.emitDecoderTransformerCase( // ["String", "Date"], @@ -1968,21 +2040,21 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { "stringValue", xfer.stringTransformer, targetType, - emitFinish + emitFinish, ); this.emitDecoderTransformerCase( ["StartObject"], "objectValue", xfer.objectTransformer, targetType, - emitFinish + emitFinish, ); this.emitDecoderTransformerCase( ["StartArray"], "arrayValue", xfer.arrayTransformer, targetType, - emitFinish + emitFinish, ); }); return false; @@ -1991,25 +2063,27 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { } } - private stringCaseValue(t: Type, stringCase: string): Sourcelike { + private stringCaseValue (t: Type, stringCase: string): Sourcelike { if (t.kind === "string") { - return ['"', utf16StringEscape(stringCase), '"']; + return ["\"", utf16StringEscape(stringCase), "\""]; } else if (t instanceof EnumType) { return [this.nameForNamedType(t), ".", this.nameForEnumCase(t, stringCase)]; } + return panic(`Type ${t.kind} does not have string cases`); } - private emitTransformer( + private emitTransformer ( variable: Sourcelike, xfer: Transformer, targetType: Type, - emitFinish: (value: Sourcelike) => void + emitFinish: (value: Sourcelike) => void, ): boolean { - function directTargetType(continuation: Transformer | undefined): Type { + function directTargetType (continuation: Transformer | undefined): Type { if (continuation === undefined) { return targetType; } + return followTargetType(continuation.sourceType); } @@ -2022,7 +2096,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { const matchXfer = caseXfer as StringMatchTransformer; const value = this.stringCaseValue( followTargetType(matchXfer.sourceType), - matchXfer.stringCase + matchXfer.stringCase, ); this.emitLine("case ", value, ":"); this.indent(() => { @@ -2030,7 +2104,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { variable, matchXfer.transformer, targetType, - emitFinish + emitFinish, ); if (!allDone) { this.emitLine("break;"); @@ -2066,9 +2140,11 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { member = [variable, ".", memberName]; test = [member, " != null"]; } + if (memberType.kind !== "null" && isValueType(memberType)) { member = [member, ".Value"]; } + this.emitLine("if (", test, ")"); this.emitBlock(() => this.emitTransformer(member, xfer.transformer, targetType, emitFinish)); } else if (xfer instanceof StringMatchTransformer) { @@ -2083,6 +2159,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { } else { this.emitLine(this.serializeValueCode(variable), ";"); } + emitFinish([]); return true; } else if (xfer instanceof ArrayEncodingTransformer) { @@ -2115,7 +2192,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { this.emitBlock(() => { // this.emitLine("var uri = new Uri(", variable, ");"); // The default value about:blank should never happen, but this way we avoid a null reference warning. - this.emitLine('var uri = new Uri("about:blank");'); + this.emitLine("var uri = new Uri(\"about:blank\");"); this.emitLine("if (!string.IsNullOrEmpty(stringValue))"); this.emitBlock(() => { this.emitLine("uri = new Uri(", variable, ");"); @@ -2141,23 +2218,23 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { switch (xfer.sourceType.kind) { case "date-time": return this.emitConsume( - [variable, '.ToString("o", System.Globalization.CultureInfo.InvariantCulture)'], + [variable, ".ToString(\"o\", System.Globalization.CultureInfo.InvariantCulture)"], xfer.consumer, targetType, - emitFinish + emitFinish, ); case "uuid": return this.emitConsume( - [variable, '.ToString("D", System.Globalization.CultureInfo.InvariantCulture)'], + [variable, ".ToString(\"D\", System.Globalization.CultureInfo.InvariantCulture)"], xfer.consumer, targetType, - emitFinish + emitFinish, ); case "integer": case "uri": return this.emitConsume([variable, ".ToString()"], xfer.consumer, targetType, emitFinish); case "bool": - this.emitLine("var boolString = ", variable, ' ? "true" : "false";'); + this.emitLine("var boolString = ", variable, " ? \"true\" : \"false\";"); return this.emitConsume("boolString", xfer.consumer, targetType, emitFinish); default: return panic(`Stringifying ${xfer.sourceType.kind} not supported`); @@ -2173,9 +2250,11 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { if (min !== undefined) { conditions.push([variable, ".Length >= ", min.toString()]); } + if (max !== undefined) { conditions.push([variable, ".Length <= ", max.toString()]); } + this.emitLine("if (", arrayIntercalate([" && "], conditions), ")"); this.emitBlock(() => this.emitConsume(variable, xfer.consumer, targetType, emitFinish)); return false; @@ -2187,9 +2266,11 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { if (min !== undefined) { conditions.push([variable, " >= ", min.toString()]); } + if (max !== undefined) { conditions.push([variable, " <= ", max.toString()]); } + this.emitLine("if (", arrayIntercalate([" && "], conditions), ")"); this.emitBlock(() => this.emitConsume(variable, xfer.consumer, targetType, emitFinish)); return false; @@ -2197,6 +2278,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { if (!(targetType instanceof UnionType)) { return panic("Union instantiation transformer must produce a union type"); } + const maybeNullable = nullableFromUnion(targetType); if (maybeNullable !== null) { emitFinish(variable); @@ -2209,16 +2291,19 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { const memberName = this.nameForUnionMember(targetType, xfer.sourceType); initializer = [" ", memberName, " = ", variable, " "]; } + emitFinish(["new ", unionName, " {", initializer, "}"]); } + return true; } else { return panic("Unknown transformer"); } + return false; } - private emitTransformation(converterName: Name, t: Type): void { + private emitTransformation (converterName: Name, t: Type): void { const xf = defined(transformationForType(t)); const reverse = xf.reverse; const targetType = xf.targetType; @@ -2252,10 +2337,10 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { // } const allHandled = this.emitDecodeTransformer(xfer, targetType, v => - this.emitLine("return ", v, ";") + this.emitLine("return ", v, ";"), ); if (!allHandled) { - this.emitThrow(['"Cannot unmarshal type ', csType, '"']); + this.emitThrow(["\"Cannot unmarshal type ", csType, "\""]); } }, csType); this.ensureBlankLine(); @@ -2272,27 +2357,28 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { // } const allHandled = this.emitTransformer("value", reverse.transformer, reverse.targetType, () => - this.emitLine("return;") + this.emitLine("return;"), ); if (!allHandled) { - this.emitThrow(['"Cannot marshal type ', csType, '"']); + this.emitThrow(["\"Cannot marshal type ", csType, "\""]); } }, - csType + csType, ); this.ensureBlankLine(); this.emitLine("public static readonly ", converterName, " Singleton = new ", converterName, "();"); - } + }, ); } - protected emitRequiredHelpers(): void { + protected emitRequiredHelpers (): void { if (this._needHelpers) { this.forEachTopLevel("leading-and-interposing", (t, n) => this.emitFromJsonForTopLevel(t, n)); this.ensureBlankLine(); this.emitSerializeClass(); } - if (this._needHelpers || (this._needAttributes && (this.haveNamedUnions || this.haveEnums))) { + + if (this._needHelpers || this._needAttributes && (this.haveNamedUnions || this.haveEnums)) { this.ensureBlankLine(); this.emitConverterClass(); this.forEachTransformation("leading-and-interposing", (n, t) => this.emitTransformation(n, t)); @@ -2409,7 +2495,7 @@ internal class IsoDateTimeOffsetConverter : JsonConverter } } - protected needNamespace(): boolean { + protected needNamespace (): boolean { return this._needNamespaces; } } diff --git a/packages/quicktype-core/src/language/Crystal.ts b/packages/quicktype-core/src/language/Crystal.ts index 3b469fe15..61fcd28c9 100644 --- a/packages/quicktype-core/src/language/Crystal.ts +++ b/packages/quicktype-core/src/language/Crystal.ts @@ -1,5 +1,6 @@ import { TargetLanguage } from "../TargetLanguage"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { ConvenienceRenderer } from "../ConvenienceRenderer"; import { legalizeCharacters, splitIntoWords, @@ -12,30 +13,32 @@ import { escapeNonPrintableMapper, isPrintable, isAscii, - isLetterOrUnderscore + isLetterOrUnderscore, } from "../support/Strings"; -import { Name, Namer, funPrefixNamer } from "../Naming"; -import { UnionType, Type, ClassType, EnumType } from "../Type"; +import { type Name, type Namer} from "../Naming"; +import { funPrefixNamer } from "../Naming"; +import { type UnionType, type Type, type ClassType, type EnumType } from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { Sourcelike, maybeAnnotated } from "../Source"; +import { type Sourcelike} from "../Source"; +import { maybeAnnotated } from "../Source"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { Option } from "../RendererOptions"; -import { RenderContext } from "../Renderer"; +import { type Option } from "../RendererOptions"; +import { type RenderContext } from "../Renderer"; export class CrystalTargetLanguage extends TargetLanguage { - protected makeRenderer(renderContext: RenderContext): CrystalRenderer { + protected makeRenderer (renderContext: RenderContext): CrystalRenderer { return new CrystalRenderer(this, renderContext); } - constructor() { + constructor () { super("Crystal", ["crystal", "cr", "crystallang"], "cr"); } - protected get defaultIndentation(): string { + protected get defaultIndentation (): string { return " "; } - protected getOptions(): Option[] { + protected getOptions (): Array> { return []; } } @@ -176,26 +179,28 @@ const keywords = [ "when", "while", "with", - "yield" + "yield", ]; -function isAsciiLetterOrUnderscoreOrDigit(codePoint: number): boolean { +function isAsciiLetterOrUnderscoreOrDigit (codePoint: number): boolean { if (!isAscii(codePoint)) { return false; } + return isLetterOrUnderscoreOrDigit(codePoint); } -function isAsciiLetterOrUnderscore(codePoint: number): boolean { +function isAsciiLetterOrUnderscore (codePoint: number): boolean { if (!isAscii(codePoint)) { return false; } + return isLetterOrUnderscore(codePoint); } const legalizeName = legalizeCharacters(isAsciiLetterOrUnderscoreOrDigit); -function crystalStyle(original: string, isSnakeCase: boolean): string { +function crystalStyle (original: string, isSnakeCase: boolean): string { const words = splitIntoWords(original); const wordStyle = isSnakeCase ? allLowerWordStyle : firstUpperWordStyle; @@ -208,7 +213,7 @@ function crystalStyle(original: string, isSnakeCase: boolean): string { wordStyle, wordStyle, isSnakeCase ? "_" : "", - isAsciiLetterOrUnderscore + isAsciiLetterOrUnderscore, ); return combined === "_" ? "_underscore" : combined; @@ -217,7 +222,7 @@ function crystalStyle(original: string, isSnakeCase: boolean): string { const snakeNamingFunction = funPrefixNamer("default", (original: string) => crystalStyle(original, true)); const camelNamingFunction = funPrefixNamer("camel", (original: string) => crystalStyle(original, false)); -function standardUnicodeCrystalEscape(codePoint: number): string { +function standardUnicodeCrystalEscape (codePoint: number): string { if (codePoint <= 0xffff) { return "\\u{" + intToHex(codePoint, 4) + "}"; } else { @@ -228,56 +233,56 @@ function standardUnicodeCrystalEscape(codePoint: number): string { const crystalStringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, standardUnicodeCrystalEscape)); export class CrystalRenderer extends ConvenienceRenderer { - constructor(targetLanguage: TargetLanguage, renderContext: RenderContext) { + constructor (targetLanguage: TargetLanguage, renderContext: RenderContext) { super(targetLanguage, renderContext); } - protected makeNamedTypeNamer(): Namer { + protected makeNamedTypeNamer (): Namer { return camelNamingFunction; } - protected namerForObjectProperty(): Namer | null { + protected namerForObjectProperty (): Namer | null { return snakeNamingFunction; } - protected makeUnionMemberNamer(): Namer | null { + protected makeUnionMemberNamer (): Namer | null { return camelNamingFunction; } - protected makeEnumCaseNamer(): Namer | null { + protected makeEnumCaseNamer (): Namer | null { return camelNamingFunction; } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace (): string[] { return keywords; } - protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties (_c: ClassType, _className: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { + protected forbiddenForUnionMembers (_u: UnionType, _unionName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { + protected forbiddenForEnumCases (_e: EnumType, _enumName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected get commentLineStart(): string { + protected get commentLineStart (): string { return "# "; } - private nullableCrystalType(t: Type, withIssues: boolean): Sourcelike { + private nullableCrystalType (t: Type, withIssues: boolean): Sourcelike { return [this.crystalType(t, withIssues), "?"]; } - protected isImplicitCycleBreaker(t: Type): boolean { + protected isImplicitCycleBreaker (t: Type): boolean { const kind = t.kind; return kind === "array" || kind === "map"; } - private crystalType(t: Type, withIssues = false): Sourcelike { + private crystalType (t: Type, withIssues = false): Sourcelike { return matchType( t, _anyType => maybeAnnotated(withIssues, anyTypeIssueAnnotation, "JSON::Any?"), @@ -300,23 +305,23 @@ export class CrystalRenderer extends ConvenienceRenderer { const name = this.nameForNamedType(unionType); return hasNull !== null ? ([name, "?"] as Sourcelike) : name; - } + }, ); } - private breakCycle(t: Type, withIssues: boolean): Sourcelike { + private breakCycle (t: Type, withIssues: boolean): Sourcelike { return this.crystalType(t, withIssues); } - private emitRenameAttribute(propName: Name, jsonName: string): void { + private emitRenameAttribute (propName: Name, jsonName: string): void { const escapedName = crystalStringEscape(jsonName); const namesDiffer = this.sourcelikeToString(propName) !== escapedName; if (namesDiffer) { - this.emitLine('@[JSON::Field(key: "', escapedName, '")]'); + this.emitLine("@[JSON::Field(key: \"", escapedName, "\")]"); } } - protected emitStructDefinition(c: ClassType, className: Name): void { + protected emitStructDefinition (c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); const structBody = () => @@ -330,7 +335,7 @@ export class CrystalRenderer extends ConvenienceRenderer { this.emitBlock(["class ", className], structBody); } - protected emitBlock(line: Sourcelike, f: () => void): void { + protected emitBlock (line: Sourcelike, f: () => void): void { this.emitLine(line); this.indent(() => { this.emitLine("include JSON::Serializable"); @@ -340,13 +345,13 @@ export class CrystalRenderer extends ConvenienceRenderer { this.emitLine("end"); } - protected emitEnum(line: Sourcelike, f: () => void): void { + protected emitEnum (line: Sourcelike, f: () => void): void { this.emitLine(line); this.indent(f); this.emitLine("end"); } - protected emitUnion(u: UnionType, unionName: Name): void { + protected emitUnion (u: UnionType, unionName: Name): void { const isMaybeWithSingleType = nullableFromUnion(u); if (isMaybeWithSingleType !== null) { @@ -367,30 +372,30 @@ export class CrystalRenderer extends ConvenienceRenderer { "alias ", unionName, " = ", - types.map(r => r.map(sl => this.sourcelikeToString(sl))).join(" | ") + types.map(r => r.map(sl => this.sourcelikeToString(sl))).join(" | "), ]); } - protected emitTopLevelAlias(t: Type, name: Name): void { + protected emitTopLevelAlias (t: Type, name: Name): void { this.emitLine("alias ", name, " = ", this.crystalType(t)); } - protected emitLeadingComments(): void { + protected emitLeadingComments (): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); return; } } - protected emitSourceStructure(): void { + protected emitSourceStructure (): void { this.emitLeadingComments(); this.ensureBlankLine(); - this.emitLine('require "json"'); + this.emitLine("require \"json\""); this.forEachTopLevel( "leading", (t, name) => this.emitTopLevelAlias(t, name), - t => this.namedTypeToNameForTopLevel(t) === undefined + t => this.namedTypeToNameForTopLevel(t) === undefined, ); this.forEachObject("leading-and-interposing", (c: ClassType, name: Name) => this.emitStructDefinition(c, name)); diff --git a/packages/quicktype-core/src/language/Dart.ts b/packages/quicktype-core/src/language/Dart.ts index 6dc40ead6..308d8091b 100644 --- a/packages/quicktype-core/src/language/Dart.ts +++ b/packages/quicktype-core/src/language/Dart.ts @@ -1,14 +1,17 @@ import { - ClassProperty, - ClassType, + type ClassProperty, + type ClassType, + type PrimitiveStringTypeKind, + type TransformedStringTypeKind, + type Type, + type UnionType, +} from "../Type"; +import { EnumType, - PrimitiveStringTypeKind, - TransformedStringTypeKind, - Type, - UnionType } from "../Type"; import { directlyReachableSingleNamedType, matchType, nullableFromUnion } from "../TypeUtils"; -import { maybeAnnotated, modifySource, Sourcelike } from "../Source"; +import { type Sourcelike } from "../Source"; +import { maybeAnnotated, modifySource } from "../Source"; import { allLowerWordStyle, allUpperWordStyle, @@ -24,18 +27,21 @@ import { splitIntoWords, standardUnicodeHexEscape, utf16ConcatMap, - utf16LegalizeCharacters + utf16LegalizeCharacters, } from "../support/Strings"; -import { StringTypeMapping } from "../TypeBuilder"; +import { type StringTypeMapping } from "../TypeBuilder"; -import { DependencyName, funPrefixNamer, Name, Namer } from "../Naming"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { type Name, type Namer } from "../Naming"; +import { DependencyName, funPrefixNamer } from "../Naming"; +import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { ConvenienceRenderer } from "../ConvenienceRenderer"; import { TargetLanguage } from "../TargetLanguage"; -import { BooleanOption, getOptionValues, Option, OptionValues, StringOption } from "../RendererOptions"; +import { type Option, type OptionValues} from "../RendererOptions"; +import { BooleanOption, getOptionValues, StringOption } from "../RendererOptions"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; import { defined } from "../support/Support"; -import { RenderContext } from "../Renderer"; +import { type RenderContext } from "../Renderer"; export const dartOptions = { nullSafety: new BooleanOption("null-safety", "Null Safety", true), @@ -49,24 +55,24 @@ export const dartOptions = { "use-freezed", "Generate class definitions with @freezed compatibility", false, - "secondary" + "secondary", ), useHive: new BooleanOption("use-hive", "Generate annotations for Hive type adapters", false, "secondary"), useJsonAnnotation: new BooleanOption( "use-json-annotation", "Generate annotations for json_serializable", false, - "secondary" + "secondary", ), - partName: new StringOption("part-name", "Use this name in `part` directive", "NAME", "", "secondary") + partName: new StringOption("part-name", "Use this name in `part` directive", "NAME", "", "secondary"), }; export class DartTargetLanguage extends TargetLanguage { - constructor() { + constructor () { super("Dart", ["dart"], "dart"); } - protected getOptions(): Option[] { + protected getOptions (): Array> { return [ dartOptions.nullSafety, dartOptions.justTypes, @@ -78,22 +84,22 @@ export class DartTargetLanguage extends TargetLanguage { dartOptions.useFreezed, dartOptions.useHive, dartOptions.useJsonAnnotation, - dartOptions.partName + dartOptions.partName, ]; } - get supportsUnionsWithBothNumberTypes(): boolean { + get supportsUnionsWithBothNumberTypes (): boolean { return true; } - get stringTypeMapping(): StringTypeMapping { + get stringTypeMapping (): StringTypeMapping { const mapping: Map = new Map(); mapping.set("date", "date"); mapping.set("date-time", "date-time"); return mapping; } - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): DartRenderer { + protected makeRenderer (renderContext: RenderContext, untypedOptionValues: { [name: string]: any, }): DartRenderer { const options = getOptionValues(dartOptions, untypedOptionValues); return new DartRenderer(this, renderContext, options); } @@ -168,7 +174,7 @@ const keywords = [ "fromJson", "toJson", "fromMap", - "toMap" + "toMap", ]; const typeNamingFunction = funPrefixNamer("types", n => dartNameStyle(true, false, n)); @@ -177,16 +183,16 @@ const enumCaseNamingFunction = funPrefixNamer("enum-cases", n => dartNameStyle(t // Escape the dollar sign, which is used in string interpolation const stringEscape = utf16ConcatMap( - escapeNonPrintableMapper(cp => isPrintable(cp) && cp !== 0x24, standardUnicodeHexEscape) + escapeNonPrintableMapper(cp => isPrintable(cp) && cp !== 0x24, standardUnicodeHexEscape), ); -function isStartCharacter(codePoint: number): boolean { +function isStartCharacter (codePoint: number): boolean { if (codePoint === 0x5f) return false; // underscore return isAscii(codePoint) && isLetter(codePoint); } -function isPartCharacter(codePoint: number): boolean { - return isStartCharacter(codePoint) || (isAscii(codePoint) && isDigit(codePoint)); +function isPartCharacter (codePoint: number): boolean { + return isStartCharacter(codePoint) || isAscii(codePoint) && isDigit(codePoint); } const legalizeName = utf16LegalizeCharacters(isPartCharacter); @@ -195,13 +201,13 @@ const legalizeName = utf16LegalizeCharacters(isPartCharacter); // we have to use namers to produce the getter and setter names - we can't // just capitalize and concatenate. // https://stackoverflow.com/questions/8277355/naming-convention-for-upper-case-abbreviations -function dartNameStyle(startWithUpper: boolean, upperUnderscore: boolean, original: string): string { +function dartNameStyle (startWithUpper: boolean, upperUnderscore: boolean, original: string): string { const words = splitIntoWords(original); const firstWordStyle = upperUnderscore ? allUpperWordStyle : startWithUpper - ? firstUpperWordStyle - : allLowerWordStyle; + ? firstUpperWordStyle + : allLowerWordStyle; const restWordStyle = upperUnderscore ? allUpperWordStyle : firstUpperWordStyle; return combineWords( words, @@ -211,121 +217,126 @@ function dartNameStyle(startWithUpper: boolean, upperUnderscore: boolean, origin firstWordStyle, restWordStyle, upperUnderscore ? "_" : "", - isStartCharacter + isStartCharacter, ); } -type TopLevelDependents = { - encoder: Name; +interface TopLevelDependents { decoder: Name; -}; + encoder: Name; +} export class DartRenderer extends ConvenienceRenderer { private readonly _gettersAndSettersForPropertyName = new Map(); + private _needEnumValues = false; + private classCounter = 0; + private classPropertyCounter = 0; + private readonly _topLevelDependents = new Map(); + private readonly _enumValues = new Map(); - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues + private readonly _options: OptionValues, ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace (): string[] { return keywords; } - protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties (_c: ClassType, _className: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected makeNamedTypeNamer(): Namer { + protected makeNamedTypeNamer (): Namer { return typeNamingFunction; } - protected namerForObjectProperty(): Namer { + protected namerForObjectProperty (): Namer { return propertyNamingFunction; } - protected makeUnionMemberNamer(): Namer { + protected makeUnionMemberNamer (): Namer { return propertyNamingFunction; } - protected makeEnumCaseNamer(): Namer { + protected makeEnumCaseNamer (): Namer { return enumCaseNamingFunction; } - protected unionNeedsName(u: UnionType): boolean { + protected unionNeedsName (u: UnionType): boolean { return nullableFromUnion(u) === null; } - protected namedTypeToNameForTopLevel(type: Type): Type | undefined { + protected namedTypeToNameForTopLevel (type: Type): Type | undefined { // If the top-level type doesn't contain any classes or unions // we have to define a class just for the `FromJson` method, in // emitFromJsonForTopLevel. return directlyReachableSingleNamedType(type); } - protected get toJson(): string { + protected get toJson (): string { return `to${this._options.methodNamesWithMap ? "Map" : "Json"}`; } - protected get fromJson(): string { + protected get fromJson (): string { return `from${this._options.methodNamesWithMap ? "Map" : "Json"}`; } - protected makeTopLevelDependencyNames(_t: Type, name: Name): DependencyName[] { + protected makeTopLevelDependencyNames (_t: Type, name: Name): DependencyName[] { const encoder = new DependencyName( propertyNamingFunction, name.order, - lookup => `${lookup(name)}_${this.toJson}` + lookup => `${lookup(name)}_${this.toJson}`, ); const decoder = new DependencyName( propertyNamingFunction, name.order, - lookup => `${lookup(name)}_${this.fromJson}` + lookup => `${lookup(name)}_${this.fromJson}`, ); this._topLevelDependents.set(name, { encoder, decoder }); return [encoder, decoder]; } - protected makeNamesForPropertyGetterAndSetter( + protected makeNamesForPropertyGetterAndSetter ( _c: ClassType, _className: Name, _p: ClassProperty, _jsonName: string, - name: Name + name: Name, ): [Name, Name] { const getterName = new DependencyName(propertyNamingFunction, name.order, lookup => `get_${lookup(name)}`); const setterName = new DependencyName(propertyNamingFunction, name.order, lookup => `set_${lookup(name)}`); return [getterName, setterName]; } - protected makePropertyDependencyNames( + protected makePropertyDependencyNames ( c: ClassType, className: Name, p: ClassProperty, jsonName: string, - name: Name + name: Name, ): Name[] { const getterAndSetterNames = this.makeNamesForPropertyGetterAndSetter(c, className, p, jsonName, name); this._gettersAndSettersForPropertyName.set(name, getterAndSetterNames); return getterAndSetterNames; } - protected makeNamedTypeDependencyNames(t: Type, name: Name): DependencyName[] { + protected makeNamedTypeDependencyNames (t: Type, name: Name): DependencyName[] { if (!(t instanceof EnumType)) return []; const enumValue = new DependencyName(propertyNamingFunction, name.order, lookup => `${lookup(name)}_values`); this._enumValues.set(t, enumValue); return [enumValue]; } - protected emitFileHeader(): void { + protected emitFileHeader (): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } @@ -345,12 +356,15 @@ export class DartRenderer extends ConvenienceRenderer { if (this._options.requiredProperties) { this.emitLine("import 'package:meta/meta.dart';"); } + if (this._options.useFreezed) { this.emitLine("import 'package:freezed_annotation/freezed_annotation.dart';"); } + if (this._options.useHive) { this.emitLine("import 'package:hive/hive.dart';"); } + if (this._options.useJsonAnnotation && !this._options.useFreezed) { // The freezed annotatation import already provides the import for json_annotation this.emitLine("import 'package:json_annotation/json_annotation.dart';"); @@ -363,31 +377,32 @@ export class DartRenderer extends ConvenienceRenderer { // FIXME: This should use a `Name`, not `modifySource` const name = modifySource( snakeCase, - optionNameIsEmpty ? [...this.topLevels.keys()][0] : this._options.partName + optionNameIsEmpty ? [...this.topLevels.keys()][0] : this._options.partName, ); if (this._options.useFreezed) { this.emitLine("part '", name, ".freezed.dart';"); } + if (!this._options.justTypes) { this.emitLine("part '", name, ".g.dart';"); } } } - protected emitDescriptionBlock(lines: Sourcelike[]): void { + protected emitDescriptionBlock (lines: Sourcelike[]): void { this.emitCommentLines(lines, { lineStart: "///", beforeComment: "" }); } - protected emitBlock(line: Sourcelike, f: () => void): void { + protected emitBlock (line: Sourcelike, f: () => void): void { this.emitLine(line, " {"); this.indent(f); this.emitLine("}"); } - protected dartType(t: Type, withIssues = false, forceNullable = false): Sourcelike { + protected dartType (t: Type, withIssues = false, forceNullable = false): Sourcelike { const nullable = - forceNullable || (this._options.nullSafety && t.isNullable && !this._options.requiredProperties); - const withNullable = (s: Sourcelike): Sourcelike => (nullable ? [s, "?"] : s); + forceNullable || this._options.nullSafety && t.isNullable && !this._options.requiredProperties; + const withNullable = (s: Sourcelike): Sourcelike => nullable ? [s, "?"] : s; return matchType( t, _anyType => maybeAnnotated(withIssues, anyTypeIssueAnnotation, "dynamic"), @@ -405,6 +420,7 @@ export class DartRenderer extends ConvenienceRenderer { if (maybeNullable === null) { return "dynamic"; } + return withNullable(this.dartType(maybeNullable, withIssues)); }, transformedStringType => { @@ -415,25 +431,27 @@ export class DartRenderer extends ConvenienceRenderer { default: return withNullable("String"); } - } + }, ); } - protected mapList(isNullable: boolean, itemType: Sourcelike, list: Sourcelike, mapper: Sourcelike): Sourcelike { + protected mapList (isNullable: boolean, itemType: Sourcelike, list: Sourcelike, mapper: Sourcelike): Sourcelike { if (this._options.nullSafety && isNullable && !this._options.requiredProperties) { return [list, " == null ? [] : ", "List<", itemType, ">.from(", list, "!.map((x) => ", mapper, "))"]; } + return ["List<", itemType, ">.from(", list, ".map((x) => ", mapper, "))"]; } - protected mapMap(isNullable: boolean, valueType: Sourcelike, map: Sourcelike, valueMapper: Sourcelike): Sourcelike { + protected mapMap (isNullable: boolean, valueType: Sourcelike, map: Sourcelike, valueMapper: Sourcelike): Sourcelike { if (this._options.nullSafety && isNullable && !this._options.requiredProperties) { return ["Map.from(", map, "!).map((k, v) => MapEntry(k, ", valueMapper, "))"]; } + return ["Map.from(", map, ").map((k, v) => MapEntry(k, ", valueMapper, "))"]; } - protected mapClass(isNullable: boolean, classType: ClassType, dynamic: Sourcelike) { + protected mapClass (isNullable: boolean, classType: ClassType, dynamic: Sourcelike) { if (this._options.nullSafety && isNullable && !this._options.requiredProperties) { return [ dynamic, @@ -443,16 +461,17 @@ export class DartRenderer extends ConvenienceRenderer { this.fromJson, "(", dynamic, - ")" + ")", ]; } + return [this.nameForNamedType(classType), ".", this.fromJson, "(", dynamic, ")"]; } - //If the first time is the unionType type, after nullableFromUnion conversion, - //the isNullable property will become false, which is obviously wrong, - //so add isNullable property - protected fromDynamicExpression(isNullable: boolean = false, t: Type, ...dynamic: Sourcelike[]): Sourcelike { + // If the first time is the unionType type, after nullableFromUnion conversion, + // the isNullable property will become false, which is obviously wrong, + // so add isNullable property + protected fromDynamicExpression (isNullable: boolean = false, t: Type, ...dynamic: Sourcelike[]): Sourcelike { return matchType( t, _anyType => dynamic, @@ -466,7 +485,7 @@ export class DartRenderer extends ConvenienceRenderer { isNullable || arrayType.isNullable, this.dartType(arrayType.items), dynamic, - this.fromDynamicExpression(arrayType.items.isNullable, arrayType.items, "x") + this.fromDynamicExpression(arrayType.items.isNullable, arrayType.items, "x"), ), classType => this.mapClass(isNullable || classType.isNullable, classType, dynamic), mapType => @@ -474,14 +493,14 @@ export class DartRenderer extends ConvenienceRenderer { mapType.isNullable || isNullable, this.dartType(mapType.values), dynamic, - this.fromDynamicExpression(mapType.values.isNullable, mapType.values, "v") + this.fromDynamicExpression(mapType.values.isNullable, mapType.values, "v"), ), enumType => { return [ defined(this._enumValues.get(enumType)), ".map[", dynamic, - this._options.nullSafety ? "]!" : "]" + this._options.nullSafety ? "]!" : "]", ]; }, unionType => { @@ -489,6 +508,7 @@ export class DartRenderer extends ConvenienceRenderer { if (maybeNullable === null) { return dynamic; } + return this.fromDynamicExpression(unionType.isNullable, maybeNullable, dynamic); }, transformedStringType => { @@ -502,18 +522,19 @@ export class DartRenderer extends ConvenienceRenderer { ) { return [dynamic, " == null ? null : ", "DateTime.parse(", dynamic, ")"]; } + return ["DateTime.parse(", dynamic, ")"]; default: return dynamic; } - } + }, ); } - //If the first time is the unionType type, after nullableFromUnion conversion, - //the isNullable property will become false, which is obviously wrong, - //so add isNullable property - protected toDynamicExpression(isNullable: boolean = false, t: Type, ...dynamic: Sourcelike[]): Sourcelike { + // If the first time is the unionType type, after nullableFromUnion conversion, + // the isNullable property will become false, which is obviously wrong, + // so add isNullable property + protected toDynamicExpression (isNullable: boolean = false, t: Type, ...dynamic: Sourcelike[]): Sourcelike { return matchType( t, _anyType => dynamic, @@ -527,7 +548,7 @@ export class DartRenderer extends ConvenienceRenderer { arrayType.isNullable || isNullable, "dynamic", dynamic, - this.toDynamicExpression(arrayType.items.isNullable, arrayType.items, "x") + this.toDynamicExpression(arrayType.items.isNullable, arrayType.items, "x"), ), _classType => { if ( @@ -537,6 +558,7 @@ export class DartRenderer extends ConvenienceRenderer { ) { return [dynamic, "?.", this.toJson, "()"]; } + return [dynamic, ".", this.toJson, "()"]; }, mapType => @@ -544,7 +566,7 @@ export class DartRenderer extends ConvenienceRenderer { mapType.isNullable || isNullable, "dynamic", dynamic, - this.toDynamicExpression(mapType.values.isNullable, mapType.values, "v") + this.toDynamicExpression(mapType.values.isNullable, mapType.values, "v"), ), enumType => { return [defined(this._enumValues.get(enumType)), ".reverse[", dynamic, "]"]; @@ -554,6 +576,7 @@ export class DartRenderer extends ConvenienceRenderer { if (maybeNullable === null) { return dynamic; } + return this.toDynamicExpression(unionType.isNullable, maybeNullable, dynamic); }, transformedStringType => { @@ -566,6 +589,7 @@ export class DartRenderer extends ConvenienceRenderer { ) { return [dynamic, "?.toIso8601String()"]; } + return [dynamic, ".toIso8601String()"]; case "date": if ( @@ -574,44 +598,45 @@ export class DartRenderer extends ConvenienceRenderer { (transformedStringType.isNullable || isNullable) ) { return [ - '"${', + "\"${", dynamic, "!.year.toString().padLeft(4, '0')", "}-${", dynamic, "!.month.toString().padLeft(2, '0')}-${", dynamic, - "!.day.toString().padLeft(2, '0')}\"" + "!.day.toString().padLeft(2, '0')}\"", ]; } + return [ - '"${', + "\"${", dynamic, ".year.toString().padLeft(4, '0')", "}-${", dynamic, ".month.toString().padLeft(2, '0')}-${", dynamic, - ".day.toString().padLeft(2, '0')}\"" + ".day.toString().padLeft(2, '0')}\"", ]; default: return dynamic; } - } + }, ); } - private _emitEmptyConstructor(className: Name): void { + private _emitEmptyConstructor (className: Name): void { this.emitLine(className, "();"); } - private _emitConstructor(c: ClassType, className: Name): void { + private _emitConstructor (c: ClassType, className: Name): void { this.emitLine(className, "({"); this.indent(() => { this.forEachClassProperty(c, "none", (name, _, prop) => { const required = this._options.requiredProperties || - (this._options.nullSafety && (!prop.type.isNullable || !prop.isOptional)); + this._options.nullSafety && (!prop.type.isNullable || !prop.isOptional); this.emitLine(required ? "required " : "", "this.", name, ","); }); }); @@ -619,7 +644,7 @@ export class DartRenderer extends ConvenienceRenderer { this.ensureBlankLine(); } - private _emitVariables(c: ClassType): void { + private _emitVariables (c: ClassType): void { this.forEachClassProperty(c, "none", (name, jsonName, p) => { const description = this.descriptionForClassProperty(c, jsonName); if (description !== undefined) { @@ -640,7 +665,7 @@ export class DartRenderer extends ConvenienceRenderer { }); } - private _emitCopyConstructor(c: ClassType, className: Name): void { + private _emitCopyConstructor (c: ClassType, className: Name): void { this.ensureBlankLine(); this.emitLine(className, " copyWith({"); this.indent(() => { @@ -660,7 +685,7 @@ export class DartRenderer extends ConvenienceRenderer { }); } - private _emitStringJsonEncoderDecoder(className: Name): void { + private _emitStringJsonEncoderDecoder (className: Name): void { this.ensureBlankLine(); this.emitLine( "factory ", @@ -671,7 +696,7 @@ export class DartRenderer extends ConvenienceRenderer { className, ".", this.fromJson, - "(json.decode(str));" + "(json.decode(str));", ); this.ensureBlankLine(); @@ -680,11 +705,11 @@ export class DartRenderer extends ConvenienceRenderer { this._options.methodNamesWithMap ? "toJson() => " : "toRawJson() => ", "json.encode(", this.toJson, - "());" + "());", ); } - private _emitMapEncoderDecoder(c: ClassType, className: Name): void { + private _emitMapEncoderDecoder (c: ClassType, className: Name): void { this.ensureBlankLine(); this.emitLine("factory ", className, ".", this.fromJson, "(Map json) => ", className, "("); this.indent(() => { @@ -695,11 +720,11 @@ export class DartRenderer extends ConvenienceRenderer { this.fromDynamicExpression( property.type.isNullable, property.type, - 'json["', + "json[\"", stringEscape(jsonName), - '"]' + "\"]", ), - "," + ",", ); }); }); @@ -711,27 +736,29 @@ export class DartRenderer extends ConvenienceRenderer { this.indent(() => { this.forEachClassProperty(c, "none", (name, jsonName, property) => { this.emitLine( - '"', + "\"", stringEscape(jsonName), - '": ', + "\": ", this.toDynamicExpression(property.type.isNullable, property.type, name), - "," + ",", ); }); }); this.emitLine("};"); } - protected emitClassDefinition(c: ClassType, className: Name): void { + protected emitClassDefinition (c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); if (this._options.useHive) { this.classCounter++; this.emitLine(`@HiveType(typeId: ${this.classCounter})`); this.classPropertyCounter = 0; } + if (this._options.useJsonAnnotation) { - this.emitLine(`@JsonSerializable()`); + this.emitLine("@JsonSerializable()"); } + this.emitBlock(["class ", className], () => { if (c.getProperties().size === 0) { this._emitEmptyConstructor(className); @@ -754,7 +781,7 @@ export class DartRenderer extends ConvenienceRenderer { ".fromJson(Map json) => ", "_$", className, - "FromJson(json);" + "FromJson(json);", ); this.ensureBlankLine(); @@ -763,7 +790,7 @@ export class DartRenderer extends ConvenienceRenderer { "Map toJson() => ", "_$", className, - "ToJson(this);" + "ToJson(this);", ); } else { if (this._options.justTypes) return; @@ -777,7 +804,7 @@ export class DartRenderer extends ConvenienceRenderer { }); } - protected emitFreezedClassDefinition(c: ClassType, className: Name): void { + protected emitFreezedClassDefinition (c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); this.emitLine("@freezed"); @@ -795,11 +822,12 @@ export class DartRenderer extends ConvenienceRenderer { const required = this._options.requiredProperties || - (this._options.nullSafety && (!prop.type.isNullable || !prop.isOptional)); + this._options.nullSafety && (!prop.type.isNullable || !prop.isOptional); if (this._options.useJsonAnnotation) { this.classPropertyCounter++; this.emitLine(`@JsonKey(name: "${jsonName}")`); } + this.emitLine(required ? "required " : "", this.dartType(prop.type, true), " ", name, ","); }); }); @@ -816,20 +844,21 @@ export class DartRenderer extends ConvenienceRenderer { ".fromJson(Map json) => ", "_$", className, - "FromJson(json);" + "FromJson(json);", ); }); } - protected emitEnumDefinition(e: EnumType, enumName: Name): void { + protected emitEnumDefinition (e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); this.emitLine("enum ", enumName, " {"); this.indent(() => { this.forEachEnumCase(e, "none", (name, jsonName, pos) => { const comma = pos === "first" || pos === "middle" ? "," : []; if (this._options.useJsonAnnotation) { - this.emitLine('@JsonValue("', stringEscape(jsonName), '")'); + this.emitLine("@JsonValue(\"", stringEscape(jsonName), "\")"); } + this.emitLine(name, comma); }); }); @@ -842,7 +871,7 @@ export class DartRenderer extends ConvenienceRenderer { this.indent(() => { this.forEachEnumCase(e, "none", (name, jsonName, pos) => { const comma = pos === "first" || pos === "middle" ? "," : []; - this.emitLine('"', stringEscape(jsonName), '": ', enumName, ".", name, comma); + this.emitLine("\"", stringEscape(jsonName), "\": ", enumName, ".", name, comma); }); }); this.emitLine("});"); @@ -850,7 +879,7 @@ export class DartRenderer extends ConvenienceRenderer { this._needEnumValues = true; } - protected emitEnumValues(): void { + protected emitEnumValues (): void { this.ensureBlankLine(); this.emitMultiline(`class EnumValues { Map map; @@ -865,7 +894,7 @@ export class DartRenderer extends ConvenienceRenderer { }`); } - private _emitTopLvlEncoderDecoder(): void { + private _emitTopLvlEncoderDecoder (): void { this.forEachTopLevel("leading-and-interposing", (t, name) => { const { encoder, decoder } = defined(this._topLevelDependents.get(name)); @@ -875,7 +904,7 @@ export class DartRenderer extends ConvenienceRenderer { decoder, "(String str) => ", this.fromDynamicExpression(t.isNullable, t, "json.decode(str)"), - ";" + ";", ); this.ensureBlankLine(); @@ -887,7 +916,7 @@ export class DartRenderer extends ConvenienceRenderer { this.dartType(t), " data) => json.encode(", this.toDynamicExpression(t.isNullable, t, "data"), - ");" + ");", ); // this.emitBlock(["String ", encoder, "(", this.dartType(t), " data)"], () => { @@ -896,7 +925,7 @@ export class DartRenderer extends ConvenienceRenderer { }); } - protected emitSourceStructure(): void { + protected emitSourceStructure (): void { this.emitFileHeader(); if (!this._options.justTypes && !this._options.codersInClass) { @@ -910,7 +939,7 @@ export class DartRenderer extends ConvenienceRenderer { (e, n) => this.emitEnumDefinition(e, n), (_e, _n) => { // We don't support this yet. - } + }, ); if (this._needEnumValues) { diff --git a/packages/quicktype-core/src/language/Elm.ts b/packages/quicktype-core/src/language/Elm.ts index bab36c541..01fa4f807 100644 --- a/packages/quicktype-core/src/language/Elm.ts +++ b/packages/quicktype-core/src/language/Elm.ts @@ -1,11 +1,15 @@ import { mapContains, arrayIntercalate } from "collection-utils"; import { TargetLanguage } from "../TargetLanguage"; -import { EnumOption, StringOption, BooleanOption, Option, getOptionValues, OptionValues } from "../RendererOptions"; -import { Type, ClassType, UnionType, EnumType, ClassProperty } from "../Type"; +import { type Option, type OptionValues } from "../RendererOptions"; +import { EnumOption, StringOption, BooleanOption, getOptionValues } from "../RendererOptions"; +import { type Type, type ClassType, type EnumType, type ClassProperty } from "../Type"; +import { UnionType } from "../Type"; import { matchType, nullableFromUnion } from "../TypeUtils"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { Namer, Name, DependencyName, funPrefixNamer } from "../Naming"; +import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { ConvenienceRenderer } from "../ConvenienceRenderer"; +import { type Namer, type Name} from "../Naming"; +import { DependencyName, funPrefixNamer } from "../Naming"; import { legalizeCharacters, isLetterOrUnderscoreOrDigit, @@ -17,41 +21,42 @@ import { combineWords, firstUpperWordStyle, allLowerWordStyle, - allUpperWordStyle + allUpperWordStyle, } from "../support/Strings"; import { defined } from "../support/Support"; -import { Sourcelike, annotated, MultiWord, singleWord, multiWord, parenIfNeeded } from "../Source"; +import { type Sourcelike, type MultiWord} from "../Source"; +import { annotated, singleWord, multiWord, parenIfNeeded } from "../Source"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { RenderContext } from "../Renderer"; +import { type RenderContext } from "../Renderer"; export const elmOptions = { justTypes: new BooleanOption("just-types", "Plain types only", false), useList: new EnumOption("array-type", "Use Array or List", [ ["array", false], - ["list", true] + ["list", true], ]), // FIXME: Do this via a configurable named eventually. - moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType") + moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType"), }; export class ElmTargetLanguage extends TargetLanguage { - constructor() { + constructor () { super("Elm", ["elm"], "elm"); } - protected getOptions(): Option[] { + protected getOptions (): Array> { return [elmOptions.justTypes, elmOptions.moduleName, elmOptions.useList]; } - get supportsOptionalClassProperties(): boolean { + get supportsOptionalClassProperties (): boolean { return true; } - get supportsUnionsWithBothNumberTypes(): boolean { + get supportsUnionsWithBothNumberTypes (): boolean { return true; } - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): ElmRenderer { + protected makeRenderer (renderContext: RenderContext, untypedOptionValues: { [name: string]: any, }): ElmRenderer { return new ElmRenderer(this, renderContext, getOptionValues(elmOptions, untypedOptionValues)); } } @@ -94,12 +99,12 @@ const forbiddenNames = [ "True", "False", "String", - "Float" + "Float", ]; const legalizeName = legalizeCharacters(cp => isAscii(cp) && isLetterOrUnderscoreOrDigit(cp)); -function elmNameStyle(original: string, upper: boolean): string { +function elmNameStyle (original: string, upper: boolean): string { const words = splitIntoWords(original); return combineWords( words, @@ -109,125 +114,131 @@ function elmNameStyle(original: string, upper: boolean): string { upper ? allUpperWordStyle : allLowerWordStyle, allUpperWordStyle, "", - isLetterOrUnderscore + isLetterOrUnderscore, ); } const upperNamingFunction = funPrefixNamer("upper", n => elmNameStyle(n, true)); const lowerNamingFunction = funPrefixNamer("lower", n => elmNameStyle(n, false)); -type RequiredOrOptional = { - reqOrOpt: string; +interface RequiredOrOptional { fallback: string; -}; + reqOrOpt: string; +} -function requiredOrOptional(p: ClassProperty): RequiredOrOptional { - function optional(fallback: string): RequiredOrOptional { +function requiredOrOptional (p: ClassProperty): RequiredOrOptional { + function optional (fallback: string): RequiredOrOptional { return { reqOrOpt: "Jpipe.optional", fallback }; } + const t = p.type; - if (p.isOptional || (t instanceof UnionType && nullableFromUnion(t) !== null)) { + if (p.isOptional || t instanceof UnionType && nullableFromUnion(t) !== null) { return optional(" Nothing"); } + if (t.kind === "null") { return optional(" ()"); } + return { reqOrOpt: "Jpipe.required", fallback: "" }; } -type TopLevelDependent = { - encoder: Name; +interface TopLevelDependent { decoder?: Name; -}; - -type NamedTypeDependent = { encoder: Name; +} + +interface NamedTypeDependent { decoder: Name; -}; + encoder: Name; +} export class ElmRenderer extends ConvenienceRenderer { private readonly _topLevelDependents = new Map(); + private readonly _namedTypeDependents = new Map(); - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues + private readonly _options: OptionValues, ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace (): string[] { return forbiddenNames; } - protected makeTopLevelDependencyNames(t: Type, topLevelName: Name): DependencyName[] { + protected makeTopLevelDependencyNames (t: Type, topLevelName: Name): DependencyName[] { const encoder = new DependencyName( lowerNamingFunction, topLevelName.order, - lookup => `${lookup(topLevelName)}_to_string` + lookup => `${lookup(topLevelName)}_to_string`, ); let decoder: DependencyName | undefined = undefined; if (this.namedTypeToNameForTopLevel(t) === undefined) { decoder = new DependencyName(lowerNamingFunction, topLevelName.order, lookup => lookup(topLevelName)); } + this._topLevelDependents.set(topLevelName, { encoder, decoder }); if (decoder !== undefined) { return [encoder, decoder]; } + return [encoder]; } - protected makeNamedTypeNamer(): Namer { + protected makeNamedTypeNamer (): Namer { return upperNamingFunction; } - protected makeNamedTypeDependencyNames(_: Type, typeName: Name): DependencyName[] { + protected makeNamedTypeDependencyNames (_: Type, typeName: Name): DependencyName[] { const encoder = new DependencyName(lowerNamingFunction, typeName.order, lookup => `encode_${lookup(typeName)}`); const decoder = new DependencyName(lowerNamingFunction, typeName.order, lookup => lookup(typeName)); this._namedTypeDependents.set(typeName, { encoder, decoder }); return [encoder, decoder]; } - protected namerForObjectProperty(): Namer { + protected namerForObjectProperty (): Namer { return lowerNamingFunction; } - protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties (_c: ClassType, _className: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected makeUnionMemberNamer(): Namer { + protected makeUnionMemberNamer (): Namer { return upperNamingFunction; } - protected get unionMembersInGlobalNamespace(): boolean { + protected get unionMembersInGlobalNamespace (): boolean { return true; } - protected makeEnumCaseNamer(): Namer { + protected makeEnumCaseNamer (): Namer { return upperNamingFunction; } - protected get enumCasesInGlobalNamespace(): boolean { + protected get enumCasesInGlobalNamespace (): boolean { return true; } - protected proposeUnionMemberName( + protected proposeUnionMemberName ( u: UnionType, unionName: Name, fieldType: Type, - lookup: (n: Name) => string + lookup: (n: Name) => string, ): string { const fieldName = super.proposeUnionMemberName(u, unionName, fieldType, lookup); return `${fieldName}_in_${lookup(unionName)}`; } - protected get commentLineStart(): string { + protected get commentLineStart (): string { return "-- "; } - protected emitDescriptionBlock(lines: Sourcelike[]): void { + protected emitDescriptionBlock (lines: Sourcelike[]): void { if (lines.length === 1) { this.emitComments([{ customLines: lines, lineStart: "{-| ", lineEnd: " -}" }]); } else { @@ -235,11 +246,11 @@ export class ElmRenderer extends ConvenienceRenderer { } } - private get arrayType(): string { + private get arrayType (): string { return this._options.useList ? "List" : "Array"; } - private elmType(t: Type, noOptional = false): MultiWord { + private elmType (t: Type, noOptional = false): MultiWord { return matchType( t, _anyType => singleWord(annotated(anyTypeIssueAnnotation, "Jdec.Value")), @@ -259,12 +270,13 @@ export class ElmRenderer extends ConvenienceRenderer { if (noOptional) return nullableType; return multiWord(" ", "Maybe", parenIfNeeded(nullableType)); } + return singleWord(this.nameForNamedType(unionType)); - } + }, ); } - private elmProperty(p: ClassProperty): Sourcelike { + private elmProperty (p: ClassProperty): Sourcelike { if (p.isOptional) { return multiWord(" ", "Maybe", parenIfNeeded(this.elmType(p.type, true))).source; } else { @@ -272,12 +284,12 @@ export class ElmRenderer extends ConvenienceRenderer { } } - private decoderNameForNamedType(t: Type): Name { + private decoderNameForNamedType (t: Type): Name { const name = this.nameForNamedType(t); return defined(this._namedTypeDependents.get(name)).decoder; } - private decoderNameForType(t: Type, noOptional = false): MultiWord { + private decoderNameForType (t: Type, noOptional = false): MultiWord { return matchType( t, _anyType => singleWord("Jdec.value"), @@ -290,7 +302,7 @@ export class ElmRenderer extends ConvenienceRenderer { multiWord( " ", ["Jdec.", decapitalize(this.arrayType)], - parenIfNeeded(this.decoderNameForType(arrayType.items)) + parenIfNeeded(this.decoderNameForType(arrayType.items)), ), classType => singleWord(this.decoderNameForNamedType(classType)), mapType => multiWord(" ", "Jdec.dict", parenIfNeeded(this.decoderNameForType(mapType.values))), @@ -302,12 +314,13 @@ export class ElmRenderer extends ConvenienceRenderer { if (noOptional) return nullableDecoder; return multiWord(" ", "Jdec.nullable", parenIfNeeded(nullableDecoder)); } + return singleWord(this.decoderNameForNamedType(unionType)); - } + }, ); } - private decoderNameForProperty(p: ClassProperty): MultiWord { + private decoderNameForProperty (p: ClassProperty): MultiWord { if (p.isOptional) { return multiWord(" ", "Jdec.nullable", parenIfNeeded(this.decoderNameForType(p.type, true))); } else { @@ -315,12 +328,12 @@ export class ElmRenderer extends ConvenienceRenderer { } } - private encoderNameForNamedType(t: Type): Name { + private encoderNameForNamedType (t: Type): Name { const name = this.nameForNamedType(t); return defined(this._namedTypeDependents.get(name)).encoder; } - private encoderNameForType(t: Type, noOptional = false): MultiWord { + private encoderNameForType (t: Type, noOptional = false): MultiWord { return matchType( t, _anyType => singleWord("identity"), @@ -333,7 +346,7 @@ export class ElmRenderer extends ConvenienceRenderer { multiWord( " ", ["make", this.arrayType, "Encoder"], - parenIfNeeded(this.encoderNameForType(arrayType.items)) + parenIfNeeded(this.encoderNameForType(arrayType.items)), ), classType => singleWord(this.encoderNameForNamedType(classType)), mapType => multiWord(" ", "makeDictEncoder", parenIfNeeded(this.encoderNameForType(mapType.values))), @@ -345,12 +358,13 @@ export class ElmRenderer extends ConvenienceRenderer { if (noOptional) return nullableEncoder; return multiWord(" ", "makeNullableEncoder", parenIfNeeded(nullableEncoder)); } + return singleWord(this.encoderNameForNamedType(unionType)); - } + }, ); } - private encoderNameForProperty(p: ClassProperty): MultiWord { + private encoderNameForProperty (p: ClassProperty): MultiWord { if (p.isOptional) { return multiWord(" ", "makeNullableEncoder", parenIfNeeded(this.encoderNameForType(p.type, true))); } else { @@ -358,11 +372,11 @@ export class ElmRenderer extends ConvenienceRenderer { } } - private emitTopLevelDefinition(t: Type, topLevelName: Name): void { + private emitTopLevelDefinition (t: Type, topLevelName: Name): void { this.emitLine("type alias ", topLevelName, " = ", this.elmType(t).source); } - private emitClassDefinition(c: ClassType, className: Name): void { + private emitClassDefinition (c: ClassType, className: Name): void { let description = this.descriptionForType(c); this.forEachClassProperty(c, "none", (name, jsonName) => { const propertyDescription = this.descriptionForClassProperty(c, jsonName); @@ -373,6 +387,7 @@ export class ElmRenderer extends ConvenienceRenderer { } else { description.push(""); } + description.push(`${this.sourcelikeToString(name)}:`); description.push(...propertyDescription); }); @@ -388,11 +403,12 @@ export class ElmRenderer extends ConvenienceRenderer { if (onFirst) { this.emitLine("{"); } + this.emitLine("}"); }); } - private emitEnumDefinition(e: EnumType, enumName: Name): void { + private emitEnumDefinition (e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); this.emitLine("type ", enumName); this.indent(() => { @@ -405,7 +421,7 @@ export class ElmRenderer extends ConvenienceRenderer { }); } - private emitUnionDefinition(u: UnionType, unionName: Name): void { + private emitUnionDefinition (u: UnionType, unionName: Name): void { this.emitDescription(this.descriptionForType(u)); this.emitLine("type ", unionName); this.indent(() => { @@ -417,23 +433,25 @@ export class ElmRenderer extends ConvenienceRenderer { } else { this.emitLine(equalsOrPipe, " ", constructor, " ", parenIfNeeded(this.elmType(t))); } + onFirst = false; }); }); } - private emitTopLevelFunctions(t: Type, topLevelName: Name): void { + private emitTopLevelFunctions (t: Type, topLevelName: Name): void { const { encoder, decoder } = defined(this._topLevelDependents.get(topLevelName)); if (this.namedTypeToNameForTopLevel(t) === undefined) { this.emitLine(defined(decoder), " : Jdec.Decoder ", topLevelName); this.emitLine(defined(decoder), " = ", this.decoderNameForType(t).source); this.ensureBlankLine(); } + this.emitLine(encoder, " : ", topLevelName, " -> String"); this.emitLine(encoder, " r = Jenc.encode 0 (", this.encoderNameForType(t).source, " r)"); } - private emitClassFunctions(c: ClassType, className: Name): void { + private emitClassFunctions (c: ClassType, className: Name): void { const decoderName = this.decoderNameForNamedType(c); this.emitLine(decoderName, " : Jdec.Decoder ", className); this.emitLine(decoderName, " ="); @@ -443,7 +461,7 @@ export class ElmRenderer extends ConvenienceRenderer { this.forEachClassProperty(c, "none", (_, jsonName, p) => { const propDecoder = parenIfNeeded(this.decoderNameForProperty(p)); const { reqOrOpt, fallback } = requiredOrOptional(p); - this.emitLine("|> ", reqOrOpt, ' "', stringEscape(jsonName), '" ', propDecoder, fallback); + this.emitLine("|> ", reqOrOpt, " \"", stringEscape(jsonName), "\" ", propDecoder, fallback); }); }); }); @@ -459,18 +477,19 @@ export class ElmRenderer extends ConvenienceRenderer { this.forEachClassProperty(c, "none", (name, jsonName, p) => { const bracketOrComma = onFirst ? "[" : ","; const propEncoder = this.encoderNameForProperty(p).source; - this.emitLine(bracketOrComma, ' ("', stringEscape(jsonName), '", ', propEncoder, " x.", name, ")"); + this.emitLine(bracketOrComma, " (\"", stringEscape(jsonName), "\", ", propEncoder, " x.", name, ")"); onFirst = false; }); if (onFirst) { this.emitLine("["); } + this.emitLine("]"); }); }); } - private emitEnumFunctions(e: EnumType, enumName: Name): void { + private emitEnumFunctions (e: EnumType, enumName: Name): void { const decoderName = this.decoderNameForNamedType(e); this.emitLine(decoderName, " : Jdec.Decoder ", enumName); this.emitLine(decoderName, " ="); @@ -482,9 +501,9 @@ export class ElmRenderer extends ConvenienceRenderer { this.emitLine("case str of"); this.indent(() => { this.forEachEnumCase(e, "none", (name, jsonName) => { - this.emitLine('"', stringEscape(jsonName), '" -> Jdec.succeed ', name); + this.emitLine("\"", stringEscape(jsonName), "\" -> Jdec.succeed ", name); }); - this.emitLine('somethingElse -> Jdec.fail <| "Invalid ', enumName, ': " ++ somethingElse'); + this.emitLine("somethingElse -> Jdec.fail <| \"Invalid ", enumName, ": \" ++ somethingElse"); }); }); this.emitLine(")"); @@ -497,14 +516,14 @@ export class ElmRenderer extends ConvenienceRenderer { this.emitLine(encoderName, " x = case x of"); this.indent(() => { this.forEachEnumCase(e, "none", (name, jsonName) => { - this.emitLine(name, ' -> Jenc.string "', stringEscape(jsonName), '"'); + this.emitLine(name, " -> Jenc.string \"", stringEscape(jsonName), "\""); }); }); } - private emitUnionFunctions(u: UnionType, unionName: Name): void { + private emitUnionFunctions (u: UnionType, unionName: Name): void { // We need arrays first, then strings, and integers before doubles. - function sortOrder(_: Name, t: Type): string { + function sortOrder (_: Name, t: Type): string { if (t.kind === "array") { return " array"; } else if (t.kind === "double") { @@ -512,6 +531,7 @@ export class ElmRenderer extends ConvenienceRenderer { } else if (t.isPrimitive()) { return " " + t.kind; } + return t.kind; } @@ -530,6 +550,7 @@ export class ElmRenderer extends ConvenienceRenderer { const decoder = parenIfNeeded(this.decoderNameForType(t)); this.emitLine(bracketOrComma, " Jdec.map ", constructor, " ", decoder); } + onFirst = false; }); this.emitLine("]"); @@ -552,7 +573,7 @@ export class ElmRenderer extends ConvenienceRenderer { }); } - protected emitSourceStructure(): void { + protected emitSourceStructure (): void { const exports: Sourcelike[] = []; const topLevelDecoders: Sourcelike[] = []; this.forEachTopLevel("none", (_, name) => { @@ -560,6 +581,7 @@ export class ElmRenderer extends ConvenienceRenderer { if (decoder === undefined) { decoder = defined(this._namedTypeDependents.get(name)).decoder; } + topLevelDecoders.push(decoder); exports.push(name, encoder, decoder); }); @@ -583,14 +605,14 @@ export class ElmRenderer extends ConvenienceRenderer { "", "add these imports", "", - " import Json.Decode exposing (decodeString)`);" + " import Json.Decode exposing (decodeString)`);", ]); this.emitLine( "-- import ", this._options.moduleName, " exposing (", arrayIntercalate(", ", topLevelDecoders), - ")" + ")", ); this.emitMultiline(`-- -- and you're off to the races with @@ -600,6 +622,7 @@ export class ElmRenderer extends ConvenienceRenderer { if (decoder === undefined) { decoder = defined(this._namedTypeDependents.get(name)).decoder; } + this.emitLine("-- decodeString ", decoder, " myJsonString"); }); } @@ -611,6 +634,7 @@ export class ElmRenderer extends ConvenienceRenderer { for (let i = 0; i < exports.length; i++) { this.emitLine(i === 0 ? "(" : ",", " ", exports[i]); } + this.emitLine(")"); }); this.ensureBlankLine(); @@ -629,13 +653,13 @@ import Dict exposing (Dict, map, toList)`); this.forEachTopLevel( "leading-and-interposing", (t: Type, topLevelName: Name) => this.emitTopLevelDefinition(t, topLevelName), - t => this.namedTypeToNameForTopLevel(t) === undefined + t => this.namedTypeToNameForTopLevel(t) === undefined, ); this.forEachNamedType( "leading-and-interposing", (c: ClassType, className: Name) => this.emitClassDefinition(c, className), (e: EnumType, enumName: Name) => this.emitEnumDefinition(e, enumName), - (u: UnionType, unionName: Name) => this.emitUnionDefinition(u, unionName) + (u: UnionType, unionName: Name) => this.emitUnionDefinition(u, unionName), ); if (this._options.justTypes) return; @@ -643,13 +667,13 @@ import Dict exposing (Dict, map, toList)`); this.ensureBlankLine(); this.emitLine("-- decoders and encoders"); this.forEachTopLevel("leading-and-interposing", (t: Type, topLevelName: Name) => - this.emitTopLevelFunctions(t, topLevelName) + this.emitTopLevelFunctions(t, topLevelName), ); this.forEachNamedType( "leading-and-interposing", (c: ClassType, className: Name) => this.emitClassFunctions(c, className), (e: EnumType, enumName: Name) => this.emitEnumFunctions(e, enumName), - (u: UnionType, unionName: Name) => this.emitUnionFunctions(u, unionName) + (u: UnionType, unionName: Name) => this.emitUnionFunctions(u, unionName), ); this.ensureBlankLine(); diff --git a/packages/quicktype-core/src/language/Golang.ts b/packages/quicktype-core/src/language/Golang.ts index 847bb075d..c41a6af26 100644 --- a/packages/quicktype-core/src/language/Golang.ts +++ b/packages/quicktype-core/src/language/Golang.ts @@ -1,6 +1,8 @@ -import { TypeKind, Type, ClassType, EnumType, UnionType, ClassProperty } from "../Type"; +import { type TypeKind, type Type, type ClassType, type EnumType, type ClassProperty } from "../Type"; +import { UnionType } from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { Name, DependencyName, Namer, funPrefixNamer } from "../Naming"; +import { type Name, type Namer} from "../Naming"; +import { DependencyName, funPrefixNamer } from "../Naming"; import { legalizeCharacters, isLetterOrUnderscore, @@ -10,16 +12,18 @@ import { combineWords, firstUpperWordStyle, allUpperWordStyle, - camelCase + camelCase, } from "../support/Strings"; import { assert, defined } from "../support/Support"; -import { StringOption, BooleanOption, Option, OptionValues, getOptionValues } from "../RendererOptions"; -import { Sourcelike, maybeAnnotated, modifySource } from "../Source"; +import { type Option, type OptionValues} from "../RendererOptions"; +import { StringOption, BooleanOption, getOptionValues } from "../RendererOptions"; +import { type Sourcelike} from "../Source"; +import { maybeAnnotated, modifySource } from "../Source"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; import { TargetLanguage } from "../TargetLanguage"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { RenderContext } from "../Renderer"; -import { StringTypeMapping, TransformedStringTypeKind, PrimitiveStringTypeKind } from ".."; +import { type RenderContext } from "../Renderer"; +import { type StringTypeMapping, type TransformedStringTypeKind, type PrimitiveStringTypeKind } from ".."; export const goOptions = { justTypes: new BooleanOption("just-types", "Plain types only", false), @@ -29,46 +33,46 @@ export const goOptions = { fieldTags: new StringOption("field-tags", "list of tags which should be generated for fields", "TAGS", "json"), omitEmpty: new BooleanOption( "omit-empty", - 'If set, all non-required objects will be tagged with ",omitempty"', - false - ) + "If set, all non-required objects will be tagged with \",omitempty\"", + false, + ), }; export class GoTargetLanguage extends TargetLanguage { - constructor() { + constructor () { super("Go", ["go", "golang"], "go"); } - protected getOptions(): Option[] { + protected getOptions (): Array> { return [ goOptions.justTypes, goOptions.justTypesAndPackage, goOptions.packageName, goOptions.multiFileOutput, goOptions.fieldTags, - goOptions.omitEmpty + goOptions.omitEmpty, ]; } - get supportsUnionsWithBothNumberTypes(): boolean { + get supportsUnionsWithBothNumberTypes (): boolean { return true; } - get stringTypeMapping(): StringTypeMapping { + get stringTypeMapping (): StringTypeMapping { const mapping: Map = new Map(); mapping.set("date-time", "date-time"); return mapping; } - get supportsOptionalClassProperties(): boolean { + get supportsOptionalClassProperties (): boolean { return true; } - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): GoRenderer { + protected makeRenderer (renderContext: RenderContext, untypedOptionValues: { [name: string]: any, }): GoRenderer { return new GoRenderer(this, renderContext, getOptionValues(goOptions, untypedOptionValues)); } - protected get defaultIndentation(): string { + protected get defaultIndentation (): string { return "\t"; } } @@ -77,7 +81,7 @@ const namingFunction = funPrefixNamer("namer", goNameStyle); const legalizeName = legalizeCharacters(isLetterOrUnderscoreOrDigit); -function goNameStyle(original: string): string { +function goNameStyle (original: string): string { const words = splitIntoWords(original); return combineWords( words, @@ -87,69 +91,70 @@ function goNameStyle(original: string): string { allUpperWordStyle, allUpperWordStyle, "", - isLetterOrUnderscore + isLetterOrUnderscore, ); } const primitiveValueTypeKinds: TypeKind[] = ["integer", "double", "bool", "string"]; const compoundTypeKinds: TypeKind[] = ["array", "class", "map", "enum"]; -function isValueType(t: Type): boolean { +function isValueType (t: Type): boolean { const kind = t.kind; - return primitiveValueTypeKinds.indexOf(kind) >= 0 || kind === "class" || kind === "enum" || kind === "date-time"; + return primitiveValueTypeKinds.includes(kind) || kind === "class" || kind === "enum" || kind === "date-time"; } -function canOmitEmpty(cp: ClassProperty, omitEmptyOption: boolean): boolean { +function canOmitEmpty (cp: ClassProperty, omitEmptyOption: boolean): boolean { if (!cp.isOptional) return false; if (omitEmptyOption) return true; const t = cp.type; - return ["union", "null", "any"].indexOf(t.kind) < 0; + return !["union", "null", "any"].includes(t.kind); } export class GoRenderer extends ConvenienceRenderer { private readonly _topLevelUnmarshalNames = new Map(); + private _currentFilename: string | undefined; - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues + private readonly _options: OptionValues, ) { super(targetLanguage, renderContext); } - protected makeNamedTypeNamer(): Namer { + protected makeNamedTypeNamer (): Namer { return namingFunction; } - protected namerForObjectProperty(): Namer { + protected namerForObjectProperty (): Namer { return namingFunction; } - protected makeUnionMemberNamer(): Namer { + protected makeUnionMemberNamer (): Namer { return namingFunction; } - protected makeEnumCaseNamer(): Namer { + protected makeEnumCaseNamer (): Namer { return namingFunction; } - protected get enumCasesInGlobalNamespace(): boolean { + protected get enumCasesInGlobalNamespace (): boolean { return true; } - protected makeTopLevelDependencyNames(_: Type, topLevelName: Name): DependencyName[] { + protected makeTopLevelDependencyNames (_: Type, topLevelName: Name): DependencyName[] { const unmarshalName = new DependencyName( namingFunction, topLevelName.order, - lookup => `unmarshal_${lookup(topLevelName)}` + lookup => `unmarshal_${lookup(topLevelName)}`, ); this._topLevelUnmarshalNames.set(topLevelName, unmarshalName); return [unmarshalName]; } /// startFile takes a file name, lowercases it, appends ".go" to it, and sets it as the current filename. - protected startFile(basename: Sourcelike): void { + protected startFile (basename: Sourcelike): void { if (this._options.multiFileOutput === false) { return; } @@ -160,7 +165,7 @@ export class GoRenderer extends ConvenienceRenderer { } /// endFile pushes the current file name onto the collection of finished files and then resets the current file name. These finished files are used in index.ts to write the output. - protected endFile(): void { + protected endFile (): void { if (this._options.multiFileOutput === false) { return; } @@ -169,21 +174,21 @@ export class GoRenderer extends ConvenienceRenderer { this._currentFilename = undefined; } - private emitBlock(line: Sourcelike, f: () => void): void { + private emitBlock (line: Sourcelike, f: () => void): void { this.emitLine(line, " {"); this.indent(f); this.emitLine("}"); } - private emitFunc(decl: Sourcelike, f: () => void): void { + private emitFunc (decl: Sourcelike, f: () => void): void { this.emitBlock(["func ", decl], f); } - private emitStruct(name: Name, table: Sourcelike[][]): void { + private emitStruct (name: Name, table: Sourcelike[][]): void { this.emitBlock(["type ", name, " struct"], () => this.emitTable(table)); } - private nullableGoType(t: Type, withIssues: boolean): Sourcelike { + private nullableGoType (t: Type, withIssues: boolean): Sourcelike { const goType = this.goType(t, withIssues); if (isValueType(t)) { return ["*", goType]; @@ -192,18 +197,20 @@ export class GoRenderer extends ConvenienceRenderer { } } - private propertyGoType(cp: ClassProperty): Sourcelike { + private propertyGoType (cp: ClassProperty): Sourcelike { const t = cp.type; if (t instanceof UnionType && nullableFromUnion(t) === null) { return ["*", this.goType(t, true)]; } + if (cp.isOptional) { return this.nullableGoType(t, true); } + return this.goType(t, true); } - private goType(t: Type, withIssues = false): Sourcelike { + private goType (t: Type, withIssues = false): Sourcelike { return matchType( t, _anyType => maybeAnnotated(withIssues, anyTypeIssueAnnotation, "interface{}"), @@ -222,6 +229,7 @@ export class GoRenderer extends ConvenienceRenderer { } else { valueSource = this.goType(v, withIssues); } + return ["map[string]", valueSource]; }, enumType => this.nameForNamedType(enumType), @@ -236,11 +244,11 @@ export class GoRenderer extends ConvenienceRenderer { } return "string"; - } + }, ); } - private emitTopLevel(t: Type, name: Name): void { + private emitTopLevel (t: Type, name: Name): void { this.startFile(name); if ( @@ -250,7 +258,7 @@ export class GoRenderer extends ConvenienceRenderer { this.leadingComments === undefined ) { this.emitLineOnce( - "// This file was generated from JSON Schema using quicktype, do not modify it directly." + "// This file was generated from JSON Schema using quicktype, do not modify it directly.", ); this.emitLineOnce("// To parse and unparse this JSON data, add this code to your project and do:"); this.emitLineOnce("//"); @@ -281,7 +289,7 @@ export class GoRenderer extends ConvenienceRenderer { this.endFile(); } - private emitClass(c: ClassType, className: Name): void { + private emitClass (c: ClassType, className: Name): void { this.startFile(className); let columns: Sourcelike[][] = []; const usedTypes = new Set(); @@ -295,12 +303,12 @@ export class GoRenderer extends ConvenienceRenderer { docStrings.forEach(doc => columns.push([doc])); const tags = this._options.fieldTags .split(",") - .map(tag => tag + ':"' + stringEscape(jsonName) + omitEmpty + '"') + .map(tag => tag + ":\"" + stringEscape(jsonName) + omitEmpty + "\"") .join(" "); columns.push([ [name, " "], [goType, " "], - ["`", tags, "`"] + ["`", tags, "`"], ]); usedTypes.add(goType.toString()); }); @@ -309,14 +317,14 @@ export class GoRenderer extends ConvenienceRenderer { false, usedTypes.has("time.Time") || usedTypes.has("*,time.Time") || usedTypes.has("[],time.Time") ? new Set(["time"]) - : undefined + : undefined, ); this.emitDescription(this.descriptionForType(c)); this.emitStruct(className, columns); this.endFile(); } - private emitEnum(e: EnumType, enumName: Name): void { + private emitEnum (e: EnumType, enumName: Name): void { this.startFile(enumName); this.emitPackageDefinitons(false); this.emitDescription(this.descriptionForType(e)); @@ -327,7 +335,7 @@ export class GoRenderer extends ConvenienceRenderer { this.forEachEnumCase(e, "none", (name, jsonName) => { columns.push([ [name, " "], - [enumName, ' = "', stringEscape(jsonName), '"'] + [enumName, " = \"", stringEscape(jsonName), "\""], ]); }); this.indent(() => this.emitTable(columns)); @@ -335,7 +343,7 @@ export class GoRenderer extends ConvenienceRenderer { this.endFile(); } - private emitUnion(u: UnionType, unionName: Name): void { + private emitUnion (u: UnionType, unionName: Name): void { this.startFile(unionName); this.emitPackageDefinitons(false); const [hasNull, nonNulls] = removeNullFromUnion(u); @@ -356,23 +364,26 @@ export class GoRenderer extends ConvenienceRenderer { this.emitLine("x.", fieldName, " = nil"); }); }; + const makeArgs = ( primitiveArg: (fieldName: Sourcelike) => Sourcelike, - compoundArg: (isClass: boolean, fieldName: Sourcelike) => Sourcelike + compoundArg: (isClass: boolean, fieldName: Sourcelike) => Sourcelike, ): Sourcelike => { const args: Sourcelike = []; for (const kind of primitiveValueTypeKinds) { args.push( ifMember(kind, "nil", (_1, fieldName, _2) => primitiveArg(fieldName)), - ", " + ", ", ); } + for (const kind of compoundTypeKinds) { args.push( ifMember(kind, "false, nil", (t, fieldName, _) => compoundArg(t.kind === "class", fieldName)), - ", " + ", ", ); } + args.push(isNullableArg); return args; }; @@ -392,6 +403,7 @@ export class GoRenderer extends ConvenienceRenderer { for (const kind of compoundTypeKinds) { maybeAssignNil(kind); } + ifMember("class", undefined, (_1, _2, goType) => { this.emitLine("var c ", goType); }); @@ -403,7 +415,7 @@ export class GoRenderer extends ConvenienceRenderer { } else { return ["true, &x.", fn]; } - } + }, ); this.emitLine("object, err := unmarshalUnion(data, ", args, ")"); this.emitBlock("if err != nil", () => { @@ -420,14 +432,14 @@ export class GoRenderer extends ConvenienceRenderer { this.emitFunc(["(x *", unionName, ") MarshalJSON() ([]byte, error)"], () => { const args = makeArgs( fn => ["x.", fn], - (_, fn) => ["x.", fn, " != nil, x.", fn] + (_, fn) => ["x.", fn, " != nil, x.", fn], ); this.emitLine("return marshalUnion(", args, ")"); }); this.endFile(); } - private emitSingleFileHeaderComments(): void { + private emitSingleFileHeaderComments (): void { this.emitLineOnce("// This file was generated from JSON Schema using quicktype, do not modify it directly."); this.emitLineOnce("// To parse and unparse this JSON data, add this code to your project and do:"); this.forEachTopLevel("none", (_: Type, name: Name) => { @@ -438,7 +450,7 @@ export class GoRenderer extends ConvenienceRenderer { }); } - private emitPackageDefinitons(includeJSONEncodingImport: boolean, imports: Set = new Set()): void { + private emitPackageDefinitons (includeJSONEncodingImport: boolean, imports: Set = new Set()): void { if (!this._options.justTypes || this._options.justTypesAndPackage) { this.ensureBlankLine(); const packageDeclaration = "package " + this._options.packageName; @@ -460,7 +472,7 @@ export class GoRenderer extends ConvenienceRenderer { this.emitImports(imports); } - private emitImports(imports: Set): void { + private emitImports (imports: Set): void { const sortedImports = Array.from(imports).sort((a, b) => a.localeCompare(b)); if (sortedImports.length === 0) { @@ -473,7 +485,7 @@ export class GoRenderer extends ConvenienceRenderer { this.ensureBlankLine(); } - private emitHelperFunctions(): void { + private emitHelperFunctions (): void { if (this.haveNamedUnions) { this.startFile("JSONSchemaSupport"); const imports = new Set(); @@ -602,7 +614,7 @@ func marshalUnion(pi *int64, pf *float64, pb *bool, ps *string, haveArray bool, } } - protected emitSourceStructure(): void { + protected emitSourceStructure (): void { if ( this._options.multiFileOutput === false && this._options.justTypes === false && @@ -618,7 +630,7 @@ func marshalUnion(pi *int64, pf *float64, pb *bool, ps *string, haveArray bool, (t, name) => this.emitTopLevel(t, name), t => !(this._options.justTypes || this._options.justTypesAndPackage) || - this.namedTypeToNameForTopLevel(t) === undefined + this.namedTypeToNameForTopLevel(t) === undefined, ); this.forEachObject("leading-and-interposing", (c: ClassType, className: Name) => this.emitClass(c, className)); this.forEachEnum("leading-and-interposing", (u: EnumType, enumName: Name) => this.emitEnum(u, enumName)); @@ -631,7 +643,7 @@ func marshalUnion(pi *int64, pf *float64, pb *bool, ps *string, haveArray bool, this.emitHelperFunctions(); } - private collectAllImports(): Set { + private collectAllImports (): Set { let imports = new Set(); this.forEachObject("leading-and-interposing", (c: ClassType, _className: Name) => { const classImports = this.collectClassImports(c); @@ -645,7 +657,7 @@ func marshalUnion(pi *int64, pf *float64, pb *bool, ps *string, haveArray bool, return imports; } - private collectClassImports(c: ClassType): Set { + private collectClassImports (c: ClassType): Set { const usedTypes = new Set(); const mapping: Map = new Map(); mapping.set("time.Time", "time"); @@ -668,7 +680,7 @@ func marshalUnion(pi *int64, pf *float64, pb *bool, ps *string, haveArray bool, return imports; } - private collectUnionImports(u: UnionType): Set { + private collectUnionImports (u: UnionType): Set { const usedTypes = new Set(); const mapping: Map = new Map(); mapping.set("time.Time", "time"); diff --git a/packages/quicktype-core/src/language/Haskell.ts b/packages/quicktype-core/src/language/Haskell.ts index 2bac412e9..ed13a8ee7 100644 --- a/packages/quicktype-core/src/language/Haskell.ts +++ b/packages/quicktype-core/src/language/Haskell.ts @@ -1,10 +1,13 @@ import { mapContains } from "collection-utils"; import { TargetLanguage } from "../TargetLanguage"; -import { EnumOption, StringOption, BooleanOption, Option, getOptionValues, OptionValues } from "../RendererOptions"; -import { Type, ClassType, UnionType, EnumType, ClassProperty } from "../Type"; +import { type Option, type OptionValues } from "../RendererOptions"; +import { EnumOption, StringOption, BooleanOption, getOptionValues } from "../RendererOptions"; +import { type Type, type ClassType, type UnionType, type EnumType, type ClassProperty } from "../Type"; import { matchType, nullableFromUnion } from "../TypeUtils"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { Namer, Name, funPrefixNamer } from "../Naming"; +import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { ConvenienceRenderer } from "../ConvenienceRenderer"; +import { type Namer, type Name} from "../Naming"; +import { funPrefixNamer } from "../Naming"; import { legalizeCharacters, isLetterOrUnderscoreOrDigit, @@ -15,40 +18,41 @@ import { combineWords, firstUpperWordStyle, allLowerWordStyle, - allUpperWordStyle + allUpperWordStyle, } from "../support/Strings"; -import { Sourcelike, MultiWord, singleWord, multiWord, parenIfNeeded } from "../Source"; -import { RenderContext } from "../Renderer"; +import { type Sourcelike, type MultiWord} from "../Source"; +import { singleWord, multiWord, parenIfNeeded } from "../Source"; +import { type RenderContext } from "../Renderer"; export const haskellOptions = { justTypes: new BooleanOption("just-types", "Plain types only", false), useList: new EnumOption("array-type", "Use Array or List", [ ["array", false], - ["list", true] + ["list", true], ]), - moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType") + moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType"), }; export class HaskellTargetLanguage extends TargetLanguage { - constructor() { + constructor () { super("Haskell", ["haskell"], "haskell"); } - protected getOptions(): Option[] { + protected getOptions (): Array> { return [haskellOptions.justTypes, haskellOptions.moduleName, haskellOptions.useList]; } - get supportsOptionalClassProperties(): boolean { + get supportsOptionalClassProperties (): boolean { return true; } - get supportsUnionsWithBothNumberTypes(): boolean { + get supportsUnionsWithBothNumberTypes (): boolean { return true; } - protected makeRenderer( + protected makeRenderer ( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } + untypedOptionValues: { [name: string]: any, }, ): HaskellRenderer { return new HaskellRenderer(this, renderContext, getOptionValues(haskellOptions, untypedOptionValues)); } @@ -106,12 +110,12 @@ const forbiddenNames = [ "Object", "Result", "Series", - "Error" + "Error", ]; const legalizeName = legalizeCharacters(cp => isAscii(cp) && isLetterOrUnderscoreOrDigit(cp)); -function haskellNameStyle(original: string, upper: boolean): string { +function haskellNameStyle (original: string, upper: boolean): string { const words = splitIntoWords(original); return combineWords( words, @@ -121,7 +125,7 @@ function haskellNameStyle(original: string, upper: boolean): string { upper ? allUpperWordStyle : allLowerWordStyle, allUpperWordStyle, "", - isLetterOrUnderscore + isLetterOrUnderscore, ); } @@ -129,73 +133,73 @@ const upperNamingFunction = funPrefixNamer("upper", n => haskellNameStyle(n, tru const lowerNamingFunction = funPrefixNamer("lower", n => haskellNameStyle(n, false)); export class HaskellRenderer extends ConvenienceRenderer { - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues + private readonly _options: OptionValues, ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace (): string[] { return forbiddenNames; } - protected makeNamedTypeNamer(): Namer { + protected makeNamedTypeNamer (): Namer { return upperNamingFunction; } - protected namerForObjectProperty(): Namer { + protected namerForObjectProperty (): Namer { return lowerNamingFunction; } - protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties (_c: ClassType, _className: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected makeUnionMemberNamer(): Namer { + protected makeUnionMemberNamer (): Namer { return upperNamingFunction; } - protected get unionMembersInGlobalNamespace(): boolean { + protected get unionMembersInGlobalNamespace (): boolean { return true; } - protected makeEnumCaseNamer(): Namer { + protected makeEnumCaseNamer (): Namer { return upperNamingFunction; } - protected get enumCasesInGlobalNamespace(): boolean { + protected get enumCasesInGlobalNamespace (): boolean { return true; } - protected proposeUnionMemberName( + protected proposeUnionMemberName ( u: UnionType, unionName: Name, fieldType: Type, - lookup: (n: Name) => string + lookup: (n: Name) => string, ): string { const fieldName = super.proposeUnionMemberName(u, unionName, fieldType, lookup); return `${fieldName}_in_${lookup(unionName)}`; } - protected get commentLineStart(): string { + protected get commentLineStart (): string { return "-- "; } - protected emitDescriptionBlock(lines: Sourcelike[]): void { + protected emitDescriptionBlock (lines: Sourcelike[]): void { if (lines.length === 1) { this.emitComments([{ customLines: lines, lineStart: "{-| ", lineEnd: " -}" }]); } else { this.emitCommentLines(lines, { firstLineStart: "{-| ", lineStart: "", - afterComment: "-}" + afterComment: "-}", }); } } - private haskellType(t: Type, noOptional = false): MultiWord { + private haskellType (t: Type, noOptional = false): MultiWord { return matchType( t, _anyType => multiWord(" ", "Maybe", "Text"), @@ -208,6 +212,7 @@ export class HaskellRenderer extends ConvenienceRenderer { if (this._options.useList) { return multiWord("", "[", parenIfNeeded(this.haskellType(arrayType.items)), "]"); } + return multiWord(" ", "Vector", parenIfNeeded(this.haskellType(arrayType.items))); }, classType => singleWord(this.nameForNamedType(classType)), @@ -220,12 +225,13 @@ export class HaskellRenderer extends ConvenienceRenderer { if (noOptional) return nullableType; return multiWord(" ", "Maybe", parenIfNeeded(nullableType)); } + return singleWord(this.nameForNamedType(unionType)); - } + }, ); } - private haskellProperty(p: ClassProperty): Sourcelike { + private haskellProperty (p: ClassProperty): Sourcelike { if (p.isOptional) { return multiWord(" ", "Maybe", parenIfNeeded(this.haskellType(p.type, true))).source; } else { @@ -233,7 +239,7 @@ export class HaskellRenderer extends ConvenienceRenderer { } } - private encoderNameForType(t: Type): MultiWord { + private encoderNameForType (t: Type): MultiWord { return matchType( t, _anyType => singleWord("String"), @@ -246,15 +252,15 @@ export class HaskellRenderer extends ConvenienceRenderer { _classType => singleWord("Object"), _mapType => singleWord("Object"), _enumType => singleWord("Object"), - _unionType => singleWord("Object") + _unionType => singleWord("Object"), ); } - private emitTopLevelDefinition(t: Type, topLevelName: Name): void { + private emitTopLevelDefinition (t: Type, topLevelName: Name): void { this.emitLine("type ", topLevelName, " = ", this.haskellType(t).source); } - private emitClassDefinition(c: ClassType, className: Name): void { + private emitClassDefinition (c: ClassType, className: Name): void { let description = this.descriptionForType(c); this.forEachClassProperty(c, "none", (name, jsonName) => { const propertyDescription = this.descriptionForClassProperty(c, jsonName); @@ -265,6 +271,7 @@ export class HaskellRenderer extends ConvenienceRenderer { } else { description.push(""); } + description.push(`${this.sourcelikeToString(name)}:`); description.push(...propertyDescription); }); @@ -280,11 +287,12 @@ export class HaskellRenderer extends ConvenienceRenderer { if (onFirst) { this.emitLine("{"); } + this.emitLine("} deriving (Show)"); }); } - private emitEnumDefinition(e: EnumType, enumName: Name): void { + private emitEnumDefinition (e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); this.emitLine("data ", enumName); this.indent(() => { @@ -298,7 +306,7 @@ export class HaskellRenderer extends ConvenienceRenderer { }); } - private emitUnionDefinition(u: UnionType, unionName: Name): void { + private emitUnionDefinition (u: UnionType, unionName: Name): void { this.emitDescription(this.descriptionForType(u)); this.emitLine("data ", unionName); this.indent(() => { @@ -310,18 +318,19 @@ export class HaskellRenderer extends ConvenienceRenderer { } else { this.emitLine(equalsOrPipe, " ", constructor, " ", parenIfNeeded(this.haskellType(t))); } + onFirst = false; }); this.emitLine("deriving (Show)"); }); } - private emitTopLevelFunctions(topLevelName: Name): void { + private emitTopLevelFunctions (topLevelName: Name): void { this.emitLine("decodeTopLevel :: ByteString -> Maybe ", topLevelName); this.emitLine("decodeTopLevel = decode"); } - private classPropertyLength(c: ClassType): number { + private classPropertyLength (c: ClassType): number { let counter = 0; this.forEachClassProperty(c, "none", () => { counter += 1; @@ -329,7 +338,7 @@ export class HaskellRenderer extends ConvenienceRenderer { return counter; } - private emitClassEncoderInstance(c: ClassType, className: Name): void { + private emitClassEncoderInstance (c: ClassType, className: Name): void { let classProperties: Array = []; this.forEachClassProperty(c, "none", name => { classProperties.push(" "); @@ -347,19 +356,20 @@ export class HaskellRenderer extends ConvenienceRenderer { this.emitLine("object"); let onFirst = true; this.forEachClassProperty(c, "none", (name, jsonName) => { - this.emitLine(onFirst ? "[ " : ", ", '"', stringEscape(jsonName), '" .= ', name, className); + this.emitLine(onFirst ? "[ " : ", ", "\"", stringEscape(jsonName), "\" .= ", name, className); onFirst = false; }); if (onFirst) { this.emitLine("["); } + this.emitLine("]"); }); } }); } - private emitClassDecoderInstance(c: ClassType, className: Name): void { + private emitClassDecoderInstance (c: ClassType, className: Name): void { this.emitLine("instance FromJSON ", className, " where"); this.indent(() => { @@ -371,7 +381,7 @@ export class HaskellRenderer extends ConvenienceRenderer { let onFirst = true; this.forEachClassProperty(c, "none", (_, jsonName, p) => { const operator = p.isOptional ? ".:?" : ".:"; - this.emitLine(onFirst ? "<$> " : "<*> ", "v ", operator, ' "', stringEscape(jsonName), '"'); + this.emitLine(onFirst ? "<$> " : "<*> ", "v ", operator, " \"", stringEscape(jsonName), "\""); onFirst = false; }); }); @@ -379,43 +389,43 @@ export class HaskellRenderer extends ConvenienceRenderer { }); } - private emitClassFunctions(c: ClassType, className: Name): void { + private emitClassFunctions (c: ClassType, className: Name): void { this.emitClassEncoderInstance(c, className); this.ensureBlankLine(); this.emitClassDecoderInstance(c, className); } - private emitEnumEncoderInstance(e: EnumType, enumName: Name): void { + private emitEnumEncoderInstance (e: EnumType, enumName: Name): void { this.emitLine("instance ToJSON ", enumName, " where"); this.indent(() => { this.forEachEnumCase(e, "none", (name, jsonName) => { - this.emitLine("toJSON ", name, enumName, ' = "', stringEscape(jsonName), '"'); + this.emitLine("toJSON ", name, enumName, " = \"", stringEscape(jsonName), "\""); }); }); } - private emitEnumDecoderInstance(e: EnumType, enumName: Name): void { + private emitEnumDecoderInstance (e: EnumType, enumName: Name): void { this.emitLine("instance FromJSON ", enumName, " where"); this.indent(() => { - this.emitLine('parseJSON = withText "', enumName, '" parseText'); + this.emitLine("parseJSON = withText \"", enumName, "\" parseText"); this.indent(() => { this.emitLine("where"); this.indent(() => { this.forEachEnumCase(e, "none", (name, jsonName) => { - this.emitLine('parseText "', stringEscape(jsonName), '" = return ', name, enumName); + this.emitLine("parseText \"", stringEscape(jsonName), "\" = return ", name, enumName); }); }); }); }); } - private emitEnumFunctions(e: EnumType, enumName: Name): void { + private emitEnumFunctions (e: EnumType, enumName: Name): void { this.emitEnumEncoderInstance(e, enumName); this.ensureBlankLine(); this.emitEnumDecoderInstance(e, enumName); } - private emitUnionEncoderInstance(u: UnionType, unionName: Name): void { + private emitUnionEncoderInstance (u: UnionType, unionName: Name): void { this.emitLine("instance ToJSON ", unionName, " where"); this.indent(() => { this.forEachUnionMember(u, null, "none", null, (constructor, t) => { @@ -428,7 +438,7 @@ export class HaskellRenderer extends ConvenienceRenderer { }); } - private emitUnionDecoderInstance(u: UnionType, unionName: Name): void { + private emitUnionDecoderInstance (u: UnionType, unionName: Name): void { this.emitLine("instance FromJSON ", unionName, " where"); this.indent(() => { this.forEachUnionMember(u, null, "none", null, (constructor, t) => { @@ -440,24 +450,24 @@ export class HaskellRenderer extends ConvenienceRenderer { this.encoderNameForType(t).source, " _) = (fmap ", constructor, - " . parseJSON) xs" + " . parseJSON) xs", ); } }); }); } - private emitUnionFunctions(u: UnionType, unionName: Name): void { + private emitUnionFunctions (u: UnionType, unionName: Name): void { this.emitUnionEncoderInstance(u, unionName); this.ensureBlankLine(); this.emitUnionDecoderInstance(u, unionName); } - private emitLanguageExtensions(ext: string): void { + private emitLanguageExtensions (ext: string): void { this.emitLine(`{-# LANGUAGE ${ext} #-}`); } - protected emitSourceStructure(): void { + protected emitSourceStructure (): void { const exports: Sourcelike[] = []; this.forEachTopLevel("none", (_, name) => { exports.push([name, " (..)"]); @@ -482,6 +492,7 @@ export class HaskellRenderer extends ConvenienceRenderer { for (let i = 0; i < exports.length; i++) { this.emitLine(i === 0 ? "(" : ",", " ", exports[i]); } + this.emitLine(", decodeTopLevel"); this.emitLine(") where"); }); @@ -501,25 +512,25 @@ import Data.Text (Text)`); this.forEachTopLevel( "leading-and-interposing", (t: Type, topLevelName: Name) => this.emitTopLevelDefinition(t, topLevelName), - t => this.namedTypeToNameForTopLevel(t) === undefined + t => this.namedTypeToNameForTopLevel(t) === undefined, ); this.forEachNamedType( "leading-and-interposing", (c: ClassType, className: Name) => this.emitClassDefinition(c, className), (e: EnumType, enumName: Name) => this.emitEnumDefinition(e, enumName), - (u: UnionType, unionName: Name) => this.emitUnionDefinition(u, unionName) + (u: UnionType, unionName: Name) => this.emitUnionDefinition(u, unionName), ); this.forEachTopLevel("leading-and-interposing", (_: Type, topLevelName: Name) => - this.emitTopLevelFunctions(topLevelName) + this.emitTopLevelFunctions(topLevelName), ); this.forEachNamedType( "leading-and-interposing", (c: ClassType, className: Name) => this.emitClassFunctions(c, className), (e: EnumType, enumName: Name) => this.emitEnumFunctions(e, enumName), - (u: UnionType, unionName: Name) => this.emitUnionFunctions(u, unionName) + (u: UnionType, unionName: Name) => this.emitUnionFunctions(u, unionName), ); if (this._options.justTypes) return; diff --git a/packages/quicktype-core/src/language/JSONSchema.ts b/packages/quicktype-core/src/language/JSONSchema.ts index 2b8a447ba..c18d6c744 100644 --- a/packages/quicktype-core/src/language/JSONSchema.ts +++ b/packages/quicktype-core/src/language/JSONSchema.ts @@ -1,47 +1,50 @@ import { mapFirst, iterableFirst } from "collection-utils"; import { TargetLanguage } from "../TargetLanguage"; -import { Type, UnionType, EnumType, ObjectType, transformedStringTypeTargetTypeKindsMap } from "../Type"; +import { type Type, type UnionType, type EnumType, type ObjectType} from "../Type"; +import { transformedStringTypeTargetTypeKindsMap } from "../Type"; import { matchTypeExhaustive } from "../TypeUtils"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { Namer, funPrefixNamer, Name } from "../Naming"; +import { type Namer, type Name } from "../Naming"; +import { funPrefixNamer } from "../Naming"; import { legalizeCharacters, splitIntoWords, combineWords, firstUpperWordStyle, - allUpperWordStyle + allUpperWordStyle, } from "../support/Strings"; import { defined, panic } from "../support/Support"; -import { StringTypeMapping, getNoStringTypeMapping } from "../TypeBuilder"; +import { type StringTypeMapping} from "../TypeBuilder"; +import { getNoStringTypeMapping } from "../TypeBuilder"; import { addDescriptionToSchema } from "../attributes/Description"; -import { Option } from "../RendererOptions"; -import { RenderContext } from "../Renderer"; +import { type Option } from "../RendererOptions"; +import { type RenderContext } from "../Renderer"; export class JSONSchemaTargetLanguage extends TargetLanguage { - constructor() { + constructor () { super("JSON Schema", ["schema", "json-schema"], "schema"); } - protected getOptions(): Option[] { + protected getOptions (): Array> { return []; } - get stringTypeMapping(): StringTypeMapping { + get stringTypeMapping (): StringTypeMapping { return getNoStringTypeMapping(); } - get supportsOptionalClassProperties(): boolean { + get supportsOptionalClassProperties (): boolean { return true; } - get supportsFullObjectType(): boolean { + get supportsFullObjectType (): boolean { return true; } - protected makeRenderer( + protected makeRenderer ( renderContext: RenderContext, - _untypedOptionValues: { [name: string]: any } + _untypedOptionValues: { [name: string]: any, }, ): JSONSchemaRenderer { return new JSONSchemaRenderer(this, renderContext); } @@ -51,7 +54,7 @@ const namingFunction = funPrefixNamer("namer", jsonNameStyle); const legalizeName = legalizeCharacters(cp => cp >= 32 && cp < 128 && cp !== 0x2f /* slash */); -function jsonNameStyle(original: string): string { +function jsonNameStyle (original: string): string { const words = splitIntoWords(original); return combineWords( words, @@ -61,57 +64,61 @@ function jsonNameStyle(original: string): string { allUpperWordStyle, allUpperWordStyle, "", - _ => true + _ => true, ); } -type Schema = { [name: string]: any }; +interface Schema { + [name: string]: any; +} export class JSONSchemaRenderer extends ConvenienceRenderer { - protected makeNamedTypeNamer(): Namer { + protected makeNamedTypeNamer (): Namer { return namingFunction; } - protected namerForObjectProperty(): null { + protected namerForObjectProperty (): null { return null; } - protected makeUnionMemberNamer(): null { + protected makeUnionMemberNamer (): null { return null; } - protected makeEnumCaseNamer(): null { + protected makeEnumCaseNamer (): null { return null; } - private nameForType(t: Type): string { + private nameForType (t: Type): string { return defined(this.names.get(this.nameForNamedType(t))); } - private makeOneOf(types: ReadonlySet): Schema { + private makeOneOf (types: ReadonlySet): Schema { const first = iterableFirst(types); if (first === undefined) { return panic("Must have at least one type for oneOf"); } + if (types.size === 1) { return this.schemaForType(first); } + return { anyOf: Array.from(types).map((t: Type) => this.schemaForType(t)) }; } - private makeRef(t: Type): Schema { + private makeRef (t: Type): Schema { return { $ref: `#/definitions/${this.nameForType(t)}` }; } - private addAttributesToSchema(t: Type, schema: Schema): void { + private addAttributesToSchema (t: Type, schema: Schema): void { const attributes = this.typeGraph.attributeStore.attributesForType(t); for (const [kind, attr] of attributes) { kind.addToSchema(schema, t, attr); } } - private schemaForType(t: Type): Schema { - const schema = matchTypeExhaustive<{ [name: string]: any }>( + private schemaForType (t: Type): Schema { + const schema = matchTypeExhaustive<{ [name: string]: any, }>( t, _noneType => { return panic("none type should have been replaced"); @@ -139,16 +146,18 @@ export class JSONSchemaRenderer extends ConvenienceRenderer { if (target === undefined) { return panic(`Unknown transformed string type ${transformedStringType.kind}`); } + return { type: "string", format: target.jsonSchema }; - } + }, ); if (schema.$ref === undefined) { this.addAttributesToSchema(t, schema); } + return schema; } - private definitionForObject(o: ObjectType, title: string | undefined): Schema { + private definitionForObject (o: ObjectType, title: string | undefined): Schema { let properties: Schema | undefined; let required: string[] | undefined; if (o.getProperties().size === 0) { @@ -162,14 +171,17 @@ export class JSONSchemaRenderer extends ConvenienceRenderer { if (prop.description === undefined) { addDescriptionToSchema(prop, this.descriptionForClassProperty(o, name)); } + props[name] = prop; if (!p.isOptional) { req.push(name); } } + properties = props; required = req.sort(); } + const additional = o.getAdditionalProperties(); const additionalProperties = additional !== undefined ? this.schemaForType(additional) : false; const schema = { @@ -177,32 +189,33 @@ export class JSONSchemaRenderer extends ConvenienceRenderer { additionalProperties, properties, required, - title + title, }; this.addAttributesToSchema(o, schema); return schema; } - private definitionForUnion(u: UnionType, title?: string): Schema { + private definitionForUnion (u: UnionType, title?: string): Schema { const oneOf = this.makeOneOf(u.sortedMembers); if (title !== undefined) { oneOf.title = title; } + this.addAttributesToSchema(u, oneOf); return oneOf; } - private definitionForEnum(e: EnumType, title: string): Schema { + private definitionForEnum (e: EnumType, title: string): Schema { const schema = { type: "string", enum: Array.from(e.cases), title }; this.addAttributesToSchema(e, schema); return schema; } - protected emitSourceStructure(): void { + protected emitSourceStructure (): void { // FIXME: Find a good way to do multiple top-levels. Maybe multiple files? const topLevelType = this.topLevels.size === 1 ? this.schemaForType(defined(mapFirst(this.topLevels))) : {}; const schema = Object.assign({ $schema: "http://json-schema.org/draft-06/schema#" }, topLevelType); - const definitions: { [name: string]: Schema } = {}; + const definitions: { [name: string]: Schema, } = {}; this.forEachObject("none", (o: ObjectType, name: Name) => { const title = defined(this.names.get(name)); definitions[title] = this.definitionForObject(o, title); diff --git a/packages/quicktype-core/src/language/Java.ts b/packages/quicktype-core/src/language/Java.ts index 05ad4b535..a4cc006d1 100644 --- a/packages/quicktype-core/src/language/Java.ts +++ b/packages/quicktype-core/src/language/Java.ts @@ -1,9 +1,13 @@ import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { DependencyName, funPrefixNamer, Name, Namer } from "../Naming"; -import { RenderContext } from "../Renderer"; -import { BooleanOption, EnumOption, getOptionValues, Option, OptionValues, StringOption } from "../RendererOptions"; -import { maybeAnnotated, Sourcelike } from "../Source"; +import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { ConvenienceRenderer } from "../ConvenienceRenderer"; +import { type Name, type Namer } from "../Naming"; +import { DependencyName, funPrefixNamer } from "../Naming"; +import { type RenderContext } from "../Renderer"; +import { type Option, type OptionValues} from "../RendererOptions"; +import { BooleanOption, EnumOption, getOptionValues, StringOption } from "../RendererOptions"; +import { type Sourcelike } from "../Source"; +import { maybeAnnotated } from "../Source"; import { acronymOption, acronymStyle, AcronymStyleOptions } from "../support/Acronyms"; import { allLowerWordStyle, @@ -18,13 +22,14 @@ import { splitIntoWords, standardUnicodeHexEscape, utf16ConcatMap, - utf16LegalizeCharacters + utf16LegalizeCharacters, } from "../support/Strings"; import { assert, assertNever, defined, panic } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; -import { ArrayType, ClassProperty, ClassType, EnumType, MapType, Type, TypeKind, UnionType } from "../Type"; +import { type ClassProperty, type Type, type TypeKind} from "../Type"; +import { ArrayType, ClassType, EnumType, MapType, UnionType } from "../Type"; import { directlyReachableSingleNamedType, matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { StringTypeMapping, TransformedStringTypeKind, PrimitiveStringTypeKind } from ".."; +import { type StringTypeMapping, type TransformedStringTypeKind, type PrimitiveStringTypeKind } from ".."; export const javaOptions = { useList: new EnumOption( @@ -32,9 +37,9 @@ export const javaOptions = { "Use T[] or List", [ ["array", false], - ["list", true] + ["list", true], ], - "array" + "array", ), justTypes: new BooleanOption("just-types", "Plain types only", false), dateTimeProvider: new EnumOption( @@ -42,23 +47,23 @@ export const javaOptions = { "Date time provider type", [ ["java8", "java8"], - ["legacy", "legacy"] + ["legacy", "legacy"], ], - "java8" + "java8", ), acronymStyle: acronymOption(AcronymStyleOptions.Pascal), // FIXME: Do this via a configurable named eventually. packageName: new StringOption("package", "Generated package name", "NAME", "io.quicktype"), lombok: new BooleanOption("lombok", "Use lombok", false, "primary"), - lombokCopyAnnotations: new BooleanOption("lombok-copy-annotations", "Copy accessor annotations", true, "secondary") + lombokCopyAnnotations: new BooleanOption("lombok-copy-annotations", "Copy accessor annotations", true, "secondary"), }; export class JavaTargetLanguage extends TargetLanguage { - constructor() { + constructor () { super("Java", ["java"], "java"); } - protected getOptions(): Option[] { + protected getOptions (): Array> { return [ javaOptions.useList, javaOptions.justTypes, @@ -66,23 +71,24 @@ export class JavaTargetLanguage extends TargetLanguage { javaOptions.acronymStyle, javaOptions.packageName, javaOptions.lombok, - javaOptions.lombokCopyAnnotations + javaOptions.lombokCopyAnnotations, ]; } - get supportsUnionsWithBothNumberTypes(): boolean { + get supportsUnionsWithBothNumberTypes (): boolean { return true; } - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): JavaRenderer { + protected makeRenderer (renderContext: RenderContext, untypedOptionValues: { [name: string]: any, }): JavaRenderer { const options = getOptionValues(javaOptions, untypedOptionValues); if (options.justTypes) { return new JavaRenderer(this, renderContext, options); } + return new JacksonRenderer(this, renderContext, options); } - get stringTypeMapping(): StringTypeMapping { + get stringTypeMapping (): StringTypeMapping { const mapping: Map = new Map(); mapping.set("date", "date"); mapping.set("time", "time"); @@ -159,27 +165,27 @@ const javaKeywords = [ "while", "null", "false", - "true" + "true", ]; export const stringEscape = utf16ConcatMap(escapeNonPrintableMapper(isAscii, standardUnicodeHexEscape)); -function isStartCharacter(codePoint: number): boolean { +function isStartCharacter (codePoint: number): boolean { if (codePoint === 0x5f) return true; // underscore return isAscii(codePoint) && isLetter(codePoint); } -function isPartCharacter(codePoint: number): boolean { - return isStartCharacter(codePoint) || (isAscii(codePoint) && isDigit(codePoint)); +function isPartCharacter (codePoint: number): boolean { + return isStartCharacter(codePoint) || isAscii(codePoint) && isDigit(codePoint); } const legalizeName = utf16LegalizeCharacters(isPartCharacter); -export function javaNameStyle( +export function javaNameStyle ( startWithUpper: boolean, upperUnderscore: boolean, original: string, - acronymsStyle: (s: string) => string = allUpperWordStyle + acronymsStyle: (s: string) => string = allUpperWordStyle, ): string { const words = splitIntoWords(original); return combineWords( @@ -190,43 +196,53 @@ export function javaNameStyle( upperUnderscore || startWithUpper ? allUpperWordStyle : allLowerWordStyle, acronymsStyle, upperUnderscore ? "_" : "", - isStartCharacter + isStartCharacter, ); } abstract class JavaDateTimeProvider { - constructor( + constructor ( protected readonly _renderer: JavaRenderer, - protected readonly _className: string + protected readonly _className: string, ) {} + abstract keywords: string[]; abstract dateTimeImports: string[]; + abstract dateImports: string[]; + abstract timeImports: string[]; + abstract converterImports: string[]; abstract dateTimeType: string; + abstract dateType: string; + abstract timeType: string; abstract dateTimeJacksonAnnotations: string[]; + abstract dateJacksonAnnotations: string[]; + abstract timeJacksonAnnotations: string[]; - abstract emitDateTimeConverters(): void; + abstract emitDateTimeConverters (): void; public shouldEmitDateTimeConverter = true; + public shouldEmitTimeConverter = true; + public shouldEmitDateConverter = true; - abstract convertStringToDateTime(variable: Sourcelike): Sourcelike; - abstract convertStringToTime(variable: Sourcelike): Sourcelike; - abstract convertStringToDate(variable: Sourcelike): Sourcelike; + abstract convertStringToDateTime (variable: Sourcelike): Sourcelike; + abstract convertStringToTime (variable: Sourcelike): Sourcelike; + abstract convertStringToDate (variable: Sourcelike): Sourcelike; - abstract convertDateTimeToString(variable: Sourcelike): Sourcelike; - abstract convertTimeToString(variable: Sourcelike): Sourcelike; - abstract convertDateToString(variable: Sourcelike): Sourcelike; + abstract convertDateTimeToString (variable: Sourcelike): Sourcelike; + abstract convertTimeToString (variable: Sourcelike): Sourcelike; + abstract convertDateToString (variable: Sourcelike): Sourcelike; } class Java8DateTimeProvider extends JavaDateTimeProvider { @@ -238,12 +254,15 @@ class Java8DateTimeProvider extends JavaDateTimeProvider { "ZonedDateTime", "DateTimeFormatter", "DateTimeFormatterBuilder", - "ChronoField" + "ChronoField", ]; dateTimeImports: string[] = ["java.time.OffsetDateTime"]; + dateImports: string[] = ["java.time.LocalDate"]; + timeImports: string[] = ["java.time.OffsetTime"]; + converterImports: string[] = [ "java.time.LocalDate", "java.time.OffsetDateTime", @@ -252,44 +271,48 @@ class Java8DateTimeProvider extends JavaDateTimeProvider { "java.time.ZonedDateTime", "java.time.format.DateTimeFormatter", "java.time.format.DateTimeFormatterBuilder", - "java.time.temporal.ChronoField" + "java.time.temporal.ChronoField", ]; dateTimeType = "OffsetDateTime"; + dateType = "LocalDate"; + timeType = "OffsetTime"; dateTimeJacksonAnnotations: string[] = []; + dateJacksonAnnotations: string[] = []; + timeJacksonAnnotations: string[] = []; - emitDateTimeConverters(): void { + emitDateTimeConverters (): void { this._renderer.ensureBlankLine(); this._renderer.emitLine( - "private static final DateTimeFormatter DATE_TIME_FORMATTER = new DateTimeFormatterBuilder()" + "private static final DateTimeFormatter DATE_TIME_FORMATTER = new DateTimeFormatterBuilder()", ); this._renderer.indent(() => this._renderer.indent(() => { this._renderer.emitLine(".appendOptional(DateTimeFormatter.ISO_DATE_TIME)"); this._renderer.emitLine(".appendOptional(DateTimeFormatter.ISO_OFFSET_DATE_TIME)"); this._renderer.emitLine(".appendOptional(DateTimeFormatter.ISO_INSTANT)"); - this._renderer.emitLine('.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SX"))'); - this._renderer.emitLine('.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ssX"))'); - this._renderer.emitLine('.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))'); + this._renderer.emitLine(".appendOptional(DateTimeFormatter.ofPattern(\"yyyy-MM-dd HH:mm:ss.SX\"))"); + this._renderer.emitLine(".appendOptional(DateTimeFormatter.ofPattern(\"yyyy-MM-dd HH:mm:ssX\"))"); + this._renderer.emitLine(".appendOptional(DateTimeFormatter.ofPattern(\"yyyy-MM-dd HH:mm:ss\"))"); this._renderer.emitLine(".toFormatter()"); this._renderer.emitLine(".withZone(ZoneOffset.UTC);"); - }) + }), ); this._renderer.ensureBlankLine(); this._renderer.emitBlock("public static OffsetDateTime parseDateTimeString(String str)", () => { this._renderer.emitLine( - "return ZonedDateTime.from(Converter.DATE_TIME_FORMATTER.parse(str)).toOffsetDateTime();" + "return ZonedDateTime.from(Converter.DATE_TIME_FORMATTER.parse(str)).toOffsetDateTime();", ); }); this._renderer.ensureBlankLine(); this._renderer.emitLine( - "private static final DateTimeFormatter TIME_FORMATTER = new DateTimeFormatterBuilder()" + "private static final DateTimeFormatter TIME_FORMATTER = new DateTimeFormatterBuilder()", ); this._renderer.indent(() => this._renderer.indent(() => { @@ -300,37 +323,37 @@ class Java8DateTimeProvider extends JavaDateTimeProvider { this._renderer.emitLine(".parseDefaulting(ChronoField.DAY_OF_MONTH, 1)"); this._renderer.emitLine(".toFormatter()"); this._renderer.emitLine(".withZone(ZoneOffset.UTC);"); - }) + }), ); this._renderer.ensureBlankLine(); this._renderer.emitBlock("public static OffsetTime parseTimeString(String str)", () => { this._renderer.emitLine( - "return ZonedDateTime.from(Converter.TIME_FORMATTER.parse(str)).toOffsetDateTime().toOffsetTime();" + "return ZonedDateTime.from(Converter.TIME_FORMATTER.parse(str)).toOffsetDateTime().toOffsetTime();", ); }); } - convertStringToDateTime(variable: Sourcelike): Sourcelike { + convertStringToDateTime (variable: Sourcelike): Sourcelike { return [this._className, ".parseDateTimeString(", variable, ")"]; } - convertStringToTime(variable: Sourcelike): Sourcelike { + convertStringToTime (variable: Sourcelike): Sourcelike { return [this._className, ".parseTimeString(", variable, ")"]; } - convertStringToDate(variable: Sourcelike): Sourcelike { + convertStringToDate (variable: Sourcelike): Sourcelike { return ["LocalDate.parse(", variable, ")"]; } - convertDateTimeToString(variable: Sourcelike): Sourcelike { + convertDateTimeToString (variable: Sourcelike): Sourcelike { return [variable, ".format(java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME)"]; } - convertTimeToString(variable: Sourcelike): Sourcelike { + convertTimeToString (variable: Sourcelike): Sourcelike { return [variable, ".format(java.time.format.DateTimeFormatter.ISO_OFFSET_TIME)"]; } - convertDateToString(variable: Sourcelike): Sourcelike { + convertDateToString (variable: Sourcelike): Sourcelike { return [variable, ".format(java.time.format.DateTimeFormatter.ISO_DATE)"]; } } @@ -339,19 +362,26 @@ class JavaLegacyDateTimeProvider extends JavaDateTimeProvider { keywords = ["SimpleDateFormat", "Date"]; dateTimeImports: string[] = ["java.util.Date"]; + dateImports: string[] = ["java.util.Date"]; + timeImports: string[] = ["java.util.Date"]; + converterImports: string[] = ["java.util.Date", "java.text.SimpleDateFormat"]; dateTimeType = "Date"; + dateType = "Date"; + timeType = "Date"; - dateTimeJacksonAnnotations: string[] = ['@JsonFormat(pattern = "yyyy-MM-dd\'T\'HH:mm:ssX", timezone = "UTC")']; - dateJacksonAnnotations: string[] = ['@JsonFormat(pattern = "yyyy-MM-dd")']; - timeJacksonAnnotations: string[] = ['@JsonFormat(pattern = "HH:mm:ssX", timezone = "UTC")']; + dateTimeJacksonAnnotations: string[] = ["@JsonFormat(pattern = \"yyyy-MM-dd'T'HH:mm:ssX\", timezone = \"UTC\")"]; - emitDateTimeConverters(): void { + dateJacksonAnnotations: string[] = ["@JsonFormat(pattern = \"yyyy-MM-dd\")"]; + + timeJacksonAnnotations: string[] = ["@JsonFormat(pattern = \"HH:mm:ssX\", timezone = \"UTC\")"]; + + emitDateTimeConverters (): void { this._renderer.ensureBlankLine(); this._renderer.emitLine("private static final String[] DATE_TIME_FORMATS = {"); this._renderer.indent(() => @@ -360,16 +390,16 @@ class JavaLegacyDateTimeProvider extends JavaDateTimeProvider { this._renderer.emitLine("\"yyyy-MM-dd'T'HH:mm:ss.S\","); this._renderer.emitLine("\"yyyy-MM-dd'T'HH:mm:ssX\","); this._renderer.emitLine("\"yyyy-MM-dd'T'HH:mm:ss\","); - this._renderer.emitLine('"yyyy-MM-dd HH:mm:ss.SX",'); - this._renderer.emitLine('"yyyy-MM-dd HH:mm:ss.S",'); - this._renderer.emitLine('"yyyy-MM-dd HH:mm:ssX",'); - this._renderer.emitLine('"yyyy-MM-dd HH:mm:ss",'); - this._renderer.emitLine('"HH:mm:ss.SZ",'); - this._renderer.emitLine('"HH:mm:ss.S",'); - this._renderer.emitLine('"HH:mm:ssZ",'); - this._renderer.emitLine('"HH:mm:ss",'); - this._renderer.emitLine('"yyyy-MM-dd",'); - }) + this._renderer.emitLine("\"yyyy-MM-dd HH:mm:ss.SX\","); + this._renderer.emitLine("\"yyyy-MM-dd HH:mm:ss.S\","); + this._renderer.emitLine("\"yyyy-MM-dd HH:mm:ssX\","); + this._renderer.emitLine("\"yyyy-MM-dd HH:mm:ss\","); + this._renderer.emitLine("\"HH:mm:ss.SZ\","); + this._renderer.emitLine("\"HH:mm:ss.S\","); + this._renderer.emitLine("\"HH:mm:ssZ\","); + this._renderer.emitLine("\"HH:mm:ss\","); + this._renderer.emitLine("\"yyyy-MM-dd\","); + }), ); this._renderer.emitLine("};"); this._renderer.ensureBlankLine(); @@ -389,55 +419,61 @@ class JavaLegacyDateTimeProvider extends JavaDateTimeProvider { this._renderer.ensureBlankLine(); this._renderer.emitBlock("public static String serializeDate(Date datetime)", () => { - this._renderer.emitLine('return new SimpleDateFormat("yyyy-MM-dd").format(datetime);'); + this._renderer.emitLine("return new SimpleDateFormat(\"yyyy-MM-dd\").format(datetime);"); }); this._renderer.ensureBlankLine(); this._renderer.emitBlock("public static String serializeTime(Date datetime)", () => { - this._renderer.emitLine('return new SimpleDateFormat("hh:mm:ssZ").format(datetime);'); + this._renderer.emitLine("return new SimpleDateFormat(\"hh:mm:ssZ\").format(datetime);"); }); } shouldEmitTimeConverter = false; + shouldEmitDateConverter = false; - convertStringToDateTime(variable: Sourcelike): Sourcelike { + convertStringToDateTime (variable: Sourcelike): Sourcelike { return [this._className, ".parseAllDateTimeString(", variable, ")"]; } - convertStringToTime(variable: Sourcelike): Sourcelike { + convertStringToTime (variable: Sourcelike): Sourcelike { return [this._className, ".parseAllDateTimeString(", variable, ")"]; } - convertStringToDate(variable: Sourcelike): Sourcelike { + convertStringToDate (variable: Sourcelike): Sourcelike { return [this._className, ".parseAllDateTimeString(", variable, ")"]; } - convertDateTimeToString(variable: Sourcelike): Sourcelike { + convertDateTimeToString (variable: Sourcelike): Sourcelike { return [this._className, ".serializeDateTime(", variable, ")"]; } - convertTimeToString(variable: Sourcelike): Sourcelike { + convertTimeToString (variable: Sourcelike): Sourcelike { return [this._className, ".serializeTime(", variable, ")"]; } - convertDateToString(variable: Sourcelike): Sourcelike { + convertDateToString (variable: Sourcelike): Sourcelike { return [this._className, ".serializeDate(", variable, ")"]; } } export class JavaRenderer extends ConvenienceRenderer { private _currentFilename: string | undefined; + private readonly _gettersAndSettersForPropertyName = new Map(); + private _haveEmittedLeadingComments = false; + protected readonly _dateTimeProvider: JavaDateTimeProvider; + protected readonly _converterClassname: string = "Converter"; + protected readonly _converterKeywords: string[] = []; - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - protected readonly _options: OptionValues + protected readonly _options: OptionValues, ) { super(targetLanguage, renderContext); @@ -452,125 +488,127 @@ export class JavaRenderer extends ConvenienceRenderer { } } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace (): string[] { const keywords = [ ...javaKeywords, ...this._converterKeywords, this._converterClassname, - ...this._dateTimeProvider.keywords + ...this._dateTimeProvider.keywords, ]; return keywords; } - protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties (_c: ClassType, _className: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected makeNamedTypeNamer(): Namer { + protected makeNamedTypeNamer (): Namer { return this.getNameStyling("typeNamingFunction"); } - protected namerForObjectProperty(): Namer { + protected namerForObjectProperty (): Namer { return this.getNameStyling("propertyNamingFunction"); } - protected makeUnionMemberNamer(): Namer { + protected makeUnionMemberNamer (): Namer { return this.getNameStyling("propertyNamingFunction"); } - protected makeEnumCaseNamer(): Namer { + protected makeEnumCaseNamer (): Namer { return this.getNameStyling("enumCaseNamingFunction"); } - protected unionNeedsName(u: UnionType): boolean { + protected unionNeedsName (u: UnionType): boolean { return nullableFromUnion(u) === null; } - protected namedTypeToNameForTopLevel(type: Type): Type | undefined { + protected namedTypeToNameForTopLevel (type: Type): Type | undefined { // If the top-level type doesn't contain any classes or unions // we have to define a class just for the `FromJson` method, in // emitFromJsonForTopLevel. return directlyReachableSingleNamedType(type); } - protected makeNamesForPropertyGetterAndSetter( + protected makeNamesForPropertyGetterAndSetter ( _c: ClassType, _className: Name, _p: ClassProperty, _jsonName: string, - name: Name + name: Name, ): [Name, Name] { const getterName = new DependencyName( this.getNameStyling("propertyNamingFunction"), name.order, - lookup => `get_${lookup(name)}` + lookup => `get_${lookup(name)}`, ); const setterName = new DependencyName( this.getNameStyling("propertyNamingFunction"), name.order, - lookup => `set_${lookup(name)}` + lookup => `set_${lookup(name)}`, ); return [getterName, setterName]; } - protected makePropertyDependencyNames( + protected makePropertyDependencyNames ( c: ClassType, className: Name, p: ClassProperty, jsonName: string, - name: Name + name: Name, ): Name[] { const getterAndSetterNames = this.makeNamesForPropertyGetterAndSetter(c, className, p, jsonName, name); this._gettersAndSettersForPropertyName.set(name, getterAndSetterNames); return getterAndSetterNames; } - private getNameStyling(convention: string): Namer { - const styling: { [key: string]: Namer } = { + private getNameStyling (convention: string): Namer { + const styling: { [key: string]: Namer, } = { typeNamingFunction: funPrefixNamer("types", n => - javaNameStyle(true, false, n, acronymStyle(this._options.acronymStyle)) + javaNameStyle(true, false, n, acronymStyle(this._options.acronymStyle)), ), propertyNamingFunction: funPrefixNamer("properties", n => - javaNameStyle(false, false, n, acronymStyle(this._options.acronymStyle)) + javaNameStyle(false, false, n, acronymStyle(this._options.acronymStyle)), ), enumCaseNamingFunction: funPrefixNamer("enum-cases", n => - javaNameStyle(true, true, n, acronymStyle(this._options.acronymStyle)) - ) + javaNameStyle(true, true, n, acronymStyle(this._options.acronymStyle)), + ), }; return styling[convention]; } - protected fieldOrMethodName(methodName: string, topLevelName: Name): Sourcelike { + protected fieldOrMethodName (methodName: string, topLevelName: Name): Sourcelike { if (this.topLevels.size === 1) { return methodName; } + return [topLevelName, capitalize(methodName)]; } - protected methodName(prefix: string, suffix: string, topLevelName: Name): Sourcelike { + protected methodName (prefix: string, suffix: string, topLevelName: Name): Sourcelike { if (this.topLevels.size === 1) { return [prefix, suffix]; } + return [prefix, topLevelName, suffix]; } - protected decoderName(topLevelName: Name): Sourcelike { + protected decoderName (topLevelName: Name): Sourcelike { return this.fieldOrMethodName("fromJsonString", topLevelName); } - protected encoderName(topLevelName: Name): Sourcelike { + protected encoderName (topLevelName: Name): Sourcelike { return this.fieldOrMethodName("toJsonString", topLevelName); } - protected readerGetterName(topLevelName: Name): Sourcelike { + protected readerGetterName (topLevelName: Name): Sourcelike { return this.methodName("get", "ObjectReader", topLevelName); } - protected writerGetterName(topLevelName: Name): Sourcelike { + protected writerGetterName (topLevelName: Name): Sourcelike { return this.methodName("get", "ObjectWriter", topLevelName); } - protected startFile(basename: Sourcelike): void { + protected startFile (basename: Sourcelike): void { assert(this._currentFilename === undefined, "Previous file wasn't finished"); // FIXME: The filenames should actually be Sourcelikes, too this._currentFilename = `${this.sourcelikeToString(basename)}.java`; @@ -583,12 +621,12 @@ export class JavaRenderer extends ConvenienceRenderer { } } - protected finishFile(): void { + protected finishFile (): void { super.finishFile(defined(this._currentFilename)); this._currentFilename = undefined; } - protected emitPackageAndImports(imports: string[]): void { + protected emitPackageAndImports (imports: string[]): void { this.emitLine("package ", this._options.packageName, ";"); this.ensureBlankLine(); for (const pkg of imports) { @@ -596,23 +634,23 @@ export class JavaRenderer extends ConvenienceRenderer { } } - protected emitFileHeader(fileName: Sourcelike, imports: string[]): void { + protected emitFileHeader (fileName: Sourcelike, imports: string[]): void { this.startFile(fileName); this.emitPackageAndImports(imports); this.ensureBlankLine(); } - public emitDescriptionBlock(lines: Sourcelike[]): void { + public emitDescriptionBlock (lines: Sourcelike[]): void { this.emitCommentLines(lines, { lineStart: " * ", beforeComment: "/**", afterComment: " */" }); } - public emitBlock(line: Sourcelike, f: () => void): void { + public emitBlock (line: Sourcelike, f: () => void): void { this.emitLine(line, " {"); this.indent(f); this.emitLine("}"); } - public emitTryCatch(main: () => void, handler: () => void, exception = "Exception") { + public emitTryCatch (main: () => void, handler: () => void, exception = "Exception") { this.emitLine("try {"); this.indent(main); this.emitLine("} catch (", exception, " ex) {"); @@ -620,18 +658,18 @@ export class JavaRenderer extends ConvenienceRenderer { this.emitLine("}"); } - public emitIgnoredTryCatchBlock(f: () => void) { + public emitIgnoredTryCatchBlock (f: () => void) { this.emitTryCatch(f, () => this.emitLine("// Ignored")); } - protected javaType(reference: boolean, t: Type, withIssues = false): Sourcelike { + protected javaType (reference: boolean, t: Type, withIssues = false): Sourcelike { return matchType( t, _anyType => maybeAnnotated(withIssues, anyTypeIssueAnnotation, "Object"), _nullType => maybeAnnotated(withIssues, nullTypeIssueAnnotation, "Object"), - _boolType => (reference ? "Boolean" : "boolean"), - _integerType => (reference ? "Long" : "long"), - _doubleType => (reference ? "Double" : "double"), + _boolType => reference ? "Boolean" : "boolean", + _integerType => reference ? "Long" : "long", + _doubleType => reference ? "Double" : "double", _stringType => "String", arrayType => { if (this._options.useList) { @@ -652,21 +690,25 @@ export class JavaRenderer extends ConvenienceRenderer { if (transformedStringType.kind === "time") { return this._dateTimeProvider.timeType; } + if (transformedStringType.kind === "date") { return this._dateTimeProvider.dateType; } + if (transformedStringType.kind === "date-time") { return this._dateTimeProvider.dateTimeType; } + if (transformedStringType.kind === "uuid") { return "UUID"; } + return "String"; - } + }, ); } - protected javaImport(t: Type): string[] { + protected javaImport (t: Type): string[] { return matchType( t, _anyType => [], @@ -694,21 +736,25 @@ export class JavaRenderer extends ConvenienceRenderer { if (transformedStringType.kind === "time") { return this._dateTimeProvider.timeImports; } + if (transformedStringType.kind === "date") { return this._dateTimeProvider.dateImports; } + if (transformedStringType.kind === "date-time") { return this._dateTimeProvider.dateTimeImports; } + if (transformedStringType.kind === "uuid") { return ["java.util.UUID"]; } + return []; - } + }, ); } - protected javaTypeWithoutGenerics(reference: boolean, t: Type): Sourcelike { + protected javaTypeWithoutGenerics (reference: boolean, t: Type): Sourcelike { if (t instanceof ArrayType) { if (this._options.useList) { return ["List"]; @@ -726,37 +772,40 @@ export class JavaRenderer extends ConvenienceRenderer { } } - protected emitClassAttributes(_c: ClassType, _className: Name): void { + protected emitClassAttributes (_c: ClassType, _className: Name): void { if (this._options.lombok) { this.emitLine("@lombok.Data"); } } - protected annotationsForAccessor( + protected annotationsForAccessor ( _c: ClassType, _className: Name, _propertyName: Name, _jsonName: string, _p: ClassProperty, - _isSetter: boolean + _isSetter: boolean, ): string[] { return []; } - protected importsForType(t: ClassType | UnionType | EnumType): string[] { + protected importsForType (t: ClassType | UnionType | EnumType): string[] { if (t instanceof ClassType) { return []; } + if (t instanceof UnionType) { return ["java.io.IOException"]; } + if (t instanceof EnumType) { return ["java.io.IOException"]; } + return assertNever(t); } - protected importsForClass(c: ClassType): string[] { + protected importsForClass (c: ClassType): string[] { const imports: string[] = []; this.forEachClassProperty(c, "none", (_name, _jsonName, p) => { this.javaImport(p.type).forEach(imp => imports.push(imp)); @@ -765,7 +814,7 @@ export class JavaRenderer extends ConvenienceRenderer { return [...new Set(imports)]; } - protected importsForUnionMembers(u: UnionType): string[] { + protected importsForUnionMembers (u: UnionType): string[] { const imports: string[] = []; const [, nonNulls] = removeNullFromUnion(u); this.forEachUnionMember(u, nonNulls, "none", null, (_fieldName, t) => { @@ -775,7 +824,7 @@ export class JavaRenderer extends ConvenienceRenderer { return [...new Set(imports)]; } - protected emitClassDefinition(c: ClassType, className: Name): void { + protected emitClassDefinition (c: ClassType, className: Name): void { let imports = [...this.importsForType(c), ...this.importsForClass(c)]; this.emitFileHeader(className, imports); @@ -789,10 +838,12 @@ export class JavaRenderer extends ConvenienceRenderer { if (getter.length !== 0) { this.emitLine("@lombok.Getter(onMethod_ = {" + getter.join(", ") + "})"); } + if (setter.length !== 0) { this.emitLine("@lombok.Setter(onMethod_ = {" + setter.join(", ") + "})"); } } + this.emitLine("private ", this.javaType(false, p.type, true), " ", name, ";"); }); if (!this._options.lombok) { @@ -801,11 +852,11 @@ export class JavaRenderer extends ConvenienceRenderer { const [getterName, setterName] = defined(this._gettersAndSettersForPropertyName.get(name)); const rendered = this.javaType(false, p.type); this.annotationsForAccessor(c, className, name, jsonName, p, false).forEach(annotation => - this.emitLine(annotation) + this.emitLine(annotation), ); this.emitLine("public ", rendered, " ", getterName, "() { return ", name, "; }"); this.annotationsForAccessor(c, className, name, jsonName, p, true).forEach(annotation => - this.emitLine(annotation) + this.emitLine(annotation), ); this.emitLine("public void ", setterName, "(", rendered, " value) { this.", name, " = value; }"); }); @@ -814,22 +865,22 @@ export class JavaRenderer extends ConvenienceRenderer { this.finishFile(); } - protected unionField(u: UnionType, t: Type, withIssues = false): { fieldType: Sourcelike; fieldName: Sourcelike } { + protected unionField (u: UnionType, t: Type, withIssues = false): { fieldName: Sourcelike, fieldType: Sourcelike, } { const fieldType = this.javaType(true, t, withIssues); // FIXME: "Value" should be part of the name. const fieldName = [this.nameForUnionMember(u, t), "Value"]; return { fieldType, fieldName }; } - protected emitUnionAttributes(_u: UnionType, _unionName: Name): void { + protected emitUnionAttributes (_u: UnionType, _unionName: Name): void { // empty } - protected emitUnionSerializer(_u: UnionType, _unionName: Name): void { + protected emitUnionSerializer (_u: UnionType, _unionName: Name): void { // empty } - protected emitUnionDefinition(u: UnionType, unionName: Name): void { + protected emitUnionDefinition (u: UnionType, unionName: Name): void { const imports = [...this.importsForType(u), ...this.importsForUnionMembers(u)]; this.emitFileHeader(unionName, imports); @@ -842,20 +893,21 @@ export class JavaRenderer extends ConvenienceRenderer { const { fieldType, fieldName } = this.unionField(u, t, true); this.emitLine("public ", fieldType, " ", fieldName, ";"); } + this.emitUnionSerializer(u, unionName); }); this.finishFile(); } - protected emitEnumSerializationAttributes(_e: EnumType) { + protected emitEnumSerializationAttributes (_e: EnumType) { // Empty } - protected emitEnumDeserializationAttributes(_e: EnumType) { + protected emitEnumDeserializationAttributes (_e: EnumType) { // Empty } - protected emitEnumDefinition(e: EnumType, enumName: Name): void { + protected emitEnumDefinition (e: EnumType, enumName: Name): void { this.emitFileHeader(enumName, this.importsForType(e)); this.emitDescription(this.descriptionForType(e)); const caseNames: Sourcelike[] = []; @@ -873,7 +925,7 @@ export class JavaRenderer extends ConvenienceRenderer { this.emitLine("switch (this) {"); this.indent(() => { this.forEachEnumCase(e, "none", (name, jsonName) => { - this.emitLine("case ", name, ': return "', stringEscape(jsonName), '";'); + this.emitLine("case ", name, ": return \"", stringEscape(jsonName), "\";"); }); }); this.emitLine("}"); @@ -884,29 +936,29 @@ export class JavaRenderer extends ConvenienceRenderer { this.emitEnumDeserializationAttributes(e); this.emitBlock(["public static ", enumName, " forValue(String value) throws IOException"], () => { this.forEachEnumCase(e, "none", (name, jsonName) => { - this.emitLine('if (value.equals("', stringEscape(jsonName), '")) return ', name, ";"); + this.emitLine("if (value.equals(\"", stringEscape(jsonName), "\")) return ", name, ";"); }); - this.emitLine('throw new IOException("Cannot deserialize ', enumName, '");'); + this.emitLine("throw new IOException(\"Cannot deserialize ", enumName, "\");"); }); }); this.finishFile(); } - protected emitSourceStructure(): void { + protected emitSourceStructure (): void { this.forEachNamedType( "leading-and-interposing", (c: ClassType, n: Name) => this.emitClassDefinition(c, n), (e, n) => this.emitEnumDefinition(e, n), - (u, n) => this.emitUnionDefinition(u, n) + (u, n) => this.emitUnionDefinition(u, n), ); } } export class JacksonRenderer extends JavaRenderer { - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - options: OptionValues + options: OptionValues, ) { super(targetLanguage, renderContext, options); } @@ -920,27 +972,27 @@ export class JacksonRenderer extends JavaRenderer { "JsonParser", "JsonProcessingException", "DeserializationContext", - "SerializerProvider" + "SerializerProvider", ]; - protected emitClassAttributes(c: ClassType, _className: Name): void { + protected emitClassAttributes (c: ClassType, _className: Name): void { if (c.getProperties().size === 0) this.emitLine("@JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.NONE)"); super.emitClassAttributes(c, _className); } - protected annotationsForAccessor( + protected annotationsForAccessor ( _c: ClassType, _className: Name, _propertyName: Name, jsonName: string, p: ClassProperty, - _isSetter: boolean + _isSetter: boolean, ): string[] { const superAnnotations = super.annotationsForAccessor(_c, _className, _propertyName, jsonName, p, _isSetter); - const annotations: string[] = ['@JsonProperty("' + stringEscape(jsonName) + '")']; + const annotations: string[] = ["@JsonProperty(\"" + stringEscape(jsonName) + "\")"]; switch (p.type.kind) { case "date-time": @@ -959,39 +1011,43 @@ export class JacksonRenderer extends JavaRenderer { return [...superAnnotations, ...annotations]; } - protected importsForType(t: ClassType | UnionType | EnumType): string[] { + protected importsForType (t: ClassType | UnionType | EnumType): string[] { if (t instanceof ClassType) { const imports = super.importsForType(t); imports.push("com.fasterxml.jackson.annotation.*"); return imports; } + if (t instanceof UnionType) { const imports = super.importsForType(t); imports.push( "java.io.IOException", "com.fasterxml.jackson.core.*", "com.fasterxml.jackson.databind.*", - "com.fasterxml.jackson.databind.annotation.*" + "com.fasterxml.jackson.databind.annotation.*", ); if (this._options.useList) { imports.push("com.fasterxml.jackson.core.type.*"); } + return imports; } + if (t instanceof EnumType) { const imports = super.importsForType(t); imports.push("com.fasterxml.jackson.annotation.*"); return imports; } + return assertNever(t); } - protected emitUnionAttributes(_u: UnionType, unionName: Name): void { + protected emitUnionAttributes (_u: UnionType, unionName: Name): void { this.emitLine("@JsonDeserialize(using = ", unionName, ".Deserializer.class)"); this.emitLine("@JsonSerialize(using = ", unionName, ".Serializer.class)"); } - protected emitUnionSerializer(u: UnionType, unionName: Name): void { + protected emitUnionSerializer (u: UnionType, unionName: Name): void { const stringBasedObjects: TypeKind[] = ["uuid", "time", "date", "date-time"]; const tokenCase = (tokenType: string): void => { @@ -1008,7 +1064,7 @@ export class JacksonRenderer extends JavaRenderer { const emitDeserializerCodeForStringObjects = ( fieldName: Sourcelike, kind: TypeKind, - parseFrom: string + parseFrom: string, ): void => { switch (kind) { case "date": @@ -1017,7 +1073,7 @@ export class JacksonRenderer extends JavaRenderer { fieldName, " = ", this._dateTimeProvider.convertStringToDate(parseFrom), - ";" + ";", ); break; @@ -1027,7 +1083,7 @@ export class JacksonRenderer extends JavaRenderer { fieldName, " = ", this._dateTimeProvider.convertStringToTime(parseFrom), - ";" + ";", ); break; @@ -1037,7 +1093,7 @@ export class JacksonRenderer extends JavaRenderer { fieldName, " = ", this._dateTimeProvider.convertStringToDateTime(parseFrom), - ";" + ";", ); break; case "uuid": @@ -1058,7 +1114,7 @@ export class JacksonRenderer extends JavaRenderer { fieldName, " = jsonParser.readValueAs(new TypeReference<", rendered, - ">() {});" + ">() {});", ); } else if (stringBasedObjects.some(stringBasedTypeKind => t.kind === stringBasedTypeKind)) { emitDeserializerCodeForStringObjects(fieldName, t.kind, variableFieldName); @@ -1080,6 +1136,7 @@ export class JacksonRenderer extends JavaRenderer { for (const tokenType of tokenTypes) { tokenCase(tokenType); } + this.indent(() => { emitDeserializeType(t); this.emitLine("break;"); @@ -1124,6 +1181,7 @@ export class JacksonRenderer extends JavaRenderer { if (stringType !== undefined) { emitDeserializeType(stringType, fromVariable); } + this.emitLine("break;"); }); }); @@ -1142,6 +1200,7 @@ export class JacksonRenderer extends JavaRenderer { this.emitLine("break;"); }); } + if (doubleType !== undefined) { tokenCase("VALUE_NUMBER_FLOAT"); this.indent(() => { @@ -1176,6 +1235,7 @@ export class JacksonRenderer extends JavaRenderer { } else { this.emitLine("jsonGenerator.writeObject(obj.", fieldName, ");"); } + this.emitLine("return;"); }); }; @@ -1189,7 +1249,7 @@ export class JacksonRenderer extends JavaRenderer { [ "public ", unionName, - " deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException" + " deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException", ], () => { this.emitLine(unionName, " value = new ", unionName, "();"); @@ -1202,11 +1262,11 @@ export class JacksonRenderer extends JavaRenderer { emitDeserializer(["START_OBJECT"], "class"); emitDeserializer(["START_OBJECT"], "map"); this.indent(() => - this.emitLine('default: throw new IOException("Cannot deserialize ', unionName, '");') + this.emitLine("default: throw new IOException(\"Cannot deserialize ", unionName, "\");"), ); this.emitLine("}"); this.emitLine("return value;"); - } + }, ); }); this.ensureBlankLine(); @@ -1216,31 +1276,32 @@ export class JacksonRenderer extends JavaRenderer { [ "public void serialize(", unionName, - " obj, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException" + " obj, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException", ], () => { for (const t of nonNulls) { emitSerializeType(t); } + if (maybeNull !== null) { this.emitLine("jsonGenerator.writeNull();"); } else { - this.emitLine('throw new IOException("', unionName, ' must not be null");'); + this.emitLine("throw new IOException(\"", unionName, " must not be null\");"); } - } + }, ); }); } - protected emitEnumSerializationAttributes(_e: EnumType) { + protected emitEnumSerializationAttributes (_e: EnumType) { this.emitLine("@JsonValue"); } - protected emitEnumDeserializationAttributes(_e: EnumType) { + protected emitEnumDeserializationAttributes (_e: EnumType) { this.emitLine("@JsonCreator"); } - protected emitOffsetDateTimeConverterModule(): void { + protected emitOffsetDateTimeConverterModule (): void { this.emitLine("SimpleModule module = new SimpleModule();"); if (this._dateTimeProvider.shouldEmitDateTimeConverter) { @@ -1249,7 +1310,7 @@ export class JacksonRenderer extends JavaRenderer { this._dateTimeProvider.dateTimeType, ".class, new JsonDeserializer<", this._dateTimeProvider.dateTimeType, - ">() {" + ">() {", ); this.indent(() => { this.emitLine("@Override"); @@ -1258,12 +1319,12 @@ export class JacksonRenderer extends JavaRenderer { "public ", this._dateTimeProvider.dateTimeType, " deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) ", - "throws IOException, JsonProcessingException" + "throws IOException, JsonProcessingException", ], () => { this.emitLine("String value = jsonParser.getText();"); this.emitLine("return ", this._dateTimeProvider.convertStringToDateTime("value"), ";"); - } + }, ); }); this.emitLine("});"); @@ -1275,7 +1336,7 @@ export class JacksonRenderer extends JavaRenderer { this._dateTimeProvider.timeType, ".class, new JsonDeserializer<", this._dateTimeProvider.timeType, - ">() {" + ">() {", ); this.indent(() => { this.emitLine("@Override"); @@ -1284,12 +1345,12 @@ export class JacksonRenderer extends JavaRenderer { "public ", this._dateTimeProvider.timeType, " deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) ", - "throws IOException, JsonProcessingException" + "throws IOException, JsonProcessingException", ], () => { this.emitLine("String value = jsonParser.getText();"); this.emitLine("return ", this._dateTimeProvider.convertStringToTime("value"), ";"); - } + }, ); }); this.emitLine("});"); @@ -1301,7 +1362,7 @@ export class JacksonRenderer extends JavaRenderer { this._dateTimeProvider.dateType, ".class, new JsonDeserializer<", this._dateTimeProvider.dateType, - ">() {" + ">() {", ); this.indent(() => { this.emitLine("@Override"); @@ -1310,12 +1371,12 @@ export class JacksonRenderer extends JavaRenderer { "public ", this._dateTimeProvider.dateType, " deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) ", - "throws IOException, JsonProcessingException" + "throws IOException, JsonProcessingException", ], () => { this.emitLine("String value = jsonParser.getText();"); this.emitLine("return ", this._dateTimeProvider.convertStringToDate("value"), ";"); - } + }, ); }); this.emitLine("});"); @@ -1324,7 +1385,7 @@ export class JacksonRenderer extends JavaRenderer { this.emitLine("mapper.registerModule(module);"); } - protected emitConverterClass(): void { + protected emitConverterClass (): void { this.startFile(this._converterClassname); this.emitCommentLines([ "To use this code, add the following Maven dependency to your project:", @@ -1336,7 +1397,7 @@ export class JacksonRenderer extends JavaRenderer { : "", "", "Import this package:", - "" + "", ]); this.emitLine("// import ", this._options.packageName, ".Converter;"); this.emitMultiline(`// @@ -1348,7 +1409,7 @@ export class JacksonRenderer extends JavaRenderer { this.javaType(false, t), " data = Converter.", this.decoderName(name), - "(jsonString);" + "(jsonString);", ); }); this.ensureBlankLine(); @@ -1358,7 +1419,7 @@ export class JacksonRenderer extends JavaRenderer { "com.fasterxml.jackson.databind.module.SimpleModule", "com.fasterxml.jackson.core.JsonParser", "com.fasterxml.jackson.core.JsonProcessingException", - "java.util.*" + "java.util.*", ].concat(this._dateTimeProvider.converterImports); this.emitPackageAndImports(imports); this.ensureBlankLine(); @@ -1375,11 +1436,11 @@ export class JacksonRenderer extends JavaRenderer { topLevelTypeRendered, " ", this.decoderName(topLevelName), - "(String json) throws IOException" + "(String json) throws IOException", ], () => { this.emitLine("return ", this.readerGetterName(topLevelName), "().readValue(json);"); - } + }, ); this.ensureBlankLine(); this.emitBlock( @@ -1388,11 +1449,11 @@ export class JacksonRenderer extends JavaRenderer { this.encoderName(topLevelName), "(", topLevelTypeRendered, - " obj) throws JsonProcessingException" + " obj) throws JsonProcessingException", ], () => { this.emitLine("return ", this.writerGetterName(topLevelName), "().writeValueAsString(obj);"); - } + }, ); }); this.forEachTopLevel("leading-and-interposing", (topLevelType, topLevelName) => { @@ -1412,7 +1473,7 @@ export class JacksonRenderer extends JavaRenderer { this.emitOffsetDateTimeConverterModule(); this.emitLine(readerName, " = mapper.readerFor(", renderedForClass, ".class);"); this.emitLine(writerName, " = mapper.writerFor(", renderedForClass, ".class);"); - } + }, ); this.ensureBlankLine(); this.emitBlock(["private static ObjectReader ", this.readerGetterName(topLevelName), "()"], () => { @@ -1421,7 +1482,7 @@ export class JacksonRenderer extends JavaRenderer { readerName, " == null) ", this.methodName("instantiate", "Mapper", topLevelName), - "();" + "();", ); this.emitLine("return ", readerName, ";"); }); @@ -1432,7 +1493,7 @@ export class JacksonRenderer extends JavaRenderer { writerName, " == null) ", this.methodName("instantiate", "Mapper", topLevelName), - "();" + "();", ); this.emitLine("return ", writerName, ";"); }); @@ -1441,7 +1502,7 @@ export class JacksonRenderer extends JavaRenderer { this.finishFile(); } - protected emitSourceStructure(): void { + protected emitSourceStructure (): void { this.emitConverterClass(); super.emitSourceStructure(); } diff --git a/packages/quicktype-core/src/language/JavaScript.ts b/packages/quicktype-core/src/language/JavaScript.ts index e8e3db9a2..1936de7b2 100644 --- a/packages/quicktype-core/src/language/JavaScript.ts +++ b/packages/quicktype-core/src/language/JavaScript.ts @@ -1,12 +1,12 @@ import { arrayIntercalate } from "collection-utils"; import { - TransformedStringTypeKind, - PrimitiveStringTypeKind, - Type, - ClassProperty, - ClassType, - ObjectType + type TransformedStringTypeKind, + type PrimitiveStringTypeKind, + type Type, + type ClassProperty, + type ClassType, + type ObjectType, } from "../Type"; import { matchType, directlyReachableSingleNamedType } from "../TypeUtils"; import { acronymOption, acronymStyle, AcronymStyleOptions } from "../support/Acronyms"; @@ -20,17 +20,20 @@ import { combineWords, firstUpperWordStyle, camelCase, - allLowerWordStyle + allLowerWordStyle, } from "../support/Strings"; import { panic } from "../support/Support"; -import { Sourcelike, modifySource } from "../Source"; -import { Namer, Name, funPrefixNamer } from "../Naming"; +import { type Sourcelike} from "../Source"; +import { modifySource } from "../Source"; +import { type Namer, type Name} from "../Naming"; +import { funPrefixNamer } from "../Naming"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; import { TargetLanguage } from "../TargetLanguage"; -import { StringTypeMapping } from "../TypeBuilder"; -import { BooleanOption, Option, OptionValues, getOptionValues, EnumOption } from "../RendererOptions"; -import { RenderContext } from "../Renderer"; +import { type StringTypeMapping } from "../TypeBuilder"; +import { type Option, type OptionValues} from "../RendererOptions"; +import { BooleanOption, getOptionValues, EnumOption } from "../RendererOptions"; +import { type RenderContext } from "../Renderer"; import { isES3IdentifierPart, isES3IdentifierStart } from "./JavaScriptUnicodeMaps"; export const javaScriptOptions = { @@ -40,7 +43,7 @@ export const javaScriptOptions = { "runtime-typecheck-ignore-unknown-properties", "Ignore unknown properties when verifying at runtime", false, - "secondary" + "secondary", ), converters: convertersOption(), rawType: new EnumOption<"json" | "any">( @@ -48,39 +51,39 @@ export const javaScriptOptions = { "Type of raw input (json by default)", [ ["json", "json"], - ["any", "any"] + ["any", "any"], ], "json", - "secondary" - ) + "secondary", + ), }; -export type JavaScriptTypeAnnotations = { +export interface JavaScriptTypeAnnotations { any: string; anyArray: string; anyMap: string; - string: string; - stringArray: string; boolean: string; never: string; -}; + string: string; + stringArray: string; +} export class JavaScriptTargetLanguage extends TargetLanguage { - constructor(displayName = "JavaScript", names: string[] = ["javascript", "js", "jsx"], extension = "js") { + constructor (displayName = "JavaScript", names: string[] = ["javascript", "js", "jsx"], extension = "js") { super(displayName, names, extension); } - protected getOptions(): Option[] { + protected getOptions (): Array> { return [ javaScriptOptions.runtimeTypecheck, javaScriptOptions.runtimeTypecheckIgnoreUnknownProperties, javaScriptOptions.acronymStyle, javaScriptOptions.converters, - javaScriptOptions.rawType + javaScriptOptions.rawType, ]; } - get stringTypeMapping(): StringTypeMapping { + get stringTypeMapping (): StringTypeMapping { const mapping: Map = new Map(); const dateTimeType = "date-time"; mapping.set("date", dateTimeType); @@ -88,17 +91,17 @@ export class JavaScriptTargetLanguage extends TargetLanguage { return mapping; } - get supportsOptionalClassProperties(): boolean { + get supportsOptionalClassProperties (): boolean { return true; } - get supportsFullObjectType(): boolean { + get supportsFullObjectType (): boolean { return true; } - protected makeRenderer( + protected makeRenderer ( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } + untypedOptionValues: { [name: string]: any, }, ): JavaScriptRenderer { return new JavaScriptRenderer(this, renderContext, getOptionValues(javaScriptOptions, untypedOptionValues)); } @@ -109,15 +112,15 @@ export const legalizeName = utf16LegalizeCharacters(isES3IdentifierPart); const identityNamingFunction = funPrefixNamer("properties", s => s); export class JavaScriptRenderer extends ConvenienceRenderer { - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _jsOptions: OptionValues + private readonly _jsOptions: OptionValues, ) { super(targetLanguage, renderContext); } - protected nameStyle(original: string, upper: boolean): string { + protected nameStyle (original: string, upper: boolean): string { const acronyms = acronymStyle(this._jsOptions.acronymStyle); const words = splitIntoWords(original); return combineWords( @@ -128,57 +131,58 @@ export class JavaScriptRenderer extends ConvenienceRenderer { upper ? s => capitalize(acronyms(s)) : allLowerWordStyle, acronyms, "", - isES3IdentifierStart + isES3IdentifierStart, ); } - protected makeNamedTypeNamer(): Namer { + protected makeNamedTypeNamer (): Namer { return funPrefixNamer("types", s => this.nameStyle(s, true)); } - protected namerForObjectProperty(): Namer { + protected namerForObjectProperty (): Namer { return identityNamingFunction; } - protected makeUnionMemberNamer(): null { + protected makeUnionMemberNamer (): null { return null; } - protected makeEnumCaseNamer(): Namer { + protected makeEnumCaseNamer (): Namer { return funPrefixNamer("enum-cases", s => this.nameStyle(s, true)); } - protected namedTypeToNameForTopLevel(type: Type): Type | undefined { + protected namedTypeToNameForTopLevel (type: Type): Type | undefined { return directlyReachableSingleNamedType(type); } - protected makeNameForProperty( + protected makeNameForProperty ( c: ClassType, className: Name, p: ClassProperty, jsonName: string, - _assignedName: string | undefined + _assignedName: string | undefined, ): Name | undefined { // Ignore the assigned name return super.makeNameForProperty(c, className, p, jsonName, undefined); } - protected emitDescriptionBlock(lines: Sourcelike[]): void { + protected emitDescriptionBlock (lines: Sourcelike[]): void { this.emitCommentLines(lines, { lineStart: " * ", beforeComment: "/**", afterComment: " */" }); } - typeMapTypeFor(t: Type): Sourcelike { - if (["class", "object", "enum"].indexOf(t.kind) >= 0) { - return ['r("', this.nameForNamedType(t), '")']; + typeMapTypeFor (t: Type): Sourcelike { + if (["class", "object", "enum"].includes(t.kind)) { + return ["r(\"", this.nameForNamedType(t), "\")"]; } + return matchType( t, - _anyType => '"any"', - _nullType => `null`, - _boolType => `true`, - _integerType => `0`, - _doubleType => `3.14`, - _stringType => `""`, + _anyType => "\"any\"", + _nullType => "null", + _boolType => "true", + _integerType => "0", + _doubleType => "3.14", + _stringType => "\"\"", arrayType => ["a(", this.typeMapTypeFor(arrayType.items), ")"], _classType => panic("We handled this above"), mapType => ["m(", this.typeMapTypeFor(mapType.values), ")"], @@ -191,26 +195,28 @@ export class JavaScriptRenderer extends ConvenienceRenderer { if (transformedStringType.kind === "date-time") { return "Date"; } - return `""`; - } + + return "\"\""; + }, ); } - typeMapTypeForProperty(p: ClassProperty): Sourcelike { + typeMapTypeForProperty (p: ClassProperty): Sourcelike { const typeMap = this.typeMapTypeFor(p.type); if (!p.isOptional) { return typeMap; } + return ["u(undefined, ", typeMap, ")"]; } - emitBlock(source: Sourcelike, end: Sourcelike, emit: () => void) { + emitBlock (source: Sourcelike, end: Sourcelike, emit: () => void) { this.emitLine(source, "{"); this.indent(emit); this.emitLine("}", end); } - emitTypeMap() { + emitTypeMap () { const { any: anyAnnotation } = this.typeAnnotations; this.emitBlock(`const typeMap${anyAnnotation} = `, ";", () => { @@ -218,24 +224,24 @@ export class JavaScriptRenderer extends ConvenienceRenderer { const additionalProperties = t.getAdditionalProperties(); const additional = additionalProperties !== undefined ? this.typeMapTypeFor(additionalProperties) : "false"; - this.emitLine('"', name, '": o(['); + this.emitLine("\"", name, "\": o(["); this.indent(() => { this.forEachClassProperty(t, "none", (propName, jsonName, property) => { this.emitLine( - '{ json: "', + "{ json: \"", utf16StringEscape(jsonName), - '", js: "', + "\", js: \"", modifySource(utf16StringEscape, propName), - '", typ: ', + "\", typ: ", this.typeMapTypeForProperty(property), - " }," + " },", ); }); }); this.emitLine("], ", additional, "),"); }); this.forEachEnum("none", (e, name) => { - this.emitLine('"', name, '": ['); + this.emitLine("\"", name, "\": ["); this.indent(() => { this.forEachEnumCase(e, "none", (_caseName, jsonName) => { this.emitLine(`"${utf16StringEscape(jsonName)}",`); @@ -246,32 +252,32 @@ export class JavaScriptRenderer extends ConvenienceRenderer { }); } - protected deserializerFunctionName(name: Name): Sourcelike { + protected deserializerFunctionName (name: Name): Sourcelike { return ["to", name]; } - protected deserializerFunctionLine(_t: Type, name: Name): Sourcelike { + protected deserializerFunctionLine (_t: Type, name: Name): Sourcelike { return ["function ", this.deserializerFunctionName(name), "(json)"]; } - protected serializerFunctionName(name: Name): Sourcelike { + protected serializerFunctionName (name: Name): Sourcelike { const camelCaseName = modifySource(camelCase, name); return [camelCaseName, "ToJson"]; } - protected serializerFunctionLine(_t: Type, name: Name): Sourcelike { + protected serializerFunctionLine (_t: Type, name: Name): Sourcelike { return ["function ", this.serializerFunctionName(name), "(value)"]; } - protected get moduleLine(): string | undefined { + protected get moduleLine (): string | undefined { return undefined; } - protected get castFunctionLines(): [string, string] { + protected get castFunctionLines (): [string, string] { return ["function cast(val, typ)", "function uncast(val, typ)"]; } - protected get typeAnnotations(): JavaScriptTypeAnnotations { + protected get typeAnnotations (): JavaScriptTypeAnnotations { return { any: "", anyArray: "", @@ -279,11 +285,11 @@ export class JavaScriptRenderer extends ConvenienceRenderer { string: "", stringArray: "", boolean: "", - never: "" + never: "", }; } - protected emitConvertModuleBody(): void { + protected emitConvertModuleBody (): void { const converter = (t: Type, name: Name) => { const typeMap = this.typeMapTypeFor(t); this.emitBlock([this.deserializerFunctionLine(t, name), " "], "", () => { @@ -324,7 +330,7 @@ export class JavaScriptRenderer extends ConvenienceRenderer { } } - protected emitConvertModuleHelpers(): void { + protected emitConvertModuleHelpers (): void { if (this._jsOptions.runtimeTypecheck) { const { any: anyAnnotation, @@ -332,7 +338,7 @@ export class JavaScriptRenderer extends ConvenienceRenderer { anyMap: anyMapAnnotation, string: stringAnnotation, stringArray: stringArrayAnnotation, - never: neverAnnotation + never: neverAnnotation, } = this.typeAnnotations; this.ensureBlankLine(); this @@ -428,10 +434,10 @@ function transform(val${anyAnnotation}, typ${anyAnnotation}, getProps${anyAnnota Object.getOwnPropertyNames(val).forEach(key => { if (!Object.prototype.hasOwnProperty.call(props, key)) { result[key] = ${ - this._jsOptions.runtimeTypecheckIgnoreUnknownProperties - ? `val[key]` - : `transform(val[key], additional, getProps, key, ref)` - }; + this._jsOptions.runtimeTypecheckIgnoreUnknownProperties + ? "val[key]" + : "transform(val[key], additional, getProps, key, ref)" +}; } }); return result; @@ -496,16 +502,17 @@ function r(name${stringAnnotation}) { } } - protected emitConvertModule(): void { + protected emitConvertModule (): void { this.ensureBlankLine(); this.emitMultiline( - `// Converts JSON ${this._jsOptions.rawType === "json" ? "strings" : "types"} to/from your types` + `// Converts JSON ${this._jsOptions.rawType === "json" ? "strings" : "types"} to/from your types`, ); if (this._jsOptions.runtimeTypecheck) { this.emitMultiline( - `// and asserts the results${this._jsOptions.rawType === "json" ? " of JSON.parse" : ""} at runtime` + `// and asserts the results${this._jsOptions.rawType === "json" ? " of JSON.parse" : ""} at runtime`, ); } + const moduleLine = this.moduleLine; if (moduleLine === undefined) { this.emitConvertModuleBody(); @@ -514,15 +521,15 @@ function r(name${stringAnnotation}) { } } - protected emitTypes(): void { + protected emitTypes (): void { return; } - protected emitUsageImportComment(): void { - this.emitLine('// const Convert = require("./file");'); + protected emitUsageImportComment (): void { + this.emitLine("// const Convert = require(\"./file\");"); } - protected emitUsageComments(): void { + protected emitUsageComments (): void { this.emitMultiline(`// To parse this data: //`); @@ -539,20 +546,20 @@ function r(name${stringAnnotation}) { } } - protected emitModuleExports(): void { + protected emitModuleExports (): void { this.ensureBlankLine(); this.emitBlock("module.exports = ", ";", () => { this.forEachTopLevel("none", (_, name) => { const serializer = this.serializerFunctionName(name); const deserializer = this.deserializerFunctionName(name); - this.emitLine('"', serializer, '": ', serializer, ","); - this.emitLine('"', deserializer, '": ', deserializer, ","); + this.emitLine("\"", serializer, "\": ", serializer, ","); + this.emitLine("\"", deserializer, "\": ", deserializer, ","); }); }); } - protected emitSourceStructure() { + protected emitSourceStructure () { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } else { diff --git a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts index 7d6d90612..7c8927f24 100644 --- a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts +++ b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts @@ -1,21 +1,25 @@ import { TargetLanguage } from "../TargetLanguage"; -import { getOptionValues, Option, OptionValues, EnumOption } from "../RendererOptions"; -import { RenderContext } from "../Renderer"; +import { type Option, type OptionValues} from "../RendererOptions"; +import { getOptionValues, EnumOption } from "../RendererOptions"; +import { type RenderContext } from "../Renderer"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { funPrefixNamer, Name, Namer } from "../Naming"; +import { type Name, type Namer } from "../Naming"; +import { funPrefixNamer } from "../Naming"; import { acronymOption, acronymStyle, AcronymStyleOptions } from "../support/Acronyms"; +import { + type ClassProperty, + type ClassType, + type ObjectType, + type Sourcelike, + type Type, +} from ".."; import { capitalize, - ClassProperty, - ClassType, combineWords, firstUpperWordStyle, matchType, - ObjectType, panic, - Sourcelike, splitIntoWords, - Type } from ".."; import { allLowerWordStyle, utf16StringEscape } from "../support/Strings"; import { isES3IdentifierStart } from "./JavaScriptUnicodeMaps"; @@ -33,29 +37,29 @@ export const javaScriptPropTypesOptions = { "Which module system to use", [ ["common-js", false], - ["es6", true] + ["es6", true], ], - "es6" - ) + "es6", + ), }; export class JavaScriptPropTypesTargetLanguage extends TargetLanguage { - protected getOptions(): Option[] { + protected getOptions (): Array> { return [javaScriptPropTypesOptions.acronymStyle, javaScriptPropTypesOptions.converters]; } - constructor(displayName = "JavaScript PropTypes", names: string[] = ["javascript-prop-types"], extension = "js") { + constructor (displayName = "JavaScript PropTypes", names: string[] = ["javascript-prop-types"], extension = "js") { super(displayName, names, extension); } - protected makeRenderer( + protected makeRenderer ( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } + untypedOptionValues: { [name: string]: any, }, ): JavaScriptPropTypesRenderer { return new JavaScriptPropTypesRenderer( this, renderContext, - getOptionValues(javaScriptPropTypesOptions, untypedOptionValues) + getOptionValues(javaScriptPropTypesOptions, untypedOptionValues), ); } } @@ -63,15 +67,15 @@ export class JavaScriptPropTypesTargetLanguage extends TargetLanguage { const identityNamingFunction = funPrefixNamer("properties", s => s); export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _jsOptions: OptionValues + private readonly _jsOptions: OptionValues, ) { super(targetLanguage, renderContext); } - protected nameStyle(original: string, upper: boolean): string { + protected nameStyle (original: string, upper: boolean): string { const acronyms = acronymStyle(this._jsOptions.acronymStyle); const words = splitIntoWords(original); return combineWords( @@ -82,43 +86,43 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { upper ? s => capitalize(acronyms(s)) : allLowerWordStyle, acronyms, "", - isES3IdentifierStart + isES3IdentifierStart, ); } - protected makeNamedTypeNamer(): Namer { + protected makeNamedTypeNamer (): Namer { return funPrefixNamer("types", s => this.nameStyle(s, true)); } - protected namerForObjectProperty(): Namer { + protected namerForObjectProperty (): Namer { return identityNamingFunction; } - protected makeUnionMemberNamer(): null { + protected makeUnionMemberNamer (): null { return null; } - protected makeEnumCaseNamer(): Namer { + protected makeEnumCaseNamer (): Namer { return funPrefixNamer("enum-cases", s => this.nameStyle(s, false)); } - protected namedTypeToNameForTopLevel(type: Type): Type | undefined { + protected namedTypeToNameForTopLevel (type: Type): Type | undefined { return directlyReachableSingleNamedType(type); } - protected makeNameForProperty( + protected makeNameForProperty ( c: ClassType, className: Name, p: ClassProperty, jsonName: string, - _assignedName: string | undefined + _assignedName: string | undefined, ): Name | undefined { // Ignore the assigned name return super.makeNameForProperty(c, className, p, jsonName, undefined); } - typeMapTypeFor(t: Type, required = true): Sourcelike { - if (["class", "object", "enum"].indexOf(t.kind) >= 0) { + typeMapTypeFor (t: Type, required = true): Sourcelike { + if (["class", "object", "enum"].includes(t.kind)) { return ["_", this.nameForNamedType(t)]; } @@ -136,13 +140,13 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { _enumType => panic("Should already be handled."), unionType => { const children = Array.from(unionType.getChildren()).map((type: Type) => - this.typeMapTypeFor(type, false) + this.typeMapTypeFor(type, false), ); return ["PropTypes.oneOfType([", ...arrayIntercalate(", ", children), "])"]; }, _transformedStringType => { return "PropTypes.string"; - } + }, ); if (required) { @@ -152,11 +156,11 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { return match; } - typeMapTypeForProperty(p: ClassProperty): Sourcelike { + typeMapTypeForProperty (p: ClassProperty): Sourcelike { return this.typeMapTypeFor(p.type); } - private importStatement(lhs: Sourcelike, moduleName: Sourcelike): Sourcelike { + private importStatement (lhs: Sourcelike, moduleName: Sourcelike): Sourcelike { if (this._jsOptions.moduleSystem) { return ["import ", lhs, " from ", moduleName, ";"]; } else { @@ -164,7 +168,7 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { } } - protected emitUsageComments(): void { + protected emitUsageComments (): void { // FIXME: Use the correct type name this.emitCommentLines( [ @@ -178,24 +182,24 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { "", "MyComponent.propTypes = {", " input: MyShape", - "};" + "};", ], - { lineStart: "// " } + { lineStart: "// " }, ); } - protected emitBlock(source: Sourcelike, end: Sourcelike, emit: () => void) { + protected emitBlock (source: Sourcelike, end: Sourcelike, emit: () => void) { this.emitLine(source, "{"); this.indent(emit); this.emitLine("}", end); } - protected emitImports(): void { + protected emitImports (): void { this.ensureBlankLine(); - this.emitLine(this.importStatement("PropTypes", '"prop-types"')); + this.emitLine(this.importStatement("PropTypes", "\"prop-types\"")); } - private emitExport(name: Sourcelike, value: Sourcelike): void { + private emitExport (name: Sourcelike, value: Sourcelike): void { if (this._jsOptions.moduleSystem) { this.emitLine("export const ", name, " = ", value, ";"); } else { @@ -203,7 +207,7 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { } } - protected emitTypes(): void { + protected emitTypes (): void { this.ensureBlankLine(); this.forEachObject("none", (_type: ObjectType, name: Name) => { @@ -278,7 +282,7 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { }); } - private emitObject(name: Name, t: ObjectType) { + private emitObject (name: Name, t: ObjectType) { this.ensureBlankLine(); this.emitLine("_", name, " = PropTypes.shape({"); this.indent(() => { @@ -289,7 +293,7 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { this.emitLine("});"); } - protected emitSourceStructure(): void { + protected emitSourceStructure (): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } else { diff --git a/packages/quicktype-core/src/language/JavaScriptUnicodeMaps.ts b/packages/quicktype-core/src/language/JavaScriptUnicodeMaps.ts index c3f105010..e818aaeb3 100644 --- a/packages/quicktype-core/src/language/JavaScriptUnicodeMaps.ts +++ b/packages/quicktype-core/src/language/JavaScriptUnicodeMaps.ts @@ -1,6 +1,6 @@ // Taken from https://github.com/Microsoft/TypeScript -function lookupInUnicodeMap(code: number, map: ReadonlyArray): boolean { +function lookupInUnicodeMap (code: number, map: readonly number[]): boolean { // Bail out quickly if it couldn't possibly be in the map. if (code < map[0]) { return false; @@ -45,24 +45,24 @@ const enum CharacterCodes { Z = 0x5a } -export function isES3IdentifierStart(ch: number): boolean { +export function isES3IdentifierStart (ch: number): boolean { return ( - (ch >= CharacterCodes.A && ch <= CharacterCodes.Z) || - (ch >= CharacterCodes.a && ch <= CharacterCodes.z) || + ch >= CharacterCodes.A && ch <= CharacterCodes.Z || + ch >= CharacterCodes.a && ch <= CharacterCodes.z || ch === CharacterCodes.$ || ch === CharacterCodes._ || - (ch > CharacterCodes.maxAsciiCharacter && lookupInUnicodeMap(ch, unicodeES3IdentifierStart)) + ch > CharacterCodes.maxAsciiCharacter && lookupInUnicodeMap(ch, unicodeES3IdentifierStart) ); } -export function isES3IdentifierPart(ch: number): boolean { +export function isES3IdentifierPart (ch: number): boolean { return ( - (ch >= CharacterCodes.A && ch <= CharacterCodes.Z) || - (ch >= CharacterCodes.a && ch <= CharacterCodes.z) || - (ch >= CharacterCodes._0 && ch <= CharacterCodes._9) || + ch >= CharacterCodes.A && ch <= CharacterCodes.Z || + ch >= CharacterCodes.a && ch <= CharacterCodes.z || + ch >= CharacterCodes._0 && ch <= CharacterCodes._9 || ch === CharacterCodes.$ || ch === CharacterCodes._ || - (ch > CharacterCodes.maxAsciiCharacter && lookupInUnicodeMap(ch, unicodeES3IdentifierPart)) + ch > CharacterCodes.maxAsciiCharacter && lookupInUnicodeMap(ch, unicodeES3IdentifierPart) ); } @@ -113,7 +113,7 @@ const unicodeES3IdentifierStart = [ 40960, 42124, 44032, 55203, 63744, 64045, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65138, 65140, 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479, - 65482, 65487, 65490, 65495, 65498, 65500 + 65482, 65487, 65490, 65495, 65498, 65500, ]; const unicodeES3IdentifierPart = [ 170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 543, 546, 563, 592, 685, 688, 696, 699, 705, 720, 721, 736, @@ -152,5 +152,5 @@ const unicodeES3IdentifierPart = [ 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65056, 65059, 65075, 65076, 65101, 65103, 65136, 65138, 65140, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65381, 65470, 65474, - 65479, 65482, 65487, 65490, 65495, 65498, 65500 + 65479, 65482, 65487, 65490, 65495, 65498, 65500, ]; diff --git a/packages/quicktype-core/src/language/Kotlin.ts b/packages/quicktype-core/src/language/Kotlin.ts index 407b82300..53d636499 100644 --- a/packages/quicktype-core/src/language/Kotlin.ts +++ b/packages/quicktype-core/src/language/Kotlin.ts @@ -1,10 +1,14 @@ import { iterableSome, arrayIntercalate } from "collection-utils"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { Name, Namer, funPrefixNamer } from "../Naming"; -import { EnumOption, Option, StringOption, OptionValues, getOptionValues } from "../RendererOptions"; -import { Sourcelike, maybeAnnotated, modifySource } from "../Source"; +import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { ConvenienceRenderer } from "../ConvenienceRenderer"; +import { type Name, type Namer} from "../Naming"; +import { funPrefixNamer } from "../Naming"; +import { type Option, type OptionValues} from "../RendererOptions"; +import { EnumOption, StringOption, getOptionValues } from "../RendererOptions"; +import { type Sourcelike} from "../Source"; +import { maybeAnnotated, modifySource } from "../Source"; import { allLowerWordStyle, allUpperWordStyle, @@ -19,23 +23,24 @@ import { isPrintable, legalizeCharacters, splitIntoWords, - utf32ConcatMap + utf32ConcatMap, } from "../support/Strings"; import { assertNever, mustNotHappen } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; +import { + type ClassProperty, + type EnumType, + type ObjectType, + type PrimitiveType, + type Type} from "../Type"; import { ArrayType, - ClassProperty, ClassType, - EnumType, MapType, - ObjectType, - PrimitiveType, - Type, - UnionType + UnionType, } from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { RenderContext } from "../Renderer"; +import { type RenderContext } from "../Renderer"; import { acronymOption, acronymStyle, AcronymStyleOptions } from "../support/Acronyms"; export enum Framework { @@ -53,34 +58,34 @@ export const kotlinOptions = { ["just-types", Framework.None], ["jackson", Framework.Jackson], ["klaxon", Framework.Klaxon], - ["kotlinx", Framework.KotlinX] + ["kotlinx", Framework.KotlinX], ], - "klaxon" + "klaxon", ), acronymStyle: acronymOption(AcronymStyleOptions.Pascal), - packageName: new StringOption("package", "Package", "PACKAGE", "quicktype") + packageName: new StringOption("package", "Package", "PACKAGE", "quicktype"), }; export class KotlinTargetLanguage extends TargetLanguage { - constructor() { + constructor () { super("Kotlin", ["kotlin"], "kt"); } - protected getOptions(): Option[] { + protected getOptions (): Array> { return [kotlinOptions.framework, kotlinOptions.acronymStyle, kotlinOptions.packageName]; } - get supportsOptionalClassProperties(): boolean { + get supportsOptionalClassProperties (): boolean { return true; } - get supportsUnionsWithBothNumberTypes(): boolean { + get supportsUnionsWithBothNumberTypes (): boolean { return true; } - protected makeRenderer( + protected makeRenderer ( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } + untypedOptionValues: { [name: string]: any, }, ): ConvenienceRenderer { const options = getOptionValues(kotlinOptions, untypedOptionValues); @@ -148,23 +153,23 @@ const keywords = [ "JsonObject", "JsonValue", "Converter", - "Klaxon" + "Klaxon", ]; -function isPartCharacter(codePoint: number): boolean { +function isPartCharacter (codePoint: number): boolean { return isLetterOrUnderscore(codePoint) || isNumeric(codePoint); } -function isStartCharacter(codePoint: number): boolean { +function isStartCharacter (codePoint: number): boolean { return isPartCharacter(codePoint) && !isDigit(codePoint); } const legalizeName = legalizeCharacters(isPartCharacter); -function kotlinNameStyle( +function kotlinNameStyle ( isUpper: boolean, original: string, - acronymsStyle: (s: string) => string = allUpperWordStyle + acronymsStyle: (s: string) => string = allUpperWordStyle, ): string { const words = splitIntoWords(original); return combineWords( @@ -175,92 +180,92 @@ function kotlinNameStyle( isUpper ? allUpperWordStyle : allLowerWordStyle, acronymsStyle, "", - isStartCharacter + isStartCharacter, ); } -function unicodeEscape(codePoint: number): string { +function unicodeEscape (codePoint: number): string { return "\\u" + intToHex(codePoint, 4); } const _stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, unicodeEscape)); -function stringEscape(s: string): string { +function stringEscape (s: string): string { // "$this" is a template string in Kotlin so we have to escape $ return _stringEscape(s).replace(/\$/g, "\\$"); } export class KotlinRenderer extends ConvenienceRenderer { - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - protected readonly _kotlinOptions: OptionValues + protected readonly _kotlinOptions: OptionValues, ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace (): string[] { return keywords; } - protected forbiddenForObjectProperties(_o: ObjectType, _classNamed: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties (_o: ObjectType, _classNamed: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { + protected forbiddenForEnumCases (_e: EnumType, _enumName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { + protected forbiddenForUnionMembers (_u: UnionType, _unionName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: false }; } - protected topLevelNameStyle(rawName: string): string { + protected topLevelNameStyle (rawName: string): string { return kotlinNameStyle(true, rawName); } - protected makeNamedTypeNamer(): Namer { + protected makeNamedTypeNamer (): Namer { return funPrefixNamer("upper", s => kotlinNameStyle(true, s, acronymStyle(this._kotlinOptions.acronymStyle))); } - protected namerForObjectProperty(): Namer { + protected namerForObjectProperty (): Namer { return funPrefixNamer("lower", s => kotlinNameStyle(false, s, acronymStyle(this._kotlinOptions.acronymStyle))); } - protected makeUnionMemberNamer(): Namer { + protected makeUnionMemberNamer (): Namer { return funPrefixNamer("upper", s => kotlinNameStyle(true, s) + "Value"); } - protected makeEnumCaseNamer(): Namer { + protected makeEnumCaseNamer (): Namer { return funPrefixNamer("upper", s => kotlinNameStyle(true, s, acronymStyle(this._kotlinOptions.acronymStyle))); } - protected emitDescriptionBlock(lines: Sourcelike[]): void { + protected emitDescriptionBlock (lines: Sourcelike[]): void { this.emitCommentLines(lines, { lineStart: " * ", beforeComment: "/**", afterComment: " */" }); } - protected emitBlock(line: Sourcelike, f: () => void, delimiter: "curly" | "paren" | "lambda" = "curly"): void { + protected emitBlock (line: Sourcelike, f: () => void, delimiter: "curly" | "paren" | "lambda" = "curly"): void { const [open, close] = delimiter === "curly" ? ["{", "}"] : delimiter === "paren" ? ["(", ")"] : ["{", "})"]; this.emitLine(line, " ", open); this.indent(f); this.emitLine(close); } - protected anySourceType(optional: string): Sourcelike { + protected anySourceType (optional: string): Sourcelike { return ["Any", optional]; } // (asarazan): I've broken out the following two functions // because some renderers, such as kotlinx, can cope with `any`, while some get mad. - protected arrayType(arrayType: ArrayType, withIssues = false, _noOptional = false): Sourcelike { + protected arrayType (arrayType: ArrayType, withIssues = false, _noOptional = false): Sourcelike { return ["List<", this.kotlinType(arrayType.items, withIssues), ">"]; } - protected mapType(mapType: MapType, withIssues = false, _noOptional = false): Sourcelike { + protected mapType (mapType: MapType, withIssues = false, _noOptional = false): Sourcelike { return ["Map"]; } - protected kotlinType(t: Type, withIssues = false, noOptional = false): Sourcelike { + protected kotlinType (t: Type, withIssues = false, noOptional = false): Sourcelike { const optional = noOptional ? "" : "?"; return matchType( t, @@ -282,15 +287,15 @@ export class KotlinRenderer extends ConvenienceRenderer { const nullable = nullableFromUnion(unionType); if (nullable !== null) return [this.kotlinType(nullable, withIssues), optional]; return this.nameForNamedType(unionType); - } + }, ); } - protected emitUsageHeader(): void { + protected emitUsageHeader (): void { // To be overridden } - protected emitHeader(): void { + protected emitHeader (): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } else { @@ -302,23 +307,23 @@ export class KotlinRenderer extends ConvenienceRenderer { this.ensureBlankLine(); } - protected emitTopLevelArray(t: ArrayType, name: Name): void { + protected emitTopLevelArray (t: ArrayType, name: Name): void { const elementType = this.kotlinType(t.items); this.emitLine(["typealias ", name, " = ArrayList<", elementType, ">"]); } - protected emitTopLevelMap(t: MapType, name: Name): void { + protected emitTopLevelMap (t: MapType, name: Name): void { const elementType = this.kotlinType(t.values); this.emitLine(["typealias ", name, " = HashMap"]); } - protected emitEmptyClassDefinition(c: ClassType, className: Name): void { + protected emitEmptyClassDefinition (c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); this.emitClassAnnotations(c, className); this.emitLine("class ", className, "()"); } - protected emitClassDefinition(c: ClassType, className: Name): void { + protected emitClassDefinition (c: ClassType, className: Name): void { if (c.getProperties().size === 0) { this.emitEmptyClassDefinition(c, className); return; @@ -372,19 +377,19 @@ export class KotlinRenderer extends ConvenienceRenderer { this.emitClassDefinitionMethods(c, className); } - protected emitClassDefinitionMethods(_c: ClassType, _className: Name) { + protected emitClassDefinitionMethods (_c: ClassType, _className: Name) { this.emitLine(")"); } - protected emitClassAnnotations(_c: Type, _className: Name) { + protected emitClassAnnotations (_c: Type, _className: Name) { // to be overridden } - protected renameAttribute(_name: Name, _jsonName: string, _required: boolean, _meta: Array<() => void>) { + protected renameAttribute (_name: Name, _jsonName: string, _required: boolean, _meta: Array<() => void>) { // to be overridden } - protected emitEnumDefinition(e: EnumType, enumName: Name): void { + protected emitEnumDefinition (e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); this.emitBlock(["enum class ", enumName], () => { @@ -395,8 +400,8 @@ export class KotlinRenderer extends ConvenienceRenderer { }); } - protected emitUnionDefinition(u: UnionType, unionName: Name): void { - function sortBy(t: Type): string { + protected emitUnionDefinition (u: UnionType, unionName: Name): void { + function sortBy (t: Type): string { const kind = t.kind; if (kind === "class") return kind; return "_" + kind; @@ -412,15 +417,16 @@ export class KotlinRenderer extends ConvenienceRenderer { this.forEachUnionMember(u, nonNulls, "none", null, (name, t) => { table.push([ ["class ", name, "(val value: ", this.kotlinType(t), ")"], - [" : ", unionName, "()"] + [" : ", unionName, "()"], ]); }); if (maybeNull !== null) { table.push([ ["class ", this.nameForUnionMember(u, maybeNull), "()"], - [" : ", unionName, "()"] + [" : ", unionName, "()"], ]); } + this.emitTable(table); } @@ -428,16 +434,16 @@ export class KotlinRenderer extends ConvenienceRenderer { }); } - protected emitUnionDefinitionMethods( + protected emitUnionDefinitionMethods ( _u: UnionType, _nonNulls: ReadonlySet, _maybeNull: PrimitiveType | null, - _unionName: Name + _unionName: Name, ) { // to be overridden } - protected emitSourceStructure(): void { + protected emitSourceStructure (): void { this.emitHeader(); // Top-level arrays, maps @@ -453,21 +459,21 @@ export class KotlinRenderer extends ConvenienceRenderer { "leading-and-interposing", (c: ClassType, n: Name) => this.emitClassDefinition(c, n), (e, n) => this.emitEnumDefinition(e, n), - (u, n) => this.emitUnionDefinition(u, n) + (u, n) => this.emitUnionDefinition(u, n), ); } } export class KotlinKlaxonRenderer extends KotlinRenderer { - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - _kotlinOptions: OptionValues + _kotlinOptions: OptionValues, ) { super(targetLanguage, renderContext, _kotlinOptions); } - private unionMemberFromJsonValue(t: Type, e: Sourcelike): Sourcelike { + private unionMemberFromJsonValue (t: Type, e: Sourcelike): Sourcelike { return matchType( t, _anyType => [e, ".inside"], @@ -480,11 +486,11 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { _classType => [e, ".obj?.let { klaxon.parseFromJsonObject<", this.kotlinType(t), ">(it) }"], _mapType => [e, ".obj?.let { klaxon.parseFromJsonObject<", this.kotlinType(t), ">(it) }"], enumType => [e, ".string?.let { ", this.kotlinType(enumType), ".fromValue(it) }"], - _unionType => mustNotHappen() + _unionType => mustNotHappen(), ); } - private unionMemberJsonValueGuard(t: Type, _e: Sourcelike): Sourcelike { + private unionMemberJsonValueGuard (t: Type, _e: Sourcelike): Sourcelike { return matchType( t, _anyType => "is Any", @@ -501,11 +507,11 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { // This could be stricter, but for now we don't allow strings // and enums in the same union _enumType => "is String", - _unionType => mustNotHappen() + _unionType => mustNotHappen(), ); } - protected emitUsageHeader(): void { + protected emitUsageHeader (): void { this.emitLine("// To parse the JSON, install Klaxon and do:"); this.emitLine("//"); this.forEachTopLevel("none", (_, name) => { @@ -513,18 +519,18 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { }); } - protected emitHeader(): void { + protected emitHeader (): void { super.emitHeader(); this.emitLine("import com.beust.klaxon.*"); const hasUnions = iterableSome( this.typeGraph.allNamedTypes(), - t => t instanceof UnionType && nullableFromUnion(t) === null + t => t instanceof UnionType && nullableFromUnion(t) === null, ); const hasEmptyObjects = iterableSome( this.typeGraph.allNamedTypes(), - c => c instanceof ClassType && c.getProperties().size === 0 + c => c instanceof ClassType && c.getProperties().size === 0, ); if (hasUnions || this.haveEnums || hasEmptyObjects) { this.emitGenericConverter(); @@ -534,18 +540,19 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { if (hasEmptyObjects) { converters.push([[".convert(JsonObject::class,"], [" { it.obj!! },"], [" { it.toJsonString() })"]]); } + this.forEachEnum("none", (_, name) => { converters.push([ [".convert(", name, "::class,"], [" { ", name, ".fromValue(it.string!!) },"], - [' { "\\"${it.value}\\"" })'] + [" { \"\\\"${it.value}\\\"\" })"], ]); }); this.forEachUnion("none", (_, name) => { converters.push([ [".convert(", name, "::class,"], [" { ", name, ".fromJson(it) },"], - [" { it.toJson() }, true)"] + [" { it.toJson() }, true)"], ]); }); @@ -556,7 +563,7 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { } } - protected emitTopLevelArray(t: ArrayType, name: Name): void { + protected emitTopLevelArray (t: ArrayType, name: Name): void { const elementType = this.kotlinType(t.items); this.emitBlock( ["class ", name, "(elements: Collection<", elementType, ">) : ArrayList<", elementType, ">(elements)"], @@ -569,14 +576,14 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { name, "(klaxon.parseArray<", elementType, - ">(json)!!)" + ">(json)!!)", ); }); - } + }, ); } - protected emitTopLevelMap(t: MapType, name: Name): void { + protected emitTopLevelMap (t: MapType, name: Name): void { const elementType = this.kotlinType(t.values); this.emitBlock( [ @@ -586,7 +593,7 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { elementType, ">) : HashMap(elements)" + ">(elements)", ], () => { this.emitLine("public fun toJson() = klaxon.toJsonString(this)"); @@ -598,36 +605,38 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { this.emitLine( "klaxon.parseJsonObject(java.io.StringReader(json)) as Map" + ">", ); }, - "paren" + "paren", ); }); - } + }, ); } - private klaxonRenameAttribute(propName: Name, jsonName: string, ignore = false): Sourcelike | undefined { + private klaxonRenameAttribute (propName: Name, jsonName: string, ignore = false): Sourcelike | undefined { const escapedName = stringEscape(jsonName); const namesDiffer = this.sourcelikeToString(propName) !== escapedName; const properties: Sourcelike[] = []; if (namesDiffer) { - properties.push(['name = "', escapedName, '"']); + properties.push(["name = \"", escapedName, "\""]); } + if (ignore) { properties.push("ignored = true"); } + return properties.length === 0 ? undefined : ["@Json(", arrayIntercalate(", ", properties), ")"]; } - protected emitEmptyClassDefinition(c: ClassType, className: Name): void { + protected emitEmptyClassDefinition (c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); this.emitLine("typealias ", className, " = JsonObject"); } - protected emitClassDefinitionMethods(c: ClassType, className: Name) { + protected emitClassDefinitionMethods (c: ClassType, className: Name) { const isTopLevel = iterableSome(this.topLevels, ([_, top]) => top === c); if (isTopLevel) { this.emitBlock(")", () => { @@ -642,14 +651,14 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { } } - protected renameAttribute(name: Name, jsonName: string, _required: boolean, meta: Array<() => void>) { + protected renameAttribute (name: Name, jsonName: string, _required: boolean, meta: Array<() => void>) { const rename = this.klaxonRenameAttribute(name, jsonName); if (rename !== undefined) { meta.push(() => this.emitLine(rename)); } } - protected emitEnumDefinition(e: EnumType, enumName: Name): void { + protected emitEnumDefinition (e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); this.emitBlock(["enum class ", enumName, "(val value: String)"], () => { @@ -671,33 +680,33 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { }); } - private emitGenericConverter(): void { + private emitGenericConverter (): void { this.ensureBlankLine(); this.emitLine( - "private fun Klaxon.convert(k: kotlin.reflect.KClass<*>, fromJson: (JsonValue) -> T, toJson: (T) -> String, isUnion: Boolean = false) =" + "private fun Klaxon.convert(k: kotlin.reflect.KClass<*>, fromJson: (JsonValue) -> T, toJson: (T) -> String, isUnion: Boolean = false) =", ); this.indent(() => { this.emitLine("this.converter(object: Converter {"); this.indent(() => { - this.emitLine(`@Suppress("UNCHECKED_CAST")`); + this.emitLine("@Suppress(\"UNCHECKED_CAST\")"); this.emitTable([ ["override fun toJson(value: Any)", " = toJson(value as T)"], ["override fun fromJson(jv: JsonValue)", " = fromJson(jv) as Any"], [ "override fun canConvert(cls: Class<*>)", - " = cls == k.java || (isUnion && cls.superclass == k.java)" - ] + " = cls == k.java || (isUnion && cls.superclass == k.java)", + ], ]); }); this.emitLine("})"); }); } - protected emitUnionDefinitionMethods( + protected emitUnionDefinitionMethods ( u: UnionType, nonNulls: ReadonlySet, maybeNull: PrimitiveType | null, - unionName: Name + unionName: Name, ) { this.ensureBlankLine(); this.emitLine("public fun toJson(): String = klaxon.toJsonString(when (this) {"); @@ -708,8 +717,9 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { }); if (maybeNull !== null) { const name = this.nameForUnionMember(u, maybeNull); - toJsonTable.push([["is ", name], [' -> "null"']]); + toJsonTable.push([["is ", name], [" -> \"null\""]]); } + this.emitTable(toJsonTable); }); this.emitLine("})"); @@ -721,13 +731,14 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { this.forEachUnionMember(u, nonNulls, "none", null, (name, t) => { table.push([ [this.unionMemberJsonValueGuard(t, "jv.inside")], - [" -> ", name, "(", this.unionMemberFromJsonValue(t, "jv"), "!!)"] + [" -> ", name, "(", this.unionMemberFromJsonValue(t, "jv"), "!!)"], ]); }); if (maybeNull !== null) { const name = this.nameForUnionMember(u, maybeNull); table.push([[this.unionMemberJsonValueGuard(maybeNull, "jv.inside")], [" -> ", name, "()"]]); } + table.push([["else"], [" -> throw IllegalArgumentException()"]]); this.emitTable(table); }); @@ -737,15 +748,15 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { } export class KotlinJacksonRenderer extends KotlinRenderer { - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - _kotlinOptions: OptionValues + _kotlinOptions: OptionValues, ) { super(targetLanguage, renderContext, _kotlinOptions); } - private unionMemberJsonValueGuard(t: Type, _e: Sourcelike): Sourcelike { + private unionMemberJsonValueGuard (t: Type, _e: Sourcelike): Sourcelike { return matchType( t, _anyType => "is Any", @@ -762,11 +773,11 @@ export class KotlinJacksonRenderer extends KotlinRenderer { // This could be stricter, but for now we don't allow strings // and enums in the same union _enumType => "is TextNode", - _unionType => mustNotHappen() + _unionType => mustNotHappen(), ); } - protected emitUsageHeader(): void { + protected emitUsageHeader (): void { this.emitLine("// To parse the JSON, install jackson-module-kotlin and do:"); this.emitLine("//"); this.forEachTopLevel("none", (_, name) => { @@ -774,7 +785,7 @@ export class KotlinJacksonRenderer extends KotlinRenderer { }); } - protected emitHeader(): void { + protected emitHeader (): void { super.emitHeader(); this.emitMultiline(`import com.fasterxml.jackson.annotation.* @@ -788,11 +799,11 @@ import com.fasterxml.jackson.module.kotlin.*`); const hasUnions = iterableSome( this.typeGraph.allNamedTypes(), - t => t instanceof UnionType && nullableFromUnion(t) === null + t => t instanceof UnionType && nullableFromUnion(t) === null, ); const hasEmptyObjects = iterableSome( this.typeGraph.allNamedTypes(), - c => c instanceof ClassType && c.getProperties().size === 0 + c => c instanceof ClassType && c.getProperties().size === 0, ); if (hasUnions || this.haveEnums || hasEmptyObjects) { this.emitGenericConverter(); @@ -806,14 +817,14 @@ import com.fasterxml.jackson.module.kotlin.*`); converters.push([ ["convert(", name, "::class,"], [" { ", name, ".fromValue(it.asText()) },"], - [' { "\\"${it.value}\\"" })'] + [" { \"\\\"${it.value}\\\"\" })"], ]); }); this.forEachUnion("none", (_, name) => { converters.push([ ["convert(", name, "::class,"], [" { ", name, ".fromJson(it) },"], - [" { it.toJson() }, true)"] + [" { it.toJson() }, true)"], ]); }); @@ -831,7 +842,7 @@ import com.fasterxml.jackson.module.kotlin.*`); this.emitLine("}"); } - protected emitTopLevelArray(t: ArrayType, name: Name): void { + protected emitTopLevelArray (t: ArrayType, name: Name): void { const elementType = this.kotlinType(t.items); this.emitBlock( ["class ", name, "(elements: Collection<", elementType, ">) : ArrayList<", elementType, ">(elements)"], @@ -841,11 +852,11 @@ import com.fasterxml.jackson.module.kotlin.*`); this.emitBlock("companion object", () => { this.emitLine("fun fromJson(json: String) = mapper.readValue<", name, ">(json)"); }); - } + }, ); } - protected emitTopLevelMap(t: MapType, name: Name): void { + protected emitTopLevelMap (t: MapType, name: Name): void { const elementType = this.kotlinType(t.values); this.emitBlock( [ @@ -855,7 +866,7 @@ import com.fasterxml.jackson.module.kotlin.*`); elementType, ">) : HashMap(elements)" + ">(elements)", ], () => { this.emitLine("fun toJson() = mapper.writeValueAsString(this)"); @@ -863,15 +874,15 @@ import com.fasterxml.jackson.module.kotlin.*`); this.emitBlock("companion object", () => { this.emitLine("fun fromJson(json: String) = mapper.readValue<", name, ">(json)"); }); - } + }, ); } - private jacksonRenameAttribute( + private jacksonRenameAttribute ( propName: Name, jsonName: string, required: boolean, - ignore = false + ignore = false, ): Sourcelike | undefined { const escapedName = stringEscape(jsonName); const namesDiffer = this.sourcelikeToString(propName) !== escapedName; @@ -880,8 +891,9 @@ import com.fasterxml.jackson.module.kotlin.*`); const propertyOpts: Sourcelike[] = []; if (namesDiffer || isPrefixBool) { - propertyOpts.push('"' + escapedName + '"'); + propertyOpts.push("\"" + escapedName + "\""); } + if (required) { propertyOpts.push("required=true"); } @@ -895,16 +907,17 @@ import com.fasterxml.jackson.module.kotlin.*`); properties.push("@get:JsonIgnore"); properties.push("@field:JsonIgnore"); } + return properties.length === 0 ? undefined : properties; } - protected emitEmptyClassDefinition(c: ClassType, className: Name): void { + protected emitEmptyClassDefinition (c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); this.emitLine("typealias ", className, " = JsonNode"); } - protected emitClassDefinitionMethods(c: ClassType, className: Name) { + protected emitClassDefinitionMethods (c: ClassType, className: Name) { const isTopLevel = iterableSome(this.topLevels, ([_, top]) => top === c); if (isTopLevel) { this.emitBlock(")", () => { @@ -919,14 +932,14 @@ import com.fasterxml.jackson.module.kotlin.*`); } } - protected renameAttribute(name: Name, jsonName: string, required: boolean, meta: Array<() => void>) { + protected renameAttribute (name: Name, jsonName: string, required: boolean, meta: Array<() => void>) { const rename = this.jacksonRenameAttribute(name, jsonName, required); if (rename !== undefined) { meta.push(() => this.emitLine(rename)); } } - protected emitEnumDefinition(e: EnumType, enumName: Name): void { + protected emitEnumDefinition (e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); this.emitBlock(["enum class ", enumName, "(val value: String)"], () => { @@ -948,7 +961,7 @@ import com.fasterxml.jackson.module.kotlin.*`); }); } - private emitGenericConverter(): void { + private emitGenericConverter (): void { this.ensureBlankLine(); this.emitMultiline(` @Suppress("UNCHECKED_CAST") @@ -962,11 +975,11 @@ private fun ObjectMapper.convert(k: kotlin.reflect.KClass<*>, fromJson: (Jso })`); } - protected emitUnionDefinitionMethods( + protected emitUnionDefinitionMethods ( u: UnionType, nonNulls: ReadonlySet, maybeNull: PrimitiveType | null, - unionName: Name + unionName: Name, ) { this.ensureBlankLine(); this.emitLine("fun toJson(): String = mapper.writeValueAsString(when (this) {"); @@ -977,8 +990,9 @@ private fun ObjectMapper.convert(k: kotlin.reflect.KClass<*>, fromJson: (Jso }); if (maybeNull !== null) { const name = this.nameForUnionMember(u, maybeNull); - toJsonTable.push([["is ", name], [' -> "null"']]); + toJsonTable.push([["is ", name], [" -> \"null\""]]); } + this.emitTable(toJsonTable); }); this.emitLine("})"); @@ -994,6 +1008,7 @@ private fun ObjectMapper.convert(k: kotlin.reflect.KClass<*>, fromJson: (Jso const name = this.nameForUnionMember(u, maybeNull); table.push([[this.unionMemberJsonValueGuard(maybeNull, "jn")], [" -> ", name, "()"]]); } + table.push([["else"], [" -> throw IllegalArgumentException()"]]); this.emitTable(table); }); @@ -1007,37 +1022,39 @@ private fun ObjectMapper.convert(k: kotlin.reflect.KClass<*>, fromJson: (Jso * TODO: Union, Any, Top Level Array, Top Level Map */ export class KotlinXRenderer extends KotlinRenderer { - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - _kotlinOptions: OptionValues + _kotlinOptions: OptionValues, ) { super(targetLanguage, renderContext, _kotlinOptions); } - protected anySourceType(optional: string): Sourcelike { + protected anySourceType (optional: string): Sourcelike { return ["JsonElement", optional]; } - protected arrayType(arrayType: ArrayType, withIssues = false, noOptional = false): Sourcelike { + protected arrayType (arrayType: ArrayType, withIssues = false, noOptional = false): Sourcelike { const valType = this.kotlinType(arrayType.items, withIssues, true); const name = this.sourcelikeToString(valType); if (name === "JsonObject" || name === "JsonElement") { return "JsonArray"; } + return super.arrayType(arrayType, withIssues, noOptional); } - protected mapType(mapType: MapType, withIssues = false, noOptional = false): Sourcelike { + protected mapType (mapType: MapType, withIssues = false, noOptional = false): Sourcelike { const valType = this.kotlinType(mapType.values, withIssues, true); const name = this.sourcelikeToString(valType); if (name === "JsonObject" || name === "JsonElement") { return "JsonObject"; } + return super.mapType(mapType, withIssues, noOptional); } - protected emitTopLevelMap(t: MapType, name: Name): void { + protected emitTopLevelMap (t: MapType, name: Name): void { const elementType = this.kotlinType(t.values); if (elementType === "JsonObject") { this.emitLine(["typealias ", name, " = JsonObject"]); @@ -1046,12 +1063,12 @@ export class KotlinXRenderer extends KotlinRenderer { } } - protected emitTopLevelArray(t: ArrayType, name: Name): void { + protected emitTopLevelArray (t: ArrayType, name: Name): void { const elementType = this.kotlinType(t.items); this.emitLine(["typealias ", name, " = JsonArray<", elementType, ">"]); } - protected emitUsageHeader(): void { + protected emitUsageHeader (): void { this.emitLine("// To parse the JSON, install kotlin's serialization plugin and do:"); this.emitLine("//"); const table: Sourcelike[][] = []; @@ -1060,13 +1077,13 @@ export class KotlinXRenderer extends KotlinRenderer { table.push([ "// val ", modifySource(camelCase, name), - ` = json.parse(${this.sourcelikeToString(name)}.serializer(), jsonString)` + ` = json.parse(${this.sourcelikeToString(name)}.serializer(), jsonString)`, ]); }); this.emitTable(table); } - protected emitHeader(): void { + protected emitHeader (): void { super.emitHeader(); this.emitLine("import kotlinx.serialization.*"); @@ -1075,27 +1092,28 @@ export class KotlinXRenderer extends KotlinRenderer { this.emitLine("import kotlinx.serialization.encoding.*"); } - protected emitClassAnnotations(_c: Type, _className: Name) { + protected emitClassAnnotations (_c: Type, _className: Name) { this.emitLine("@Serializable"); } - protected renameAttribute(name: Name, jsonName: string, _required: boolean, meta: Array<() => void>) { + protected renameAttribute (name: Name, jsonName: string, _required: boolean, meta: Array<() => void>) { const rename = this._rename(name, jsonName); if (rename !== undefined) { meta.push(() => this.emitLine(rename)); } } - private _rename(propName: Name, jsonName: string): Sourcelike | undefined { + private _rename (propName: Name, jsonName: string): Sourcelike | undefined { const escapedName = stringEscape(jsonName); const namesDiffer = this.sourcelikeToString(propName) !== escapedName; if (namesDiffer) { - return ['@SerialName("', escapedName, '")']; + return ["@SerialName(\"", escapedName, "\")"]; } + return undefined; } - protected emitEnumDefinition(e: EnumType, enumName: Name): void { + protected emitEnumDefinition (e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); this.emitLine(["@Serializable"]); diff --git a/packages/quicktype-core/src/language/Objective-C.ts b/packages/quicktype-core/src/language/Objective-C.ts index b1a44e899..00235121c 100644 --- a/packages/quicktype-core/src/language/Objective-C.ts +++ b/packages/quicktype-core/src/language/Objective-C.ts @@ -1,10 +1,13 @@ import { iterableSome, iterableFirst, mapContains, mapFirst, mapSome } from "collection-utils"; import { TargetLanguage } from "../TargetLanguage"; -import { Type, ClassType, EnumType, ArrayType, MapType, UnionType, ClassProperty } from "../Type"; +import { type ClassProperty } from "../Type"; +import { Type, ClassType, EnumType, ArrayType, MapType, UnionType } from "../Type"; import { matchType, nullableFromUnion, isAnyOrNull } from "../TypeUtils"; -import { Name, Namer, funPrefixNamer } from "../Naming"; -import { Sourcelike, modifySource } from "../Source"; +import { type Name} from "../Naming"; +import { Namer, funPrefixNamer } from "../Naming"; +import { type Sourcelike} from "../Source"; +import { modifySource } from "../Source"; import { splitIntoWords, combineWords, @@ -16,17 +19,21 @@ import { stringEscape, addPrefixIfNecessary, repeatString, - fastIsUpperCase + fastIsUpperCase, } from "../support/Strings"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { StringOption, BooleanOption, EnumOption, Option, getOptionValues, OptionValues } from "../RendererOptions"; +import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { ConvenienceRenderer } from "../ConvenienceRenderer"; +import { type Option, type OptionValues } from "../RendererOptions"; +import { StringOption, BooleanOption, EnumOption, getOptionValues } from "../RendererOptions"; import { assert, defined } from "../support/Support"; -import { RenderContext } from "../Renderer"; +import { type RenderContext } from "../Renderer"; import unicode from "unicode-properties"; export type MemoryAttribute = "assign" | "strong" | "copy"; -export type OutputFeatures = { interface: boolean; implementation: boolean }; +export interface OutputFeatures { + implementation: boolean; interface: boolean; +} const DEBUG = false; const DEFAULT_CLASS_PREFIX = "QT"; @@ -35,38 +42,38 @@ export const objcOptions = { features: new EnumOption("features", "Interface and implementation", [ ["all", { interface: true, implementation: true }], ["interface", { interface: true, implementation: false }], - ["implementation", { interface: false, implementation: true }] + ["implementation", { interface: false, implementation: true }], ]), justTypes: new BooleanOption("just-types", "Plain types only", false), marshallingFunctions: new BooleanOption("functions", "C-style functions", false), classPrefix: new StringOption("class-prefix", "Class prefix", "PREFIX", DEFAULT_CLASS_PREFIX), - extraComments: new BooleanOption("extra-comments", "Extra comments", false) + extraComments: new BooleanOption("extra-comments", "Extra comments", false), }; export class ObjectiveCTargetLanguage extends TargetLanguage { - constructor() { + constructor () { super("Objective-C", ["objc", "objective-c", "objectivec"], "m"); } - protected getOptions(): Option[] { + protected getOptions (): Array> { return [ objcOptions.justTypes, objcOptions.classPrefix, objcOptions.features, objcOptions.extraComments, - objcOptions.marshallingFunctions + objcOptions.marshallingFunctions, ]; } - protected makeRenderer( + protected makeRenderer ( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } + untypedOptionValues: { [name: string]: any, }, ): ObjectiveCRenderer { return new ObjectiveCRenderer(this, renderContext, getOptionValues(objcOptions, untypedOptionValues)); } } -function typeNameStyle(prefix: string, original: string): string { +function typeNameStyle (prefix: string, original: string): string { const words = splitIntoWords(original); const result = combineWords( words, @@ -76,12 +83,12 @@ function typeNameStyle(prefix: string, original: string): string { allUpperWordStyle, allUpperWordStyle, "", - isStartCharacter + isStartCharacter, ); return addPrefixIfNecessary(prefix, result); } -function propertyNameStyle(original: string, isBool = false): string { +function propertyNameStyle (original: string, isBool = false): string { // Objective-C developers are uncomfortable with property "id" // so we use an alternate name in this special case. if (original === "id") { @@ -93,14 +100,14 @@ function propertyNameStyle(original: string, isBool = false): string { if (isBool) { if (words.length === 0) { words = [{ word: "flag", isAcronym: false }]; - } else if (!words[0].isAcronym && booleanPrefixes.indexOf(words[0].word) < 0) { + } else if (!words[0].isAcronym && !booleanPrefixes.includes(words[0].word)) { words = [{ word: "is", isAcronym: false }, ...words]; } } // Properties cannot even begin with any of the forbidden names // For example, properies named new* are treated differently by ARC - if (words.length > 0 && forbiddenPropertyNames.indexOf(words[0].word) >= 0) { + if (words.length > 0 && forbiddenPropertyNames.includes(words[0].word)) { words = [{ word: "the", isAcronym: false }, ...words]; } @@ -112,7 +119,7 @@ function propertyNameStyle(original: string, isBool = false): string { allLowerWordStyle, allUpperWordStyle, "", - isStartCharacter + isStartCharacter, ); } @@ -164,7 +171,7 @@ const keywords = [ "unsigned", "void", "volatile", - "while" + "while", ]; const forbiddenPropertyNames = [ @@ -176,7 +183,7 @@ const forbiddenPropertyNames = [ "mutableCopy", "superclass", "debugDescription", - "new" + "new", ]; const booleanPrefixes = [ @@ -196,16 +203,16 @@ const booleanPrefixes = [ "requires", "require", "needs", - "need" + "need", ]; -function isStartCharacter(utf16Unit: number): boolean { +function isStartCharacter (utf16Unit: number): boolean { return unicode.isAlphabetic(utf16Unit) || utf16Unit === 0x5f; // underscore } -function isPartCharacter(utf16Unit: number): boolean { +function isPartCharacter (utf16Unit: number): boolean { const category: string = unicode.getCategory(utf16Unit); - return ["Nd", "Pc", "Mn", "Mc"].indexOf(category) >= 0 || isStartCharacter(utf16Unit); + return ["Nd", "Pc", "Mn", "Mc"].includes(category) || isStartCharacter(utf16Unit); } const legalizeName = utf16LegalizeCharacters(isPartCharacter); @@ -213,7 +220,7 @@ const legalizeName = utf16LegalizeCharacters(isPartCharacter); const staticEnumValuesIdentifier = "values"; const forbiddenForEnumCases = ["new", staticEnumValuesIdentifier]; -function splitExtension(filename: string): [string, string] { +function splitExtension (filename: string): [string, string] { const i = filename.lastIndexOf("."); const extension = i !== -1 ? filename.split(".").pop() : "m"; filename = i !== -1 ? filename.slice(0, i) : filename; @@ -222,12 +229,13 @@ function splitExtension(filename: string): [string, string] { export class ObjectiveCRenderer extends ConvenienceRenderer { private _currentFilename: string | undefined; + private readonly _classPrefix: string; - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues + private readonly _options: OptionValues, ) { super(targetLanguage, renderContext); @@ -240,98 +248,99 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { } } - private inferClassPrefix(name: string): string { + private inferClassPrefix (name: string): string { const l = name.length; let firstNonUpper = 0; while (firstNonUpper < l && fastIsUpperCase(name.charCodeAt(firstNonUpper))) { firstNonUpper += 1; } + if (firstNonUpper < 2) return DEFAULT_CLASS_PREFIX; return name.slice(0, firstNonUpper - 1); } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace (): string[] { return keywords; } - protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties (_c: ClassType, _className: Name): ForbiddenWordsInfo { return { names: forbiddenPropertyNames, includeGlobalForbidden: true }; } - protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { + protected forbiddenForEnumCases (_e: EnumType, _enumName: Name): ForbiddenWordsInfo { return { names: forbiddenForEnumCases, includeGlobalForbidden: true }; } - protected makeNamedTypeNamer(): Namer { + protected makeNamedTypeNamer (): Namer { return funPrefixNamer("types", rawName => typeNameStyle(this._classPrefix, rawName)); } - protected namerForObjectProperty(_: ClassType, p: ClassProperty): Namer { + protected namerForObjectProperty (_: ClassType, p: ClassProperty): Namer { // TODO why is underscore being removed? return new Namer("properties", s => propertyNameStyle(s, p.type.kind === "bool"), [ "_", "the", "one", "some", - "another" + "another", ]); } - protected makeUnionMemberNamer(): null { + protected makeUnionMemberNamer (): null { return null; } - protected makeEnumCaseNamer(): Namer { + protected makeEnumCaseNamer (): Namer { return new Namer("enum-cases", propertyNameStyle, []); } - protected namedTypeToNameForTopLevel(type: Type): Type | undefined { + protected namedTypeToNameForTopLevel (type: Type): Type | undefined { return type; } - protected emitDescriptionBlock(lines: Sourcelike[]): void { + protected emitDescriptionBlock (lines: Sourcelike[]): void { this.emitCommentLines(lines, { lineStart: "/// " }); } - protected emitBlock(line: Sourcelike, f: () => void): void { + protected emitBlock (line: Sourcelike, f: () => void): void { this.emitLine(line, " {"); this.indent(f); this.emitLine("}"); } - protected emitMethod(declaration: Sourcelike, f: () => void) { + protected emitMethod (declaration: Sourcelike, f: () => void) { this.emitLine(declaration); this.emitLine("{"); this.indent(f); this.emitLine("}"); } - protected emitExtraComments(...comments: Sourcelike[]) { + protected emitExtraComments (...comments: Sourcelike[]) { if (!this._options.extraComments) return; for (const comment of comments) { this.emitLine("// ", comment); } } - protected startFile(basename: Sourcelike, extension: string): void { + protected startFile (basename: Sourcelike, extension: string): void { assert(this._currentFilename === undefined, "Previous file wasn't finished"); // FIXME: The filenames should actually be Sourcelikes, too this._currentFilename = `${this.sourcelikeToString(basename)}.${extension}`; } - protected finishFile(): void { + protected finishFile (): void { super.finishFile(defined(this._currentFilename)); this._currentFilename = undefined; } - protected memoryAttribute(t: Type, isNullable: boolean): MemoryAttribute { + protected memoryAttribute (t: Type, isNullable: boolean): MemoryAttribute { return matchType( t, _anyType => "copy", _nullType => "copy", - _boolType => (isNullable ? "strong" : "assign"), - _integerType => (isNullable ? "strong" : "assign"), - _doubleType => (isNullable ? "strong" : "assign"), + _boolType => isNullable ? "strong" : "assign", + _integerType => isNullable ? "strong" : "assign", + _doubleType => isNullable ? "strong" : "assign", _stringType => "copy", _arrayType => "copy", _classType => "strong", @@ -340,19 +349,19 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { unionType => { const nullable = nullableFromUnion(unionType); return nullable !== null ? this.memoryAttribute(nullable, true) : "copy"; - } + }, ); } - protected objcType(t: Type, nullableOrBoxed = false): [Sourcelike, string] { + protected objcType (t: Type, nullableOrBoxed = false): [Sourcelike, string] { return matchType<[Sourcelike, string]>( t, _anyType => ["id", ""], // For now, we're treating nulls just like any _nullType => ["id", ""], - _boolType => (nullableOrBoxed ? ["NSNumber", " *"] : ["BOOL", ""]), - _integerType => (nullableOrBoxed ? ["NSNumber", " *"] : ["NSInteger", ""]), - _doubleType => (nullableOrBoxed ? ["NSNumber", " *"] : ["double", ""]), + _boolType => nullableOrBoxed ? ["NSNumber", " *"] : ["BOOL", ""], + _integerType => nullableOrBoxed ? ["NSNumber", " *"] : ["NSInteger", ""], + _doubleType => nullableOrBoxed ? ["NSNumber", " *"] : ["double", ""], _stringType => ["NSString", " *"], arrayType => { const itemType = arrayType.items; @@ -361,6 +370,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { if (isAnyOrNull(itemType)) { return ["NSArray", " *"]; } + return [["NSArray<", itemTypeName, ">"], " *"]; }, classType => [this.nameForNamedType(classType), " *"], @@ -369,11 +379,11 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { unionType => { const nullable = nullableFromUnion(unionType); return nullable !== null ? this.objcType(nullable, true) : ["id", ""]; - } + }, ); } - private jsonType(t: Type): [Sourcelike, string] { + private jsonType (t: Type): [Sourcelike, string] { return matchType<[Sourcelike, string]>( t, _anyType => ["id", ""], @@ -390,11 +400,11 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { unionType => { const nullable = nullableFromUnion(unionType); return nullable !== null ? this.jsonType(nullable) : ["id", ""]; - } + }, ); } - protected fromDynamicExpression(t: Type, ...dynamic: Sourcelike[]): Sourcelike { + protected fromDynamicExpression (t: Type, ...dynamic: Sourcelike[]): Sourcelike { return matchType( t, _anyType => dynamic, @@ -410,17 +420,17 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { unionType => { const nullable = nullableFromUnion(unionType); return nullable !== null ? this.fromDynamicExpression(nullable, dynamic) : dynamic; - } + }, ); } - protected toDynamicExpression(t: Type, typed: Sourcelike): Sourcelike { + protected toDynamicExpression (t: Type, typed: Sourcelike): Sourcelike { return matchType( t, _anyType => ["NSNullify(", typed, ")"], _nullType => ["NSNullify(", typed, ")"], // Sadly, KVC - _boolType => [typed, ` ? @YES : @NO`], + _boolType => [typed, " ? @YES : @NO"], _integerType => typed, _doubleType => typed, _stringType => typed, @@ -429,6 +439,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { // TODO check each value type return typed; } + return ["map(", typed, ", λ(id x, ", this.toDynamicExpression(arrayType.items, "x"), "))"]; }, _classType => ["[", typed, " JSONDictionary]"], @@ -437,6 +448,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { // TODO check each value type return typed; } + return ["map(", typed, ", λ(id x, ", this.toDynamicExpression(mapType.values, "x"), "))"]; }, _enumType => ["[", typed, " value]"], @@ -452,11 +464,11 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { // TODO support unions return typed; } - } + }, ); } - protected implicitlyConvertsFromJSON(t: Type): boolean { + protected implicitlyConvertsFromJSON (t: Type): boolean { if (t instanceof ClassType) { return false; } else if (t instanceof EnumType) { @@ -480,11 +492,11 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { } } - protected implicitlyConvertsToJSON(t: Type): boolean { + protected implicitlyConvertsToJSON (t: Type): boolean { return this.implicitlyConvertsFromJSON(t) && "bool" !== t.kind; } - protected emitPropertyAssignment(propertyName: Name, jsonName: string, propertyType: Type) { + protected emitPropertyAssignment (propertyName: Name, jsonName: string, propertyType: Type) { const name = ["_", propertyName]; matchType( propertyType, @@ -504,7 +516,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { name, ", ", ["λ(id x, ", this.fromDynamicExpression(itemType, "x"), ")"], - ");" + ");", ); }, enumType => this.emitLine(name, " = ", this.fromDynamicExpression(enumType, ["(id)", name]), ";"), @@ -516,43 +528,43 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { // TODO This is a union, but for now we just leave it dynamic this.emitLine(name, " = ", this.fromDynamicExpression(unionType, name), ";"); } - } + }, ); } - protected emitPrivateClassInterface(_: ClassType, name: Name): void { + protected emitPrivateClassInterface (_: ClassType, name: Name): void { this.emitLine("@interface ", name, " (JSONConversion)"); this.emitLine("+ (instancetype)fromJSONDictionary:(NSDictionary *)dict;"); this.emitLine("- (NSDictionary *)JSONDictionary;"); this.emitLine("@end"); } - protected pointerAwareTypeName(t: Type | [Sourcelike, string]): Sourcelike { + protected pointerAwareTypeName (t: Type | [Sourcelike, string]): Sourcelike { const name = t instanceof Type ? this.objcType(t) : t; const isPointer = name[1] !== ""; return isPointer ? name : [name, " "]; } - private emitNonClassTopLevelTypedef(t: Type, name: Name): void { + private emitNonClassTopLevelTypedef (t: Type, name: Name): void { let nonPointerTypeName = this.objcType(t)[0]; this.emitLine("typedef ", nonPointerTypeName, " ", name, ";"); } - private topLevelFromDataPrototype(name: Name): Sourcelike { + private topLevelFromDataPrototype (name: Name): Sourcelike { return [name, " *_Nullable ", name, "FromData(NSData *data, NSError **error)"]; } - private topLevelFromJSONPrototype(name: Name): Sourcelike { + private topLevelFromJSONPrototype (name: Name): Sourcelike { return [name, " *_Nullable ", name, "FromJSON(NSString *json, NSStringEncoding encoding, NSError **error)"]; } - private topLevelToDataPrototype(name: Name, pad = false): Sourcelike { + private topLevelToDataPrototype (name: Name, pad = false): Sourcelike { const parameter = this.variableNameForTopLevel(name); const padding = pad ? repeatString(" ", this.sourcelikeToString(name).length - "NSData".length) : ""; return ["NSData", padding, " *_Nullable ", name, "ToData(", name, " *", parameter, ", NSError **error)"]; } - private topLevelToJSONPrototype(name: Name, pad = false): Sourcelike { + private topLevelToJSONPrototype (name: Name, pad = false): Sourcelike { const parameter = this.variableNameForTopLevel(name); const padding = pad ? repeatString(" ", this.sourcelikeToString(name).length - "NSString".length) : ""; return [ @@ -564,31 +576,31 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { name, " *", parameter, - ", NSStringEncoding encoding, NSError **error)" + ", NSStringEncoding encoding, NSError **error)", ]; } - private emitTopLevelFunctionDeclarations(_: Type, name: Name): void { + private emitTopLevelFunctionDeclarations (_: Type, name: Name): void { this.emitLine(this.topLevelFromDataPrototype(name), ";"); this.emitLine(this.topLevelFromJSONPrototype(name), ";"); this.emitLine(this.topLevelToDataPrototype(name, true), ";"); this.emitLine(this.topLevelToJSONPrototype(name, true), ";"); } - private emitTryCatchAsError(inTry: () => void, inCatch: () => void) { + private emitTryCatchAsError (inTry: () => void, inCatch: () => void) { this.emitLine("@try {"); this.indent(inTry); this.emitLine("} @catch (NSException *exception) {"); this.indent(() => { this.emitLine( - `*error = [NSError errorWithDomain:@"JSONSerialization" code:-1 userInfo:@{ @"exception": exception }];` + "*error = [NSError errorWithDomain:@\"JSONSerialization\" code:-1 userInfo:@{ @\"exception\": exception }];", ); inCatch(); }); this.emitLine("}"); } - private emitTopLevelFunctions(t: Type, name: Name): void { + private emitTopLevelFunctions (t: Type, name: Name): void { const parameter = this.variableNameForTopLevel(name); this.ensureBlankLine(); @@ -596,11 +608,11 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { this.emitTryCatchAsError( () => { this.emitLine( - "id json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:error];" + "id json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:error];", ); this.emitLine("return *error ? nil : ", this.fromDynamicExpression(t, "json"), ";"); }, - () => this.emitLine("return nil;") + () => this.emitLine("return nil;"), ); }); @@ -615,11 +627,11 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { () => { this.emitLine("id json = ", this.toDynamicExpression(t, parameter), ";"); this.emitLine( - "NSData *data = [NSJSONSerialization dataWithJSONObject:json options:kNilOptions error:error];" + "NSData *data = [NSJSONSerialization dataWithJSONObject:json options:kNilOptions error:error];", ); this.emitLine("return *error ? nil : data;"); }, - () => this.emitLine("return nil;") + () => this.emitLine("return nil;"), ); }); @@ -630,7 +642,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { }); } - private emitClassInterface(t: ClassType, className: Name): void { + private emitClassInterface (t: ClassType, className: Name): void { const isTopLevel = mapContains(this.topLevels, t); this.emitDescription(this.descriptionForType(t)); @@ -644,10 +656,11 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { if (property.type.isNullable) { attributes.push("nullable"); } + attributes.push(this.memoryAttribute(property.type, property.type.isNullable)); return [ ["@property ", ["(", attributes.join(", "), ")"], " "], - [this.pointerAwareTypeName(property.type), name, ";"] + [this.pointerAwareTypeName(property.type), name, ";"], ]; }); @@ -655,18 +668,19 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { if (t.getProperties().size > 0) this.ensureBlankLine(); this.emitLine( - "+ (_Nullable instancetype)fromJSON:(NSString *)json encoding:(NSStringEncoding)encoding error:(NSError *_Nullable *)error;" + "+ (_Nullable instancetype)fromJSON:(NSString *)json encoding:(NSStringEncoding)encoding error:(NSError *_Nullable *)error;", ); this.emitLine("+ (_Nullable instancetype)fromData:(NSData *)data error:(NSError *_Nullable *)error;"); this.emitLine( - "- (NSString *_Nullable)toJSON:(NSStringEncoding)encoding error:(NSError *_Nullable *)error;" + "- (NSString *_Nullable)toJSON:(NSStringEncoding)encoding error:(NSError *_Nullable *)error;", ); this.emitLine("- (NSData *_Nullable)toData:(NSError *_Nullable *)error;"); } + this.emitLine("@end"); } - protected hasIrregularProperties(t: ClassType) { + protected hasIrregularProperties (t: ClassType) { let irregular = false; this.forEachClassProperty(t, "none", (name, jsonName) => { irregular = irregular || stringEscape(jsonName) !== this.sourcelikeToString(name); @@ -674,7 +688,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { return irregular; } - protected hasUnsafeProperties(t: ClassType) { + protected hasUnsafeProperties (t: ClassType) { let unsafe = false; this.forEachClassProperty(t, "none", (_, __, property) => { unsafe = unsafe || !this.implicitlyConvertsToJSON(property.type); @@ -683,7 +697,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { } // TODO Implement NSCopying - private emitClassImplementation(t: ClassType, className: Name): void { + private emitClassImplementation (t: ClassType, className: Name): void { const isTopLevel = mapContains(this.topLevels, t); const hasIrregularProperties = this.hasIrregularProperties(t); @@ -696,7 +710,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { this.emitLine("return properties = properties ? properties : @{"); this.indent(() => { this.forEachClassProperty(t, "none", (name, jsonName) => - this.emitLine(`@"${stringEscape(jsonName)}": @"`, name, `",`) + this.emitLine(`@"${stringEscape(jsonName)}": @"`, name, "\","), ); }); this.emitLine("};"); @@ -708,14 +722,14 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { "+ (_Nullable instancetype)fromData:(NSData *)data error:(NSError *_Nullable *)error", () => { this.emitLine("return ", className, "FromData(data, error);"); - } + }, ); this.ensureBlankLine(); this.emitMethod( "+ (_Nullable instancetype)fromJSON:(NSString *)json encoding:(NSStringEncoding)encoding error:(NSError *_Nullable *)error", () => { this.emitLine("return ", className, "FromJSON(json, encoding, error);"); - } + }, ); this.ensureBlankLine(); } @@ -763,17 +777,17 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { this.emitLine( "id dict = [[self dictionaryWithValuesForKeys:", className, - ".properties.allValues] mutableCopy];" + ".properties.allValues] mutableCopy];", ); this.ensureBlankLine(); if (hasIrregularProperties) { this.emitExtraComments("Rewrite property names that differ in JSON"); this.emitBlock(["for (id jsonName in ", className, ".properties)"], () => { - this.emitLine(`id propertyName = `, className, `.properties[jsonName];`); - this.emitBlock(`if (![jsonName isEqualToString:propertyName])`, () => { - this.emitLine(`dict[jsonName] = dict[propertyName];`); - this.emitLine(`[dict removeObjectForKey:propertyName];`); + this.emitLine("id propertyName = ", className, ".properties[jsonName];"); + this.emitBlock("if (![jsonName isEqualToString:propertyName])", () => { + this.emitLine("dict[jsonName] = dict[propertyName];"); + this.emitLine("[dict removeObjectForKey:propertyName];"); }); }); } @@ -787,7 +801,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { if (!this.implicitlyConvertsToJSON(property.type)) { const key = stringEscape(jsonKey); const name = ["_", propertyName]; - this.emitLine('@"', key, '": ', this.toDynamicExpression(property.type, name), ","); + this.emitLine("@\"", key, "\": ", this.toDynamicExpression(property.type, name), ","); } }); }); @@ -800,15 +814,15 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { if (isTopLevel) { this.ensureBlankLine(); - this.emitMethod(`- (NSData *_Nullable)toData:(NSError *_Nullable *)error`, () => { + this.emitMethod("- (NSData *_Nullable)toData:(NSError *_Nullable *)error", () => { this.emitLine("return ", className, "ToData(self, error);"); }); this.ensureBlankLine(); this.emitMethod( - `- (NSString *_Nullable)toJSON:(NSStringEncoding)encoding error:(NSError *_Nullable *)error`, + "- (NSString *_Nullable)toJSON:(NSStringEncoding)encoding error:(NSError *_Nullable *)error", () => { this.emitLine("return ", className, "ToJSON(self, encoding, error);"); - } + }, ); } } @@ -816,13 +830,13 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { this.emitLine("@end"); } - protected emitMark(label: string) { + protected emitMark (label: string) { this.ensureBlankLine(); this.emitLine(`#pragma mark - ${label}`); this.ensureBlankLine(); } - protected variableNameForTopLevel(name: Name): Sourcelike { + protected variableNameForTopLevel (name: Name): Sourcelike { const camelCaseName = modifySource(serialized => { // 1. remove class prefix serialized = serialized.slice(this._classPrefix.length); @@ -832,7 +846,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { return camelCaseName; } - private emitPseudoEnumInterface(enumType: EnumType, enumName: Name) { + private emitPseudoEnumInterface (enumType: EnumType, enumName: Name) { this.emitDescription(this.descriptionForType(enumType)); this.emitLine("@interface ", enumName, " : NSObject"); @@ -844,7 +858,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { this.emitLine("@end"); } - private emitPseudoEnumImplementation(enumType: EnumType, enumName: Name) { + private emitPseudoEnumImplementation (enumType: EnumType, enumName: Name) { this.emitLine("@implementation ", enumName); const instances = [enumName, ".", staticEnumValuesIdentifier]; @@ -857,11 +871,11 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { staticEnumValuesIdentifier, " ? ", staticEnumValuesIdentifier, - " : @{" + " : @{", ); this.indent(() => { this.forEachEnumCase(enumType, "none", (_, jsonValue) => { - const value = ['@"', stringEscape(jsonValue), '"']; + const value = ["@\"", stringEscape(jsonValue), "\""]; this.emitLine(value, ": [[", enumName, " alloc] initWithValue:", value, "],"); }); }); @@ -877,15 +891,15 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { name, " { return ", instances, - '[@"', + "[@\"", stringEscape(jsonValue), - '"]; }' + "\"]; }", ); }); this.ensureBlankLine(); this.emitMethod("+ (instancetype _Nullable)withValue:(NSString *)value", () => - this.emitLine("return ", instances, "[value];") + this.emitLine("return ", instances, "[value];"), ); this.ensureBlankLine(); @@ -899,13 +913,14 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { this.emitLine("@end"); } - protected emitSourceStructure(proposedFilename: string): void { + protected emitSourceStructure (proposedFilename: string): void { const fileMode = proposedFilename !== "stdout"; if (!fileMode) { // We don't have a filename, so we use a top-level name const firstTopLevel = defined(mapFirst(this.topLevels)); proposedFilename = this.sourcelikeToString(this.nameForNamedType(firstTopLevel)) + ".m"; } + const [filename, extension] = splitExtension(proposedFilename); if (this._options.features.interface) { @@ -927,13 +942,13 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { " *", this.variableNameForTopLevel(topLevelName), " = ", - fromJsonExpression + fromJsonExpression, ); }); } this.ensureBlankLine(); - this.emitLine(`#import `); + this.emitLine("#import "); this.ensureBlankLine(); // Emit @class declarations for top-level array+maps and classes @@ -941,7 +956,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { "none", (_: ClassType, className: Name) => this.emitLine("@class ", className, ";"), (_, enumName) => this.emitLine("@class ", enumName, ";"), - () => null + () => null, ); this.ensureBlankLine(); @@ -958,7 +973,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { this.forEachTopLevel( "leading-and-interposing", (t, n) => this.emitNonClassTopLevelTypedef(t, n), - t => !(t instanceof ClassType) + t => !(t instanceof ClassType), ); const hasTopLevelNonClassTypes = iterableSome(this.topLevels, ([_, t]) => !(t instanceof ClassType)); @@ -970,7 +985,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { (t, n) => this.emitTopLevelFunctionDeclarations(t, n), // Objective-C developers get freaked out by C functions, so we don't // declare them for top-level object types (we always need them for non-object types) - t => this._options.marshallingFunctions || !(t instanceof ClassType) + t => this._options.marshallingFunctions || !(t instanceof ClassType), ); } @@ -979,7 +994,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { "leading-and-interposing", (c: ClassType, className: Name) => this.emitClassInterface(c, className), () => null, - () => null + () => null, ); this.ensureBlankLine(); @@ -996,11 +1011,11 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { if (!this._options.justTypes) { this.ensureBlankLine(); this.emitExtraComments("Shorthand for simple blocks"); - this.emitLine(`#define λ(decl, expr) (^(decl) { return (expr); })`); + this.emitLine("#define λ(decl, expr) (^(decl) { return (expr); })"); this.ensureBlankLine(); this.emitExtraComments("nil → NSNull conversion for JSON dictionaries"); this.emitBlock("static id NSNullify(id _Nullable x)", () => - this.emitLine("return (x == nil || x == NSNull.null) ? NSNull.null : x;") + this.emitLine("return (x == nil || x == NSNull.null) ? NSNull.null : x;"), ); this.ensureBlankLine(); this.emitLine("NS_ASSUME_NONNULL_BEGIN"); @@ -1016,7 +1031,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { "leading-and-interposing", (c: ClassType, className: Name) => this.emitPrivateClassInterface(c, className), () => null, - () => null + () => null, ); if (this.haveEnums) { @@ -1024,10 +1039,11 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { this.ensureBlankLine(); this.emitExtraComments( "These enum-like reference types are needed so that enum", - "values can be contained by NSArray and NSDictionary." + "values can be contained by NSArray and NSDictionary.", ); this.ensureBlankLine(); } + this.forEachEnum("leading-and-interposing", (t, n) => this.emitPseudoEnumImplementation(t, n)); } @@ -1043,7 +1059,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { "leading-and-interposing", (c: ClassType, className: Name) => this.emitClassImplementation(c, className), () => null, - () => null + () => null, ); if (!this._options.justTypes) { @@ -1054,19 +1070,21 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { this.finishFile(); } } - private get needsMap(): boolean { + + private get needsMap (): boolean { // TODO this isn't complete (needs union support, for example) - function needsMap(t: Type): boolean { + function needsMap (t: Type): boolean { return ( t instanceof MapType || t instanceof ArrayType || - (t instanceof ClassType && mapSome(t.getProperties(), p => needsMap(p.type))) + t instanceof ClassType && mapSome(t.getProperties(), p => needsMap(p.type)) ); } + return iterableSome(this.typeGraph.allTypesUnordered(), needsMap); } - protected emitMapFunction() { + protected emitMapFunction () { if (this.needsMap) { this.emitMultiline(`static id map(id collection, id (^f)(id value)) { id result = nil; diff --git a/packages/quicktype-core/src/language/Php.ts b/packages/quicktype-core/src/language/Php.ts index 670b09cc1..87c9e2b1c 100644 --- a/packages/quicktype-core/src/language/Php.ts +++ b/packages/quicktype-core/src/language/Php.ts @@ -1,9 +1,13 @@ import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { DependencyName, funPrefixNamer, Name, Namer } from "../Naming"; -import { RenderContext } from "../Renderer"; -import { BooleanOption, getOptionValues, Option, OptionValues } from "../RendererOptions"; -import { maybeAnnotated, Sourcelike } from "../Source"; +import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { ConvenienceRenderer } from "../ConvenienceRenderer"; +import { type Name, type Namer } from "../Naming"; +import { DependencyName, funPrefixNamer } from "../Naming"; +import { type RenderContext } from "../Renderer"; +import { type Option, type OptionValues } from "../RendererOptions"; +import { BooleanOption, getOptionValues } from "../RendererOptions"; +import { type Sourcelike } from "../Source"; +import { maybeAnnotated } from "../Source"; import { acronymOption, acronymStyle, AcronymStyleOptions } from "../support/Acronyms"; import { allLowerWordStyle, @@ -17,13 +21,13 @@ import { splitIntoWords, standardUnicodeHexEscape, utf16ConcatMap, - utf16LegalizeCharacters + utf16LegalizeCharacters, } from "../support/Strings"; import { defined } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; -import { ClassProperty, ClassType, EnumType, Type, UnionType } from "../Type"; +import { type ClassProperty, type ClassType, type EnumType, type Type, type UnionType } from "../Type"; import { directlyReachableSingleNamedType, matchType, nullableFromUnion } from "../TypeUtils"; -import { StringTypeMapping, TransformedStringTypeKind, PrimitiveStringTypeKind } from ".."; +import { type StringTypeMapping, type TransformedStringTypeKind, type PrimitiveStringTypeKind } from ".."; import * as _ from "lodash"; export const phpOptions = { @@ -31,28 +35,28 @@ export const phpOptions = { fastGet: new BooleanOption("fast-get", "getter without validation", false), withSet: new BooleanOption("with-set", "Create Setter", false), withClosing: new BooleanOption("with-closing", "PHP Closing Tag", false), - acronymStyle: acronymOption(AcronymStyleOptions.Pascal) + acronymStyle: acronymOption(AcronymStyleOptions.Pascal), }; export class PhpTargetLanguage extends TargetLanguage { - constructor() { + constructor () { super("PHP", ["php"], "php"); } - protected getOptions(): Option[] { + protected getOptions (): Array> { return _.values(phpOptions); } - get supportsUnionsWithBothNumberTypes(): boolean { + get supportsUnionsWithBothNumberTypes (): boolean { return true; } - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): PhpRenderer { + protected makeRenderer (renderContext: RenderContext, untypedOptionValues: { [name: string]: any, }): PhpRenderer { const options = getOptionValues(phpOptions, untypedOptionValues); return new PhpRenderer(this, renderContext, options); } - get stringTypeMapping(): StringTypeMapping { + get stringTypeMapping (): StringTypeMapping { const mapping: Map = new Map(); mapping.set("date", "date"); // TODO is not implemented yet mapping.set("time", "time"); // TODO is not implemented yet @@ -64,22 +68,22 @@ export class PhpTargetLanguage extends TargetLanguage { export const stringEscape = utf16ConcatMap(escapeNonPrintableMapper(isAscii, standardUnicodeHexEscape)); -function isStartCharacter(codePoint: number): boolean { +function isStartCharacter (codePoint: number): boolean { if (codePoint === 0x5f) return true; // underscore return isAscii(codePoint) && isLetter(codePoint); } -function isPartCharacter(codePoint: number): boolean { - return isStartCharacter(codePoint) || (isAscii(codePoint) && isDigit(codePoint)); +function isPartCharacter (codePoint: number): boolean { + return isStartCharacter(codePoint) || isAscii(codePoint) && isDigit(codePoint); } const legalizeName = utf16LegalizeCharacters(isPartCharacter); -export function phpNameStyle( +export function phpNameStyle ( startWithUpper: boolean, upperUnderscore: boolean, original: string, - acronymsStyle: (s: string) => string = allUpperWordStyle + acronymsStyle: (s: string) => string = allUpperWordStyle, ): string { const words = splitIntoWords(original); return combineWords( @@ -90,97 +94,100 @@ export function phpNameStyle( upperUnderscore || startWithUpper ? allUpperWordStyle : allLowerWordStyle, acronymsStyle, upperUnderscore ? "_" : "", - isStartCharacter + isStartCharacter, ); } export interface FunctionNames { + readonly from: Name; readonly getter: Name; + readonly sample: Name; readonly setter: Name; - readonly validate: Name; - readonly from: Name; readonly to: Name; - readonly sample: Name; + readonly validate: Name; } export class PhpRenderer extends ConvenienceRenderer { private readonly _gettersAndSettersForPropertyName = new Map(); + private _haveEmittedLeadingComments = false; + protected readonly _converterClassname: string = "Converter"; + protected readonly _converterKeywords: string[] = []; - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - protected readonly _options: OptionValues + protected readonly _options: OptionValues, ) { super(targetLanguage, renderContext); } - protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties (_c: ClassType, _className: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected makeNamedTypeNamer(): Namer { + protected makeNamedTypeNamer (): Namer { return this.getNameStyling("typeNamingFunction"); } - protected namerForObjectProperty(): Namer { + protected namerForObjectProperty (): Namer { return this.getNameStyling("propertyNamingFunction"); } - protected makeUnionMemberNamer(): Namer { + protected makeUnionMemberNamer (): Namer { return this.getNameStyling("propertyNamingFunction"); } - protected makeEnumCaseNamer(): Namer { + protected makeEnumCaseNamer (): Namer { return this.getNameStyling("enumCaseNamingFunction"); } - protected unionNeedsName(u: UnionType): boolean { + protected unionNeedsName (u: UnionType): boolean { return nullableFromUnion(u) === null; } - protected namedTypeToNameForTopLevel(type: Type): Type | undefined { + protected namedTypeToNameForTopLevel (type: Type): Type | undefined { return directlyReachableSingleNamedType(type); } - protected makeNamesForPropertyGetterAndSetter( + protected makeNamesForPropertyGetterAndSetter ( _c: ClassType, _className: Name, _p: ClassProperty, _jsonName: string, - name: Name + name: Name, ): FunctionNames { const getterName = new DependencyName( this.getNameStyling("propertyNamingFunction"), name.order, - lookup => `get_${lookup(name)}` + lookup => `get_${lookup(name)}`, ); const setterName = new DependencyName( this.getNameStyling("propertyNamingFunction"), name.order, - lookup => `set_${lookup(name)}` + lookup => `set_${lookup(name)}`, ); const validateName = new DependencyName( this.getNameStyling("propertyNamingFunction"), name.order, - lookup => `validate_${lookup(name)}` + lookup => `validate_${lookup(name)}`, ); const fromName = new DependencyName( this.getNameStyling("propertyNamingFunction"), name.order, - lookup => `from_${lookup(name)}` + lookup => `from_${lookup(name)}`, ); const toName = new DependencyName( this.getNameStyling("propertyNamingFunction"), name.order, - lookup => `to_${lookup(name)}` + lookup => `to_${lookup(name)}`, ); const sampleName = new DependencyName( this.getNameStyling("propertyNamingFunction"), name.order, - lookup => `sample_${lookup(name)}` + lookup => `sample_${lookup(name)}`, ); return { getter: getterName, @@ -188,16 +195,16 @@ export class PhpRenderer extends ConvenienceRenderer { validate: validateName, from: fromName, to: toName, - sample: sampleName + sample: sampleName, }; } - protected makePropertyDependencyNames( + protected makePropertyDependencyNames ( c: ClassType, className: Name, p: ClassProperty, jsonName: string, - name: Name + name: Name, ): Name[] { const getterAndSetterNames = this.makeNamesForPropertyGetterAndSetter(c, className, p, jsonName, name); this._gettersAndSettersForPropertyName.set(name, getterAndSetterNames); @@ -207,26 +214,26 @@ export class PhpRenderer extends ConvenienceRenderer { getterAndSetterNames.validate, getterAndSetterNames.to, getterAndSetterNames.from, - getterAndSetterNames.sample + getterAndSetterNames.sample, ]; } - private getNameStyling(convention: string): Namer { - const styling: { [key: string]: Namer } = { + private getNameStyling (convention: string): Namer { + const styling: { [key: string]: Namer, } = { typeNamingFunction: funPrefixNamer("types", n => - phpNameStyle(true, false, n, acronymStyle(this._options.acronymStyle)) + phpNameStyle(true, false, n, acronymStyle(this._options.acronymStyle)), ), propertyNamingFunction: funPrefixNamer("properties", n => - phpNameStyle(false, false, n, acronymStyle(this._options.acronymStyle)) + phpNameStyle(false, false, n, acronymStyle(this._options.acronymStyle)), ), enumCaseNamingFunction: funPrefixNamer("enum-cases", n => - phpNameStyle(true, true, n, acronymStyle(this._options.acronymStyle)) - ) + phpNameStyle(true, true, n, acronymStyle(this._options.acronymStyle)), + ), }; return styling[convention]; } - protected startFile(_basename: Sourcelike): void { + protected startFile (_basename: Sourcelike): void { this.ensureBlankLine(); if (!this._haveEmittedLeadingComments && this.leadingComments !== undefined) { this.emitComments(this.leadingComments); @@ -235,30 +242,31 @@ export class PhpRenderer extends ConvenienceRenderer { } } - protected finishFile(): void { + protected finishFile (): void { // empty } - protected emitFileHeader(fileName: Sourcelike, _imports: string[]): void { + protected emitFileHeader (fileName: Sourcelike, _imports: string[]): void { this.startFile(fileName); this.emitLine("// This is a autogenerated file:", fileName); this.ensureBlankLine(); } - public emitDescriptionBlock(lines: Sourcelike[]): void { + public emitDescriptionBlock (lines: Sourcelike[]): void { this.emitCommentLines(lines, { lineStart: " * ", beforeComment: "/**", afterComment: " */" }); } - public emitBlock(line: Sourcelike, f: () => void): void { + public emitBlock (line: Sourcelike, f: () => void): void { this.emitLine(line, " {"); this.indent(f); this.emitLine("}"); } - protected phpType(_reference: boolean, t: Type, isOptional = false, prefix = "?", suffix = ""): Sourcelike { - function optionalize(s: Sourcelike) { + protected phpType (_reference: boolean, t: Type, isOptional = false, prefix = "?", suffix = ""): Sourcelike { + function optionalize (s: Sourcelike) { return [isOptional ? prefix : "", s, isOptional ? suffix : ""]; } + return matchType( t, _anyType => maybeAnnotated(isOptional, anyTypeIssueAnnotation, "Object"), @@ -278,23 +286,27 @@ export class PhpRenderer extends ConvenienceRenderer { }, transformedStringType => { if (transformedStringType.kind === "time") { - throw Error('transformedStringType.kind === "time"'); + throw Error("transformedStringType.kind === \"time\""); } + if (transformedStringType.kind === "date") { - throw Error('transformedStringType.kind === "date"'); + throw Error("transformedStringType.kind === \"date\""); } + if (transformedStringType.kind === "date-time") { return "DateTime"; } + if (transformedStringType.kind === "uuid") { - throw Error('transformedStringType.kind === "uuid"'); + throw Error("transformedStringType.kind === \"uuid\""); } + return "string"; - } + }, ); } - protected phpDocConvertType(className: Name, t: Type): Sourcelike { + protected phpDocConvertType (className: Name, t: Type): Sourcelike { return matchType( t, _anyType => "any", @@ -312,18 +324,20 @@ export class PhpRenderer extends ConvenienceRenderer { if (nullable !== null) { return [this.phpDocConvertType(className, nullable), "|null"]; } + throw Error("union are not supported"); }, transformedStringType => { if (transformedStringType.kind === "date-time") { return "DateTime"; } - throw Error('transformedStringType.kind === "unknown"'); - } + + throw Error("transformedStringType.kind === \"unknown\""); + }, ); } - protected phpConvertType(className: Name, t: Type): Sourcelike { + protected phpConvertType (className: Name, t: Type): Sourcelike { return matchType( t, _anyType => "any", @@ -341,19 +355,21 @@ export class PhpRenderer extends ConvenienceRenderer { if (nullable !== null) { return ["?", this.phpConvertType(className, nullable)]; } + throw Error("union are not supported"); }, transformedStringType => { if (transformedStringType.kind === "date-time") { return "string"; } - throw Error('transformedStringType.kind === "unknown"'); - } + + throw Error("transformedStringType.kind === \"unknown\""); + }, ); } - protected phpToObjConvert(className: Name, t: Type, lhs: Sourcelike[], args: Sourcelike[]) { - return matchType( + protected phpToObjConvert (className: Name, t: Type, lhs: Sourcelike[], args: Sourcelike[]) { + matchType( t, _anyType => this.emitLine(...lhs, ...args, "; /*any*/"), _nullType => this.emitLine(...lhs, ...args, "; /*null*/"), @@ -391,6 +407,7 @@ export class PhpRenderer extends ConvenienceRenderer { this.emitLine("}"); return; } + throw Error("union are not supported"); }, transformedStringType => { @@ -398,22 +415,23 @@ export class PhpRenderer extends ConvenienceRenderer { this.emitLine(...lhs, ...args, "->format(DateTimeInterface::ISO8601);"); return; } - throw Error('transformedStringType.kind === "unknown"'); - } + + throw Error("transformedStringType.kind === \"unknown\""); + }, ); } - private transformDateTime(className: Name, attrName: Sourcelike, scopeAttrName: Sourcelike[]) { + private transformDateTime (className: Name, attrName: Sourcelike, scopeAttrName: Sourcelike[]) { this.emitBlock(["if (!is_a(", scopeAttrName, ", 'DateTime'))"], () => - this.emitLine("throw new Exception('Attribute Error:", className, "::", attrName, "');") + this.emitLine("throw new Exception('Attribute Error:", className, "::", attrName, "');"), ); // if (lhs !== undefined) { // this.emitLine(lhs, "$tmp;"); // } } - protected phpFromObjConvert(className: Name, t: Type, lhs: Sourcelike[], args: Sourcelike[]) { - return matchType( + protected phpFromObjConvert (className: Name, t: Type, lhs: Sourcelike[], args: Sourcelike[]) { + matchType( t, _anyType => this.emitLine(...lhs, ...args, "; /*any*/"), _nullType => this.emitLine(...lhs, ...args, "; /*null*/"), @@ -452,6 +470,7 @@ export class PhpRenderer extends ConvenienceRenderer { this.emitLine("}"); return; } + throw Error("union are not supported"); }, transformedStringType => { @@ -461,20 +480,21 @@ export class PhpRenderer extends ConvenienceRenderer { this.emitLine("return $tmp;"); return; } - throw Error('transformedStringType.kind === "unknown"'); - } + + throw Error("transformedStringType.kind === \"unknown\""); + }, ); } - protected phpSampleConvert( + protected phpSampleConvert ( className: Name, t: Type, lhs: Sourcelike[], args: Sourcelike[], idx: number, - suffix: Sourcelike + suffix: Sourcelike, ) { - return matchType( + matchType( t, _anyType => this.emitLine( @@ -490,7 +510,7 @@ export class PhpRenderer extends ConvenienceRenderer { "" + idx, ":", args, - "*/" + "*/", ), _nullType => this.emitLine(...lhs, "null", suffix, " /*", "" + idx, ":", args, "*/"), _boolType => this.emitLine(...lhs, "true", suffix, " /*", "" + idx, ":", args, "*/"), @@ -510,7 +530,7 @@ export class PhpRenderer extends ConvenienceRenderer { "" + idx, ":", args, - "*/" + "*/", ), arrayType => { this.emitLine(...lhs, " array("); @@ -529,7 +549,7 @@ export class PhpRenderer extends ConvenienceRenderer { "" + idx, ":", args, - "*/" + "*/", ), mapType => { this.emitBlock(["function sample(): stdClass"], () => { @@ -546,33 +566,36 @@ export class PhpRenderer extends ConvenienceRenderer { this.phpSampleConvert(className, nullable, lhs, args, idx, suffix); return; } + throw Error("union are not supported:" + unionType); }, transformedStringType => { if (transformedStringType.kind === "date-time") { - const x = _.pad("" + (1 + (idx % 31)), 2, "0"); + const x = _.pad("" + (1 + idx % 31), 2, "0"); this.emitLine( ...lhs, "DateTime::createFromFormat(DateTimeInterface::ISO8601, '", `2020-12-${x}T12:${x}:${x}+00:00`, "')", - suffix + suffix, ); // this.emitLine("return sample();"); return; } - throw Error('transformedStringType.kind === "unknown"'); - } + + throw Error("transformedStringType.kind === \"unknown\""); + }, ); } - private phpValidate(className: Name, t: Type, attrName: Sourcelike, scopeAttrName: string) { + private phpValidate (className: Name, t: Type, attrName: Sourcelike, scopeAttrName: string) { const is = (isfn: string, myT: Name = className) => { this.emitBlock(["if (!", isfn, "(", scopeAttrName, "))"], () => - this.emitLine('throw new Exception("Attribute Error:', myT, "::", attrName, '");') + this.emitLine("throw new Exception(\"Attribute Error:", myT, "::", attrName, "\");"), ); }; - return matchType( + + matchType( t, _anyType => is("defined"), _nullType => is("is_null"), @@ -609,6 +632,7 @@ export class PhpRenderer extends ConvenienceRenderer { }); return; } + throw Error("not implemented"); }, transformedStringType => { @@ -616,17 +640,19 @@ export class PhpRenderer extends ConvenienceRenderer { this.transformDateTime(className, attrName, [scopeAttrName]); return; } + throw Error(`transformedStringType.kind === ${transformedStringType.kind}`); - } + }, ); } - protected emitFromMethod(names: FunctionNames, p: ClassProperty, className: Name, _name: Name, desc?: string[]) { + protected emitFromMethod (names: FunctionNames, p: ClassProperty, className: Name, _name: Name, desc?: string[]) { this.emitLine("/**"); if (desc !== undefined) { this.emitLine(" * ", desc); this.emitLine(" *"); } + // this.emitLine(" * @param ", this.phpType(false, p.type, false, "", "|null")); this.emitLine(" * @param ", this.phpConvertType(className, p.type), " $value"); this.emitLine(" * @throws Exception"); @@ -639,20 +665,22 @@ export class PhpRenderer extends ConvenienceRenderer { "(", this.phpConvertType(className, p.type), " $value): ", - this.phpType(false, p.type) + this.phpType(false, p.type), ], () => { - this.phpFromObjConvert(className, p.type, ["return "], [`$value`]); + this.phpFromObjConvert(className, p.type, ["return "], ["$value"]); // this.emitLine("return $ret;"); - } + }, ); } - protected emitToMethod(names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc?: string[]) { + + protected emitToMethod (names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc?: string[]) { this.emitLine("/**"); if (desc !== undefined) { this.emitLine(" * ", desc); this.emitLine(" *"); } + this.emitLine(" * @throws Exception"); this.emitLine(" * @return ", this.phpConvertType(className, p.type)); this.emitLine(" */"); @@ -663,12 +691,14 @@ export class PhpRenderer extends ConvenienceRenderer { this.emitLine("throw new Exception('never get to this ", className, "::", name, "');"); }); } - protected emitValidateMethod(names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc?: string[]) { + + protected emitValidateMethod (names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc?: string[]) { this.emitLine("/**"); if (desc !== undefined) { this.emitLine(" * ", desc); this.emitLine(" *"); } + this.emitLine(" * @param ", this.phpType(false, p.type, false, "", "|null")); this.emitLine(" * @return bool"); this.emitLine(" * @throws Exception"); @@ -676,21 +706,24 @@ export class PhpRenderer extends ConvenienceRenderer { this.emitBlock( ["public static function ", names.validate, "(", this.phpType(false, p.type), " $value): bool"], () => { - this.phpValidate(className, p.type, name, `$value`); + this.phpValidate(className, p.type, name, "$value"); this.emitLine("return true;"); - } + }, ); } - protected emitGetMethod(names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc?: string[]) { + + protected emitGetMethod (names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc?: string[]) { if (this._options.withGet) { this.emitLine("/**"); if (desc !== undefined) { this.emitLine(" * ", desc); this.emitLine(" *"); } + if (!this._options.fastGet) { - this.emitLine(` * @throws Exception`); + this.emitLine(" * @throws Exception"); } + const rendered = this.phpType(false, p.type); this.emitLine(" * @return ", rendered); this.emitLine(" */"); @@ -706,7 +739,7 @@ export class PhpRenderer extends ConvenienceRenderer { className, "::", name, - "');" + "');", ); } else { this.emitLine("return $this->", name, ";"); @@ -714,15 +747,17 @@ export class PhpRenderer extends ConvenienceRenderer { }); } } - protected emitSetMethod(names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc?: string[]) { + + protected emitSetMethod (names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc?: string[]) { if (this._options.withSet) { this.emitLine("/**"); if (desc !== undefined) { this.emitLine(" * ", desc); this.emitLine(" *"); } + this.emitLine(" * @param ", this.phpType(false, p.type, false, "", "|null")); - this.emitLine(` * @throws Exception`); + this.emitLine(" * @throws Exception"); this.emitLine(" */"); this.emitBlock(["public function ", names.setter, "(", this.phpType(false, p.type), " $value)"], () => { this.emitBlock(["if (", className, "::", names.validate, "($value)) "], () => { @@ -731,13 +766,14 @@ export class PhpRenderer extends ConvenienceRenderer { }); } } - protected emitSampleMethod( + + protected emitSampleMethod ( names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc: string[] | undefined, - idx: number + idx: number, ) { if (this._options.withGet) { this.emitLine("/**"); @@ -745,6 +781,7 @@ export class PhpRenderer extends ConvenienceRenderer { this.emitLine(" * ", desc); this.emitLine(" *"); } + const rendered = this.phpType(false, p.type); this.emitLine(" * @return ", rendered); this.emitLine(" */"); @@ -754,7 +791,7 @@ export class PhpRenderer extends ConvenienceRenderer { } } - protected emitClassDefinition(c: ClassType, className: Name): void { + protected emitClassDefinition (c: ClassType, className: Name): void { this.emitFileHeader(className, []); this.emitBlock(["class ", className], () => { @@ -767,7 +804,7 @@ export class PhpRenderer extends ConvenienceRenderer { "; // json:", jsonName, " ", - p.type.isNullable ? "Optional" : "Required" + p.type.isNullable ? "Optional" : "Required", ); }); @@ -807,7 +844,7 @@ export class PhpRenderer extends ConvenienceRenderer { this.ensureBlankLine(); this.emitBlock( - ["/**\n", ` * @throws Exception\n`, ` * @return bool\n`, " */\n", "public function validate(): bool"], + ["/**\n", " * @throws Exception\n", " * @return bool\n", " */\n", "public function validate(): bool"], () => { let lines: Sourcelike[][] = []; let p = "return "; @@ -819,17 +856,17 @@ export class PhpRenderer extends ConvenienceRenderer { lines.forEach((line, jdx) => { this.emitLine(...line, lines.length === jdx + 1 ? ";" : ""); }); - } + }, ); this.ensureBlankLine(); this.emitBlock( [ "/**\n", - ` * @return stdClass\n`, - ` * @throws Exception\n`, + " * @return stdClass\n", + " * @throws Exception\n", " */\n", - "public function to(): stdClass " + "public function to(): stdClass ", ], () => { this.emitLine("$out = new stdClass();"); @@ -838,21 +875,21 @@ export class PhpRenderer extends ConvenienceRenderer { this.emitLine("$out->{'", jsonName, "'} = $this->", names.to, "();"); }); this.emitLine("return $out;"); - } + }, ); this.ensureBlankLine(); this.emitBlock( [ "/**\n", - ` * @param stdClass $obj\n`, - ` * @return `, + " * @param stdClass $obj\n", + " * @return ", className, - `\n`, - ` * @throws Exception\n`, + "\n", + " * @throws Exception\n", " */\n", "public static function from(stdClass $obj): ", - className + className, ], () => { if (this._options.fastGet) { @@ -861,6 +898,7 @@ export class PhpRenderer extends ConvenienceRenderer { this.emitLine(className, "::", names.validate, "($this->", name, ", true);"); }); } + this.emitLine("return new ", className, "("); let comma = " "; this.forEachClassProperty(c, "none", (name, jsonName) => { @@ -869,7 +907,7 @@ export class PhpRenderer extends ConvenienceRenderer { comma = ","; }); this.emitLine(");"); - } + }, ); this.ensureBlankLine(); this.emitBlock( @@ -883,33 +921,33 @@ export class PhpRenderer extends ConvenienceRenderer { comma = ","; }); this.emitLine(");"); - } + }, ); }); this.finishFile(); } - protected emitUnionAttributes(_u: UnionType, _unionName: Name): void { + protected emitUnionAttributes (_u: UnionType, _unionName: Name): void { // empty } - protected emitUnionSerializer(_u: UnionType, _unionName: Name): void { + protected emitUnionSerializer (_u: UnionType, _unionName: Name): void { // empty } - protected emitUnionDefinition(_u: UnionType, _unionName: Name): void { + protected emitUnionDefinition (_u: UnionType, _unionName: Name): void { throw Error("emitUnionDefinition not implemented"); } - protected emitEnumSerializationAttributes(_e: EnumType) { + protected emitEnumSerializationAttributes (_e: EnumType) { // Empty } - protected emitEnumDeserializationAttributes(_e: EnumType) { + protected emitEnumDeserializationAttributes (_e: EnumType) { // Empty } - protected emitEnumDefinition(e: EnumType, enumName: Name): void { + protected emitEnumDefinition (e: EnumType, enumName: Name): void { this.emitFileHeader(enumName, []); this.emitDescription(this.descriptionForType(e)); const caseNames: Sourcelike[] = []; @@ -937,18 +975,18 @@ export class PhpRenderer extends ConvenienceRenderer { this.emitBlock( [ "/**\n", - ` * @param `, + " * @param ", enumName, - `\n`, - ` * @return `, + "\n", + " * @return ", enumSerdeType, - `\n`, - ` * @throws Exception\n`, + "\n", + " * @throws Exception\n", " */\n", "public static function to(", enumName, " $obj): ", - enumSerdeType + enumSerdeType, ], () => { this.emitLine("switch ($obj->enum) {"); @@ -962,13 +1000,13 @@ export class PhpRenderer extends ConvenienceRenderer { name, "->enum: return '", stringEscape(jsonName), - "';" + "';", ); }); }); this.emitLine("}"); this.emitLine("throw new Exception('the give value is not an enum-value.');"); - } + }, ); this.ensureBlankLine(); this.emitEnumDeserializationAttributes(e); @@ -976,14 +1014,14 @@ export class PhpRenderer extends ConvenienceRenderer { this.emitBlock( [ "/**\n", - ` * @param mixed\n`, - ` * @return `, + " * @param mixed\n", + " * @return ", enumName, "\n", - ` * @throws Exception\n`, + " * @throws Exception\n", " */\n", "public static function from($obj): ", - enumName + enumName, ], () => { this.emitLine("switch ($obj) {"); @@ -994,36 +1032,37 @@ export class PhpRenderer extends ConvenienceRenderer { }); }); this.emitLine("}"); - this.emitLine('throw new Exception("Cannot deserialize ', enumName, '");'); - } + this.emitLine("throw new Exception(\"Cannot deserialize ", enumName, "\");"); + }, ); this.ensureBlankLine(); this.emitBlock( - ["/**\n", ` * @return `, enumName, "\n", " */\n", "public static function sample(): ", enumName], + ["/**\n", " * @return ", enumName, "\n", " */\n", "public static function sample(): ", enumName], () => { const lines: Sourcelike[] = []; this.forEachEnumCase(e, "none", name => { lines.push([enumName, "::$", name]); }); this.emitLine("return ", lines[0], ";"); - } + }, ); }); this.emitLine(enumName, "::init();"); this.finishFile(); } - protected emitSourceStructure(givenFilename: string): void { + protected emitSourceStructure (givenFilename: string): void { this.emitLine(" this.emitClassDefinition(c, n), (e, n) => this.emitEnumDefinition(e, n), - (u, n) => this.emitUnionDefinition(u, n) + (u, n) => this.emitUnionDefinition(u, n), ); if (this._options.withClosing) { this.emitLine("?>"); } + super.finishFile(defined(givenFilename)); } } diff --git a/packages/quicktype-core/src/language/Pike.ts b/packages/quicktype-core/src/language/Pike.ts index d2d9541b7..0e9716278 100644 --- a/packages/quicktype-core/src/language/Pike.ts +++ b/packages/quicktype-core/src/language/Pike.ts @@ -1,10 +1,14 @@ -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { Name, Namer, funPrefixNamer } from "../Naming"; -import { Option } from "../RendererOptions"; -import { RenderContext } from "../Renderer"; -import { MultiWord, Sourcelike, multiWord, parenIfNeeded, singleWord } from "../Source"; +import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { ConvenienceRenderer } from "../ConvenienceRenderer"; +import { type Name, type Namer} from "../Naming"; +import { funPrefixNamer } from "../Naming"; +import { type Option } from "../RendererOptions"; +import { type RenderContext } from "../Renderer"; +import { type MultiWord, type Sourcelike} from "../Source"; +import { multiWord, parenIfNeeded, singleWord } from "../Source"; import { TargetLanguage } from "../TargetLanguage"; -import { Type, ClassType, EnumType, UnionType, ArrayType, MapType, PrimitiveType } from "../Type"; +import { type Type, type ClassType, type EnumType, type UnionType} from "../Type"; +import { ArrayType, MapType, PrimitiveType } from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; import { legalizeCharacters, isLetterOrUnderscoreOrDigit, stringEscape, makeNameStyle } from "../support/Strings"; @@ -62,7 +66,7 @@ const keywords = [ "sscanf", "switch", "typeof", - "global" + "global", ]; const legalizeName = legalizeCharacters(isLetterOrUnderscoreOrDigit); @@ -71,20 +75,21 @@ const namingFunction = funPrefixNamer("genericNamer", makeNameStyle("underscore" const namedTypeNamingFunction = funPrefixNamer("typeNamer", makeNameStyle("pascal", legalizeName)); export class PikeTargetLanguage extends TargetLanguage { - constructor() { + constructor () { super("Pike", ["pike", "pikelang"], "pmod"); } - protected getOptions(): Option[] { + + protected getOptions (): Array> { return []; } - protected makeRenderer(renderContext: RenderContext): PikeRenderer { + protected makeRenderer (renderContext: RenderContext): PikeRenderer { return new PikeRenderer(this, renderContext); } } export class PikeRenderer extends ConvenienceRenderer { - protected emitSourceStructure(): void { + protected emitSourceStructure (): void { this.emitInformationComment(); this.ensureBlankLine(); this.forEachTopLevel( @@ -95,56 +100,58 @@ export class PikeRenderer extends ConvenienceRenderer { this.emitTopLevelConverter(t, name); this.ensureBlankLine(); }, - t => this.namedTypeToNameForTopLevel(t) === undefined + t => this.namedTypeToNameForTopLevel(t) === undefined, ); this.ensureBlankLine(); this.forEachNamedType( "leading-and-interposing", (c: ClassType, className: Name) => this.emitClassDefinition(c, className), (e, n) => this.emitEnum(e, n), - (u, n) => this.emitUnion(u, n) + (u, n) => this.emitUnion(u, n), ); } - protected get enumCasesInGlobalNamespace(): boolean { + protected get enumCasesInGlobalNamespace (): boolean { return true; } - protected makeEnumCaseNamer(): Namer { + protected makeEnumCaseNamer (): Namer { return enumNamingFunction; } - protected makeNamedTypeNamer(): Namer { + + protected makeNamedTypeNamer (): Namer { return namedTypeNamingFunction; } - protected makeUnionMemberNamer(): Namer { + protected makeUnionMemberNamer (): Namer { return namingFunction; } - protected namerForObjectProperty(): Namer { + protected namerForObjectProperty (): Namer { return namingFunction; } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace (): string[] { return [...keywords]; } - protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties (_c: ClassType, _className: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { + protected forbiddenForEnumCases (_e: EnumType, _enumName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { + protected forbiddenForUnionMembers (_u: UnionType, _unionName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected sourceFor(t: Type): MultiWord { - if (["class", "object", "enum"].indexOf(t.kind) >= 0) { + protected sourceFor (t: Type): MultiWord { + if (["class", "object", "enum"].includes(t.kind)) { return singleWord(this.nameForNamedType(t)); } + return matchType( t, _anyType => singleWord("mixed"), @@ -170,11 +177,11 @@ export class PikeRenderer extends ConvenienceRenderer { } else { return singleWord(this.nameForNamedType(unionType)); } - } + }, ); } - protected emitClassDefinition(c: ClassType, className: Name): void { + protected emitClassDefinition (c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); this.emitBlock(["class ", className], () => { this.emitClassMembers(c); @@ -185,20 +192,20 @@ export class PikeRenderer extends ConvenienceRenderer { this.emitDecodingFunction(className, c); } - protected emitEnum(e: EnumType, enumName: Name): void { + protected emitEnum (e: EnumType, enumName: Name): void { this.emitBlock([e.kind, " ", enumName], () => { let table: Sourcelike[][] = []; this.forEachEnumCase(e, "none", (name, jsonName) => { table.push([ - [name, ' = "', stringEscape(jsonName), '", '], - ['// json: "', jsonName, '"'] + [name, " = \"", stringEscape(jsonName), "\", "], + ["// json: \"", jsonName, "\""], ]); }); this.emitTable(table); }); } - protected emitUnion(u: UnionType, unionName: Name): void { + protected emitUnion (u: UnionType, unionName: Name): void { const isMaybeWithSingleType = nullableFromUnion(u); if (isMaybeWithSingleType !== null) { @@ -220,7 +227,7 @@ export class PikeRenderer extends ConvenienceRenderer { types.map(r => r.map(sl => this.sourcelikeToString(sl))).join("|"), " ", unionName, - ";" + ";", ]); this.ensureBlankLine(); this.emitBlock([unionName, " ", unionName, "_from_JSON(mixed json)"], () => { @@ -228,17 +235,17 @@ export class PikeRenderer extends ConvenienceRenderer { }); } - private emitBlock(line: Sourcelike, f: () => void, opening: Sourcelike = " {", closing: Sourcelike = "}"): void { + private emitBlock (line: Sourcelike, f: () => void, opening: Sourcelike = " {", closing: Sourcelike = "}"): void { this.emitLine(line, opening); this.indent(f); this.emitLine(closing); } - private emitMappingBlock(line: Sourcelike, f: () => void): void { + private emitMappingBlock (line: Sourcelike, f: () => void): void { this.emitBlock(line, f, "([", "]);"); } - private emitClassMembers(c: ClassType): void { + private emitClassMembers (c: ClassType): void { let table: Sourcelike[][] = []; this.forEachClassProperty(c, "none", (name, jsonName, p) => { const pikeType = this.sourceFor(p.type).source; @@ -246,13 +253,13 @@ export class PikeRenderer extends ConvenienceRenderer { table.push([ [pikeType, " "], [name, "; "], - ['// json: "', jsonName, '"'] + ["// json: \"", jsonName, "\""], ]); }); this.emitTable(table); } - private emitInformationComment() { + private emitInformationComment () { this.emitCommentLines( [ "This source has been automatically generated by quicktype.", @@ -267,17 +274,17 @@ export class PikeRenderer extends ConvenienceRenderer { "It will return an instance of .", "Bear in mind that these functions have unexpected behavior,", "and will likely throw an error, if the JSON string does not", - "match the expected interface, even if the JSON itself is valid." + "match the expected interface, even if the JSON itself is valid.", ], - { lineStart: "// " } + { lineStart: "// " }, ); } - private emitTopLevelTypedef(t: Type, name: Name) { + private emitTopLevelTypedef (t: Type, name: Name) { this.emitLine("typedef ", this.sourceFor(t).source, " ", name, ";"); } - private emitTopLevelConverter(t: Type, name: Name) { + private emitTopLevelConverter (t: Type, name: Name) { this.emitBlock([name, " ", name, "_from_JSON(mixed json)"], () => { if (t instanceof PrimitiveType) { this.emitLine(["return json;"]); @@ -298,11 +305,11 @@ export class PikeRenderer extends ConvenienceRenderer { }); } - private emitEncodingFunction(c: ClassType) { + private emitEncodingFunction (c: ClassType) { this.emitBlock(["string encode_json()"], () => { this.emitMappingBlock(["mapping(string:mixed) json = "], () => { this.forEachClassProperty(c, "none", (name, jsonName) => { - this.emitLine(['"', stringEscape(jsonName), '" : ', name, ","]); + this.emitLine(["\"", stringEscape(jsonName), "\" : ", name, ","]); }); }); this.ensureBlankLine(); @@ -310,12 +317,12 @@ export class PikeRenderer extends ConvenienceRenderer { }); } - private emitDecodingFunction(className: Name, c: ClassType) { + private emitDecodingFunction (className: Name, c: ClassType) { this.emitBlock([className, " ", className, "_from_JSON(mixed json)"], () => { this.emitLine([className, " retval = ", className, "();"]); this.ensureBlankLine(); this.forEachClassProperty(c, "none", (name, jsonName) => { - this.emitLine(["retval.", name, ' = json["', stringEscape(jsonName), '"];']); + this.emitLine(["retval.", name, " = json[\"", stringEscape(jsonName), "\"];"]); }); this.ensureBlankLine(); this.emitLine(["return retval;"]); diff --git a/packages/quicktype-core/src/language/Python.ts b/packages/quicktype-core/src/language/Python.ts index bce7db095..91cb653e4 100644 --- a/packages/quicktype-core/src/language/Python.ts +++ b/packages/quicktype-core/src/language/Python.ts @@ -1,18 +1,23 @@ import { TargetLanguage } from "../TargetLanguage"; -import { StringTypeMapping } from "../TypeBuilder"; +import { type StringTypeMapping } from "../TypeBuilder"; +import { + type TransformedStringTypeKind, + type PrimitiveStringTypeKind, + type Type, + type ClassProperty, +} from "../Type"; import { - TransformedStringTypeKind, - PrimitiveStringTypeKind, - Type, EnumType, ClassType, UnionType, - ClassProperty } from "../Type"; -import { RenderContext } from "../Renderer"; -import { Option, getOptionValues, OptionValues, EnumOption, BooleanOption } from "../RendererOptions"; -import { ConvenienceRenderer, ForbiddenWordsInfo, topLevelNameOrder } from "../ConvenienceRenderer"; -import { Namer, funPrefixNamer, Name, DependencyName } from "../Naming"; +import { type RenderContext } from "../Renderer"; +import { type Option, type OptionValues} from "../RendererOptions"; +import { getOptionValues, EnumOption, BooleanOption } from "../RendererOptions"; +import { type ForbiddenWordsInfo} from "../ConvenienceRenderer"; +import { ConvenienceRenderer, topLevelNameOrder } from "../ConvenienceRenderer"; +import { type Namer, type Name} from "../Naming"; +import { funPrefixNamer, DependencyName } from "../Naming"; import { splitIntoWords, combineWords, @@ -21,15 +26,17 @@ import { allUpperWordStyle, allLowerWordStyle, stringEscape, - originalWord + originalWord, } from "../support/Strings"; import { assertNever, panic, defined } from "../support/Support"; -import { Sourcelike, MultiWord, multiWord, singleWord, parenIfNeeded, modifySource } from "../Source"; +import { type Sourcelike, type MultiWord} from "../Source"; +import { multiWord, singleWord, parenIfNeeded, modifySource } from "../Source"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; +import { + type Transformer} from "../Transformers"; import { followTargetType, transformationForType, - Transformer, DecodingChoiceTransformer, ChoiceTransformer, DecodingTransformer, @@ -37,7 +44,7 @@ import { ParseStringTransformer, UnionMemberMatchTransformer, StringifyTransformer, - EncodingTransformer + EncodingTransformer, } from "../Transformers"; import { arrayIntercalate, @@ -45,7 +52,7 @@ import { mapUpdateInto, iterableSome, mapSortBy, - iterableFirst + iterableFirst, } from "collection-utils"; import unicode from "unicode-properties"; @@ -64,7 +71,7 @@ const forbiddenTypeNames = [ "Type", "TypeVar", "T", - "EnumT" + "EnumT", ]; const forbiddenPropertyNames = [ "and", @@ -106,13 +113,13 @@ const forbiddenPropertyNames = [ "try", "while", "with", - "yield" + "yield", ]; -export type PythonFeatures = { - typeHints: boolean; +export interface PythonFeatures { dataClasses: boolean; -}; + typeHints: boolean; +} export const pythonOptions = { features: new EnumOption( @@ -121,20 +128,20 @@ export const pythonOptions = { [ ["3.5", { typeHints: false, dataClasses: false }], ["3.6", { typeHints: true, dataClasses: false }], - ["3.7", { typeHints: true, dataClasses: true }] + ["3.7", { typeHints: true, dataClasses: true }], ], - "3.6" + "3.6", ), justTypes: new BooleanOption("just-types", "Classes only", false), - nicePropertyNames: new BooleanOption("nice-property-names", "Transform property names to be Pythonic", true) + nicePropertyNames: new BooleanOption("nice-property-names", "Transform property names to be Pythonic", true), }; export class PythonTargetLanguage extends TargetLanguage { - protected getOptions(): Option[] { + protected getOptions (): Array> { return [pythonOptions.features, pythonOptions.justTypes, pythonOptions.nicePropertyNames]; } - get stringTypeMapping(): StringTypeMapping { + get stringTypeMapping (): StringTypeMapping { const mapping: Map = new Map(); const dateTimeType = "date-time"; mapping.set("date", dateTimeType); @@ -146,22 +153,23 @@ export class PythonTargetLanguage extends TargetLanguage { return mapping; } - get supportsUnionsWithBothNumberTypes(): boolean { + get supportsUnionsWithBothNumberTypes (): boolean { return true; } - get supportsOptionalClassProperties(): boolean { + get supportsOptionalClassProperties (): boolean { return false; } - needsTransformerForType(t: Type): boolean { + needsTransformerForType (t: Type): boolean { if (t instanceof UnionType) { return iterableSome(t.members, m => this.needsTransformerForType(m)); } + return t.kind === "integer-string" || t.kind === "bool-string"; } - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): PythonRenderer { + protected makeRenderer (renderContext: RenderContext, untypedOptionValues: { [name: string]: any, }): PythonRenderer { const options = getOptionValues(pythonOptions, untypedOptionValues); if (options.justTypes) { return new PythonRenderer(this, renderContext, options); @@ -171,41 +179,43 @@ export class PythonTargetLanguage extends TargetLanguage { } } -function isNormalizedStartCharacter3(utf16Unit: number): boolean { +function isNormalizedStartCharacter3 (utf16Unit: number): boolean { // FIXME: add Other_ID_Start - https://docs.python.org/3/reference/lexical_analysis.html#identifiers const category: string = unicode.getCategory(utf16Unit); - return ["Lu", "Ll", "Lt", "Lm", "Lo", "Nl"].indexOf(category) >= 0; + return ["Lu", "Ll", "Lt", "Lm", "Lo", "Nl"].includes(category); } -function isNormalizedPartCharacter3(utf16Unit: number): boolean { +function isNormalizedPartCharacter3 (utf16Unit: number): boolean { // FIXME: add Other_ID_Continue - https://docs.python.org/3/reference/lexical_analysis.html#identifiers if (isNormalizedStartCharacter3(utf16Unit)) return true; const category: string = unicode.getCategory(utf16Unit); - return ["Mn", "Mc", "Nd", "Pc"].indexOf(category) >= 0; + return ["Mn", "Mc", "Nd", "Pc"].includes(category); } -function isStartCharacter3(utf16Unit: number): boolean { +function isStartCharacter3 (utf16Unit: number): boolean { const s = String.fromCharCode(utf16Unit).normalize("NFKC"); const l = s.length; if (l === 0 || !isNormalizedStartCharacter3(s.charCodeAt(0))) return false; for (let i = 1; i < l; i++) { if (!isNormalizedPartCharacter3(s.charCodeAt(i))) return false; } + return true; } -function isPartCharacter3(utf16Unit: number): boolean { +function isPartCharacter3 (utf16Unit: number): boolean { const s = String.fromCharCode(utf16Unit).normalize("NFKC"); const l = s.length; for (let i = 0; i < l; i++) { if (!isNormalizedPartCharacter3(s.charCodeAt(i))) return false; } + return true; } const legalizeName3 = utf16LegalizeCharacters(isPartCharacter3); -function classNameStyle(original: string): string { +function classNameStyle (original: string): string { const words = splitIntoWords(original); return combineWords( words, @@ -215,18 +225,19 @@ function classNameStyle(original: string): string { allUpperWordStyle, allUpperWordStyle, "", - isStartCharacter3 + isStartCharacter3, ); } -function getWordStyle(uppercase: boolean, forceSnakeNameStyle: boolean) { +function getWordStyle (uppercase: boolean, forceSnakeNameStyle: boolean) { if (!forceSnakeNameStyle) { return originalWord; } + return uppercase ? allUpperWordStyle : allLowerWordStyle; } -function snakeNameStyle(original: string, uppercase: boolean, forceSnakeNameStyle: boolean): string { +function snakeNameStyle (original: string, uppercase: boolean, forceSnakeNameStyle: boolean): string { const wordStyle = getWordStyle(uppercase, forceSnakeNameStyle); const separator = forceSnakeNameStyle ? "_" : ""; const words = splitIntoWords(original); @@ -235,104 +246,106 @@ function snakeNameStyle(original: string, uppercase: boolean, forceSnakeNameStyl export class PythonRenderer extends ConvenienceRenderer { private readonly imports: Map> = new Map(); + private readonly declaredTypes: Set = new Set(); - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - protected readonly pyOptions: OptionValues + protected readonly pyOptions: OptionValues, ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace (): string[] { return forbiddenTypeNames; } - protected forbiddenForObjectProperties(_: ClassType, _classNamed: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties (_: ClassType, _classNamed: Name): ForbiddenWordsInfo { return { names: forbiddenPropertyNames, includeGlobalForbidden: false }; } - protected makeNamedTypeNamer(): Namer { + protected makeNamedTypeNamer (): Namer { return funPrefixNamer("type", classNameStyle); } - protected namerForObjectProperty(): Namer { + protected namerForObjectProperty (): Namer { return funPrefixNamer("property", s => snakeNameStyle(s, false, this.pyOptions.nicePropertyNames)); } - protected makeUnionMemberNamer(): null { + protected makeUnionMemberNamer (): null { return null; } - protected makeEnumCaseNamer(): Namer { + protected makeEnumCaseNamer (): Namer { return funPrefixNamer("enum-case", s => snakeNameStyle(s, true, this.pyOptions.nicePropertyNames)); } - protected get commentLineStart(): string { + protected get commentLineStart (): string { return "# "; } - protected emitDescriptionBlock(lines: Sourcelike[]): void { + protected emitDescriptionBlock (lines: Sourcelike[]): void { if (lines.length === 1) { const docstring = modifySource(content => { - if (content.endsWith('"')) { - return content.slice(0, -1) + '\\"'; + if (content.endsWith("\"")) { + return content.slice(0, -1) + "\\\""; } return content; }, lines[0]); - this.emitComments([{ customLines: [docstring], lineStart: '"""', lineEnd: '"""' }]); + this.emitComments([{ customLines: [docstring], lineStart: "\"\"\"", lineEnd: "\"\"\"" }]); } else { this.emitCommentLines(lines, { - firstLineStart: '"""', + firstLineStart: "\"\"\"", lineStart: "", - afterComment: '"""' + afterComment: "\"\"\"", }); } } - protected get needsTypeDeclarationBeforeUse(): boolean { + protected get needsTypeDeclarationBeforeUse (): boolean { return true; } - protected canBeForwardDeclared(t: Type): boolean { + protected canBeForwardDeclared (t: Type): boolean { const kind = t.kind; return kind === "class" || kind === "enum"; } - protected emitBlock(line: Sourcelike, f: () => void): void { + protected emitBlock (line: Sourcelike, f: () => void): void { this.emitLine(line); this.indent(f); } - protected string(s: string): Sourcelike { - const openQuote = '"'; - return [openQuote, stringEscape(s), '"']; + protected string (s: string): Sourcelike { + const openQuote = "\""; + return [openQuote, stringEscape(s), "\""]; } - protected withImport(module: string, name: string): Sourcelike { + protected withImport (module: string, name: string): Sourcelike { if (this.pyOptions.features.typeHints || module !== "typing") { // FIXME: This is ugly. We should rather not generate that import in the first // place, but right now we just make the type source and then throw it away. It's // not a performance issue, so it's fine, I just bemoan this special case, and // potential others down the road. - mapUpdateInto(this.imports, module, s => (s ? setUnionInto(s, [name]) : new Set([name]))); + mapUpdateInto(this.imports, module, s => s ? setUnionInto(s, [name]) : new Set([name])); } + return name; } - protected withTyping(name: string): Sourcelike { + protected withTyping (name: string): Sourcelike { return this.withImport("typing", name); } - protected namedType(t: Type): Sourcelike { + protected namedType (t: Type): Sourcelike { const name = this.nameForNamedType(t); if (this.declaredTypes.has(t)) return name; return ["'", name, "'"]; } - protected pythonType(t: Type, _isRootTypeDef = false): Sourcelike { + protected pythonType (t: Type, _isRootTypeDef = false): Sourcelike { const actualType = followTargetType(t); return matchType( @@ -367,7 +380,7 @@ export class PythonRenderer extends ConvenienceRenderer { "[Union[", arrayIntercalate(", ", memberTypes), "]]", - ...rest + ...rest, ]; } else { return [this.withTyping("Optional"), "[", defined(iterableFirst(memberTypes)), "]", ...rest]; @@ -380,21 +393,25 @@ export class PythonRenderer extends ConvenienceRenderer { if (transformedStringType.kind === "date-time") { return this.withImport("datetime", "datetime"); } + if (transformedStringType.kind === "uuid") { return this.withImport("uuid", "UUID"); } + return panic(`Transformed type ${transformedStringType.kind} not supported`); - } + }, ); } - protected declarationLine(t: Type): Sourcelike { + protected declarationLine (t: Type): Sourcelike { if (t instanceof ClassType) { return ["class ", this.nameForNamedType(t), ":"]; } + if (t instanceof EnumType) { return ["class ", this.nameForNamedType(t), "(", this.withImport("enum", "Enum"), "):"]; } + return panic(`Can't declare type ${t.kind}`); } @@ -406,7 +423,7 @@ export class PythonRenderer extends ConvenienceRenderer { this.declaredTypes.add(t); } - protected emitClassMembers(t: ClassType): void { + protected emitClassMembers (t: ClassType): void { if (this.pyOptions.features.dataClasses) return; const args: Sourcelike[] = []; @@ -423,42 +440,44 @@ export class PythonRenderer extends ConvenienceRenderer { this.emitLine("self.", name, " = ", name); }); } - } + }, ); } - protected typeHint(...sl: Sourcelike[]): Sourcelike { + protected typeHint (...sl: Sourcelike[]): Sourcelike { if (this.pyOptions.features.typeHints) { return sl; } + return []; } - protected typingDecl(name: Sourcelike, type: string): Sourcelike { + protected typingDecl (name: Sourcelike, type: string): Sourcelike { return [name, this.typeHint(": ", this.withTyping(type))]; } - protected typingReturn(type: string): Sourcelike { + protected typingReturn (type: string): Sourcelike { return this.typeHint(" -> ", this.withTyping(type)); } - protected sortClassProperties( + protected sortClassProperties ( properties: ReadonlyMap, - propertyNames: ReadonlyMap + propertyNames: ReadonlyMap, ): ReadonlyMap { if (this.pyOptions.features.dataClasses) { return mapSortBy(properties, (p: ClassProperty) => { - return (p.type instanceof UnionType && nullableFromUnion(p.type) != null) || p.isOptional ? 1 : 0; + return p.type instanceof UnionType && nullableFromUnion(p.type) != null || p.isOptional ? 1 : 0; }); } else { return super.sortClassProperties(properties, propertyNames); } } - protected emitClass(t: ClassType): void { + protected emitClass (t: ClassType): void { if (this.pyOptions.features.dataClasses) { this.emitLine("@", this.withImport("dataclasses", "dataclass")); } + this.declareType(t, () => { if (this.pyOptions.features.typeHints) { if (t.getProperties().size === 0) { @@ -469,13 +488,15 @@ export class PythonRenderer extends ConvenienceRenderer { this.emitDescription(this.descriptionForClassProperty(t, jsonName)); }); } + this.ensureBlankLine(); } + this.emitClassMembers(t); }); } - protected emitEnum(t: EnumType): void { + protected emitEnum (t: EnumType): void { this.declareType(t, () => { this.forEachEnumCase(t, "none", (name, jsonName) => { this.emitLine([name, " = ", this.string(jsonName)]); @@ -483,21 +504,21 @@ export class PythonRenderer extends ConvenienceRenderer { }); } - protected emitImports(): void { + protected emitImports (): void { this.imports.forEach((names, module) => { this.emitLine("from ", module, " import ", Array.from(names).join(", ")); }); } - protected emitSupportCode(): void { + protected emitSupportCode (): void { return; } - protected emitClosingCode(): void { + protected emitClosingCode (): void { return; } - protected emitSourceStructure(_givenOutputFilename: string): void { + protected emitSourceStructure (_givenOutputFilename: string): void { const declarationLines = this.gatherSource(() => { this.forEachNamedType( ["interposing", 2], @@ -505,7 +526,7 @@ export class PythonRenderer extends ConvenienceRenderer { e => this.emitEnum(e), _u => { return; - } + }, ); }); @@ -515,6 +536,7 @@ export class PythonRenderer extends ConvenienceRenderer { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } + this.ensureBlankLine(); this.emitImports(); this.ensureBlankLine(2); @@ -542,10 +564,10 @@ export type ConverterFunction = | "from-stringified-bool" | "is-type"; -type TopLevelConverterNames = { +interface TopLevelConverterNames { fromDict: Name; toDict: Name; -}; +} // A value or a lambda. All four combinations are valid: // @@ -553,10 +575,10 @@ type TopLevelConverterNames = { // * `lambda` only: a lambda given by `lambda` // * `value` only: a value given by `value` // * neither: the identity function, i.e. `lambda x: x` -export type ValueOrLambda = { - value: Sourcelike | undefined; +export interface ValueOrLambda { lambda?: MultiWord; -}; + value: Sourcelike | undefined; +} // Return the result of composing `input` and `f`. `input` can be a // value or a lambda, but `f` must be a lambda or a TypeScript function @@ -564,18 +586,20 @@ export type ValueOrLambda = { // // * If `input` is a value, the result is `f(input)`. // * If `input` is a lambda, the result is `lambda x: f(input(x))` -function compose(input: ValueOrLambda, f: (arg: Sourcelike) => Sourcelike): ValueOrLambda; -function compose(input: ValueOrLambda, f: ValueOrLambda): ValueOrLambda; -function compose(input: ValueOrLambda, f: ValueOrLambda | ((arg: Sourcelike) => Sourcelike)): ValueOrLambda { +function compose (input: ValueOrLambda, f: (arg: Sourcelike) => Sourcelike): ValueOrLambda; +function compose (input: ValueOrLambda, f: ValueOrLambda): ValueOrLambda; +function compose (input: ValueOrLambda, f: ValueOrLambda | ((arg: Sourcelike) => Sourcelike)): ValueOrLambda { if (typeof f === "function") { if (input.value !== undefined) { // `input` is a value, so just apply `f` to its source form. return { value: f(makeValue(input)) }; } + if (input.lambda !== undefined) { // `input` is a lambda, so build `lambda x: f(input(x))`. return { lambda: multiWord(" ", "lambda x:", f([parenIfNeeded(input.lambda), "(x)"])), value: undefined }; } + // `input` is the identify function, so the composition is `lambda x: f(x)`. return { lambda: multiWord(" ", "lambda x:", f("x")), value: undefined }; } @@ -583,6 +607,7 @@ function compose(input: ValueOrLambda, f: ValueOrLambda | ((arg: Sourcelike) => if (f.value !== undefined) { return panic("Cannot compose into a value"); } + if (f.lambda === undefined) { // `f` is the identity function, so the result is just `input`. return input; @@ -594,10 +619,11 @@ function compose(input: ValueOrLambda, f: ValueOrLambda | ((arg: Sourcelike) => // `input` is the identity function, so the result is just `f`. return f; } + // `input` is a lambda, so the result is `lambda x: f(input(x))`. return { lambda: multiWord("", "lambda x: ", parenIfNeeded(f.lambda), "(", parenIfNeeded(input.lambda), "(x))"), - value: undefined + value: undefined, }; } @@ -609,48 +635,58 @@ const identity: ValueOrLambda = { value: undefined }; // If `vol` is a lambda, return it in its source form. If it's // a value, return a `lambda` that returns the value. -function makeLambda(vol: ValueOrLambda): MultiWord { +function makeLambda (vol: ValueOrLambda): MultiWord { if (vol.lambda !== undefined) { if (vol.value === undefined) { return vol.lambda; } + return multiWord("", "lambda x: ", parenIfNeeded(vol.lambda), "(", vol.value, ")"); } else if (vol.value !== undefined) { return multiWord(" ", "lambda x:", vol.value); } + return multiWord(" ", "lambda x:", "x"); } // If `vol` is a value, return the value in its source form. // Calling this with `vol` being a lambda is not allowed. -function makeValue(vol: ValueOrLambda): Sourcelike { +function makeValue (vol: ValueOrLambda): Sourcelike { if (vol.value === undefined) { return panic("Cannot make value from lambda without value"); } + if (vol.lambda !== undefined) { return [parenIfNeeded(vol.lambda), "(", vol.value, ")"]; } + return vol.value; } export class JSONPythonRenderer extends PythonRenderer { private readonly _deserializerFunctions = new Set(); + private readonly _converterNamer = funPrefixNamer("converter", s => - snakeNameStyle(s, false, this.pyOptions.nicePropertyNames) + snakeNameStyle(s, false, this.pyOptions.nicePropertyNames), ); + private readonly _topLevelConverterNames = new Map(); + private _haveTypeVar = false; + private _haveEnumTypeVar = false; + private _haveDateutil = false; - protected emitTypeVar(tvar: string, constraints: Sourcelike): void { + protected emitTypeVar (tvar: string, constraints: Sourcelike): void { if (!this.pyOptions.features.typeHints) { return; } + this.emitLine(tvar, " = ", this.withTyping("TypeVar"), "(", this.string(tvar), constraints, ")"); } - protected typeVar(): string { + protected typeVar (): string { this._haveTypeVar = true; // FIXME: This is ugly, but the code that requires the type variables, in // `emitImports` actually runs after imports have been imported. The proper @@ -662,7 +698,7 @@ export class JSONPythonRenderer extends PythonRenderer { return "T"; } - protected enumTypeVar(): string { + protected enumTypeVar (): string { this._haveEnumTypeVar = true; // See the comment above. this.withTyping("TypeVar"); @@ -670,14 +706,15 @@ export class JSONPythonRenderer extends PythonRenderer { return "EnumT"; } - protected cast(type: Sourcelike, v: Sourcelike): Sourcelike { + protected cast (type: Sourcelike, v: Sourcelike): Sourcelike { if (!this.pyOptions.features.typeHints) { return v; } + return [this.withTyping("cast"), "(", type, ", ", v, ")"]; } - protected emitNoneConverter(): void { + protected emitNoneConverter (): void { // FIXME: We can't return the None type here because mypy thinks that means // We're not returning any value, when we're actually returning `None`. this.emitBlock( @@ -685,39 +722,39 @@ export class JSONPythonRenderer extends PythonRenderer { () => { this.emitLine("assert x is None"); this.emitLine("return x"); - } + }, ); } - protected emitBoolConverter(): void { + protected emitBoolConverter (): void { this.emitBlock(["def from_bool(", this.typingDecl("x", "Any"), ")", this.typeHint(" -> bool"), ":"], () => { this.emitLine("assert isinstance(x, bool)"); this.emitLine("return x"); }); } - protected emitIntConverter(): void { + protected emitIntConverter (): void { this.emitBlock(["def from_int(", this.typingDecl("x", "Any"), ")", this.typeHint(" -> int"), ":"], () => { this.emitLine("assert isinstance(x, int) and not isinstance(x, bool)"); this.emitLine("return x"); }); } - protected emitFromFloatConverter(): void { + protected emitFromFloatConverter (): void { this.emitBlock(["def from_float(", this.typingDecl("x", "Any"), ")", this.typeHint(" -> float"), ":"], () => { this.emitLine("assert isinstance(x, (float, int)) and not isinstance(x, bool)"); this.emitLine("return float(x)"); }); } - protected emitToFloatConverter(): void { + protected emitToFloatConverter (): void { this.emitBlock(["def to_float(", this.typingDecl("x", "Any"), ")", this.typeHint(" -> float"), ":"], () => { this.emitLine("assert isinstance(x, float)"); this.emitLine("return x"); }); } - protected emitStrConverter(): void { + protected emitStrConverter (): void { this.emitBlock(["def from_str(", this.typingDecl("x", "Any"), ")", this.typeHint(" -> str"), ":"], () => { const strType = "str"; this.emitLine("assert isinstance(x, ", strType, ")"); @@ -725,7 +762,7 @@ export class JSONPythonRenderer extends PythonRenderer { }); } - protected emitToEnumConverter(): void { + protected emitToEnumConverter (): void { const tvar = this.enumTypeVar(); this.emitBlock( [ @@ -735,16 +772,16 @@ export class JSONPythonRenderer extends PythonRenderer { this.typingDecl("x", "Any"), ")", this.typeHint(" -> ", tvar), - ":" + ":", ], () => { this.emitLine("assert isinstance(x, c)"); this.emitLine("return x.value"); - } + }, ); } - protected emitListConverter(): void { + protected emitListConverter (): void { const tvar = this.typeVar(); this.emitBlock( [ @@ -754,16 +791,16 @@ export class JSONPythonRenderer extends PythonRenderer { this.typingDecl("x", "Any"), ")", this.typeHint(" -> ", this.withTyping("List"), "[", tvar, "]"), - ":" + ":", ], () => { this.emitLine("assert isinstance(x, list)"); this.emitLine("return [f(y) for y in x]"); - } + }, ); } - protected emitToClassConverter(): void { + protected emitToClassConverter (): void { const tvar = this.typeVar(); this.emitBlock( [ @@ -773,16 +810,16 @@ export class JSONPythonRenderer extends PythonRenderer { this.typingDecl("x", "Any"), ")", this.typeHint(" -> dict"), - ":" + ":", ], () => { this.emitLine("assert isinstance(x, c)"); this.emitLine("return ", this.cast(this.withTyping("Any"), "x"), ".to_dict()"); - } + }, ); } - protected emitDictConverter(): void { + protected emitDictConverter (): void { const tvar = this.typeVar(); this.emitBlock( [ @@ -792,18 +829,18 @@ export class JSONPythonRenderer extends PythonRenderer { this.typingDecl("x", "Any"), ")", this.typeHint(" -> ", this.withTyping("Dict"), "[str, ", tvar, "]"), - ":" + ":", ], () => { this.emitLine("assert isinstance(x, dict)"); this.emitLine("return { k: f(v) for (k, v) in x.items() }"); - } + }, ); } // This is not easily idiomatically typeable in Python. See // https://stackoverflow.com/questions/51066468/computed-types-in-mypy/51084497 - protected emitUnionConverter(): void { + protected emitUnionConverter (): void { this.emitMultiline(`def from_union(fs, x): for f in fs: try: @@ -813,34 +850,34 @@ export class JSONPythonRenderer extends PythonRenderer { assert False`); } - protected emitFromDatetimeConverter(): void { + protected emitFromDatetimeConverter (): void { this.emitBlock( [ "def from_datetime(", this.typingDecl("x", "Any"), ")", this.typeHint(" -> ", this.withImport("datetime", "datetime")), - ":" + ":", ], () => { this._haveDateutil = true; this.emitLine("return dateutil.parser.parse(x)"); - } + }, ); } - protected emitFromStringifiedBoolConverter(): void { + protected emitFromStringifiedBoolConverter (): void { this.emitBlock( ["def from_stringified_bool(x", this.typeHint(": str"), ")", this.typeHint(" -> bool"), ":"], () => { - this.emitBlock('if x == "true":', () => this.emitLine("return True")); - this.emitBlock('if x == "false":', () => this.emitLine("return False")); + this.emitBlock("if x == \"true\":", () => this.emitLine("return True")); + this.emitBlock("if x == \"false\":", () => this.emitLine("return False")); this.emitLine("assert False"); - } + }, ); } - protected emitIsTypeConverter(): void { + protected emitIsTypeConverter (): void { const tvar = this.typeVar(); this.emitBlock( [ @@ -850,52 +887,66 @@ export class JSONPythonRenderer extends PythonRenderer { this.typingDecl("x", "Any"), ")", this.typeHint(" -> ", tvar), - ":" + ":", ], () => { this.emitLine("assert isinstance(x, t)"); this.emitLine("return x"); - } + }, ); } - protected emitConverter(cf: ConverterFunction): void { + protected emitConverter (cf: ConverterFunction): void { switch (cf) { case "none": - return this.emitNoneConverter(); + { this.emitNoneConverter(); return; } + case "bool": - return this.emitBoolConverter(); + { this.emitBoolConverter(); return; } + case "int": - return this.emitIntConverter(); + { this.emitIntConverter(); return; } + case "from-float": - return this.emitFromFloatConverter(); + { this.emitFromFloatConverter(); return; } + case "to-float": - return this.emitToFloatConverter(); + { this.emitToFloatConverter(); return; } + case "str": - return this.emitStrConverter(); + { this.emitStrConverter(); return; } + case "to-enum": - return this.emitToEnumConverter(); + { this.emitToEnumConverter(); return; } + case "list": - return this.emitListConverter(); + { this.emitListConverter(); return; } + case "to-class": - return this.emitToClassConverter(); + { this.emitToClassConverter(); return; } + case "dict": - return this.emitDictConverter(); + { this.emitDictConverter(); return; } + case "union": - return this.emitUnionConverter(); + { this.emitUnionConverter(); return; } + case "from-datetime": - return this.emitFromDatetimeConverter(); + { this.emitFromDatetimeConverter(); return; } + case "from-stringified-bool": - return this.emitFromStringifiedBoolConverter(); + { this.emitFromStringifiedBoolConverter(); return; } + case "is-type": - return this.emitIsTypeConverter(); + { this.emitIsTypeConverter(); return; } + default: return assertNever(cf); } } // Return the name of the Python converter function `cf`. - protected conv(cf: ConverterFunction): Sourcelike { + protected conv (cf: ConverterFunction): Sourcelike { this._deserializerFunctions.add(cf); const name = cf.replace(/-/g, "_"); if (cf.startsWith("from-") || cf.startsWith("to-") || cf.startsWith("is-")) return name; @@ -903,11 +954,11 @@ export class JSONPythonRenderer extends PythonRenderer { } // Applies the converter function to `arg` - protected convFn(cf: ConverterFunction, arg: ValueOrLambda): ValueOrLambda { + protected convFn (cf: ConverterFunction, arg: ValueOrLambda): ValueOrLambda { return compose(arg, { lambda: singleWord(this.conv(cf)), value: undefined }); } - protected typeObject(t: Type): Sourcelike { + protected typeObject (t: Type): Sourcelike { const s = matchType( t, _anyType => undefined, @@ -925,23 +976,27 @@ export class JSONPythonRenderer extends PythonRenderer { if (transformedStringType.kind === "date-time") { return this.withImport("datetime", "datetime"); } + if (transformedStringType.kind === "uuid") { return this.withImport("uuid", "UUID"); } + return undefined; - } + }, ); if (s === undefined) { return panic(`No type object for ${t.kind}`); } + return s; } - protected transformer(inputTransformer: ValueOrLambda, xfer: Transformer, targetType: Type): ValueOrLambda { + protected transformer (inputTransformer: ValueOrLambda, xfer: Transformer, targetType: Type): ValueOrLambda { const consume = (consumer: Transformer | undefined, vol: ValueOrLambda) => { if (consumer === undefined) { return vol; } + return this.transformer(vol, consumer, targetType); }; @@ -957,7 +1012,7 @@ export class JSONPythonRenderer extends PythonRenderer { arrayIntercalate(", ", lambdas), "], ", v, - ")" + ")", ]); } else if (xfer instanceof DecodingTransformer) { const consumer = xfer.consumer; @@ -994,6 +1049,7 @@ export class JSONPythonRenderer extends PythonRenderer { default: return panic(`Parsing of ${immediateTargetType.kind} in a transformer is not supported`); } + return consume(consumer, vol); } else if (xfer instanceof StringifyTransformer) { const consumer = xfer.consumer; @@ -1017,6 +1073,7 @@ export class JSONPythonRenderer extends PythonRenderer { default: return panic(`Parsing of ${xfer.sourceType.kind} in a transformer is not supported`); } + return consume(consumer, vol); } else { return panic(`Transformer ${xfer.kind} is not supported`); @@ -1026,11 +1083,12 @@ export class JSONPythonRenderer extends PythonRenderer { // Returns the code to deserialize `value` as type `t`. If `t` has // an associated transformer, the code for that transformer is // returned. - protected deserializer(value: ValueOrLambda, t: Type): ValueOrLambda { + protected deserializer (value: ValueOrLambda, t: Type): ValueOrLambda { const xf = transformationForType(t); if (xf !== undefined) { return this.transformer(value, xf.transformer, xf.targetType); } + return matchType( t, _anyType => value, @@ -1046,12 +1104,12 @@ export class JSONPythonRenderer extends PythonRenderer { makeLambda(this.deserializer(identity, arrayType.items)).source, ", ", v, - ")" + ")", ]), classType => compose(value, { lambda: singleWord(this.nameForNamedType(classType), ".from_dict"), - value: undefined + value: undefined, }), mapType => compose(value, v => [ @@ -1060,13 +1118,13 @@ export class JSONPythonRenderer extends PythonRenderer { makeLambda(this.deserializer(identity, mapType.values)).source, ", ", v, - ")" + ")", ]), enumType => compose(value, { lambda: singleWord(this.nameForNamedType(enumType)), value: undefined }), unionType => { // FIXME: handle via transformers const deserializers = Array.from(unionType.members).map( - m => makeLambda(this.deserializer(identity, m)).source + m => makeLambda(this.deserializer(identity, m)).source, ); return compose(value, v => [ this.conv("union"), @@ -1074,7 +1132,7 @@ export class JSONPythonRenderer extends PythonRenderer { arrayIntercalate(", ", deserializers), "], ", v, - ")" + ")", ]); }, transformedStringType => { @@ -1082,20 +1140,23 @@ export class JSONPythonRenderer extends PythonRenderer { if (transformedStringType.kind === "date-time") { return this.convFn("from-datetime", value); } + if (transformedStringType.kind === "uuid") { return compose(value, v => [this.withImport("uuid", "UUID"), "(", v, ")"]); } + return panic(`Transformed type ${transformedStringType.kind} not supported`); - } + }, ); } - protected serializer(value: ValueOrLambda, t: Type): ValueOrLambda { + protected serializer (value: ValueOrLambda, t: Type): ValueOrLambda { const xf = transformationForType(t); if (xf !== undefined) { const reverse = xf.reverse; return this.transformer(value, reverse.transformer, reverse.targetType); } + return matchType( t, _anyType => value, @@ -1111,7 +1172,7 @@ export class JSONPythonRenderer extends PythonRenderer { makeLambda(this.serializer(identity, arrayType.items)).source, ", ", v, - ")" + ")", ]), classType => compose(value, v => [this.conv("to-class"), "(", this.nameForNamedType(classType), ", ", v, ")"]), @@ -1122,12 +1183,12 @@ export class JSONPythonRenderer extends PythonRenderer { makeLambda(this.serializer(identity, mapType.values)).source, ", ", v, - ")" + ")", ]), enumType => compose(value, v => [this.conv("to-enum"), "(", this.nameForNamedType(enumType), ", ", v, ")"]), unionType => { const serializers = Array.from(unionType.members).map( - m => makeLambda(this.serializer(identity, m)).source + m => makeLambda(this.serializer(identity, m)).source, ); return compose(value, v => [ this.conv("union"), @@ -1135,22 +1196,24 @@ export class JSONPythonRenderer extends PythonRenderer { arrayIntercalate(", ", serializers), "], ", v, - ")" + ")", ]); }, transformedStringType => { if (transformedStringType.kind === "date-time") { return compose(value, v => [v, ".isoformat()"]); } + if (transformedStringType.kind === "uuid") { return compose(value, v => ["str(", v, ")"]); } + return panic(`Transformed type ${transformedStringType.kind} not supported`); - } + }, ); } - protected emitClassMembers(t: ClassType): void { + protected emitClassMembers (t: ClassType): void { super.emitClassMembers(t); this.ensureBlankLine(); @@ -1168,7 +1231,7 @@ export class JSONPythonRenderer extends PythonRenderer { args.push(name); }); this.emitLine("return ", className, "(", arrayIntercalate(", ", args), ")"); - } + }, ); this.ensureBlankLine(); @@ -1182,7 +1245,7 @@ export class JSONPythonRenderer extends PythonRenderer { "result[", this.string(jsonName), "] = ", - makeValue(this.serializer(property, cp.type)) + makeValue(this.serializer(property, cp.type)), ); }); } else { @@ -1190,7 +1253,7 @@ export class JSONPythonRenderer extends PythonRenderer { "result[", this.string(jsonName), "] = ", - makeValue(this.serializer(property, cp.type)) + makeValue(this.serializer(property, cp.type)), ); } }); @@ -1198,7 +1261,7 @@ export class JSONPythonRenderer extends PythonRenderer { }); } - protected emitImports(): void { + protected emitImports (): void { super.emitImports(); if (this._haveDateutil) { this.emitLine("import dateutil.parser"); @@ -1210,46 +1273,48 @@ export class JSONPythonRenderer extends PythonRenderer { if (this._haveTypeVar) { this.emitTypeVar(this.typeVar(), []); } + if (this._haveEnumTypeVar) { this.emitTypeVar(this.enumTypeVar(), [", bound=", this.withImport("enum", "Enum")]); } } - protected emitSupportCode(): void { + protected emitSupportCode (): void { const map = Array.from(this._deserializerFunctions).map(f => [f, f] as [ConverterFunction, ConverterFunction]); this.forEachWithBlankLines(map, ["interposing", 2], cf => { this.emitConverter(cf); }); } - protected makeTopLevelDependencyNames(_t: Type, topLevelName: Name): DependencyName[] { + protected makeTopLevelDependencyNames (_t: Type, topLevelName: Name): DependencyName[] { const fromDict = new DependencyName( this._converterNamer, topLevelNameOrder, - l => `${l(topLevelName)}_from_dict` + l => `${l(topLevelName)}_from_dict`, ); const toDict = new DependencyName(this._converterNamer, topLevelNameOrder, l => `${l(topLevelName)}_to_dict`); this._topLevelConverterNames.set(topLevelName, { fromDict, toDict }); return [fromDict, toDict]; } - protected emitDefaultLeadingComments(): void { + protected emitDefaultLeadingComments (): void { this.ensureBlankLine(); if (this._haveDateutil) { this.emitCommentLines([ "This code parses date/times, so please", "", " pip install python-dateutil", - "" + "", ]); } + this.emitCommentLines([ "To use this code, make sure you", "", " import json", "", "and then, to convert JSON from a string, do", - "" + "", ]); this.forEachTopLevel("none", (_, name) => { const { fromDict } = defined(this._topLevelConverterNames.get(name)); @@ -1257,7 +1322,7 @@ export class JSONPythonRenderer extends PythonRenderer { }); } - protected emitClosingCode(): void { + protected emitClosingCode (): void { this.forEachTopLevel(["interposing", 2], (t, name) => { const { fromDict, toDict } = defined(this._topLevelConverterNames.get(name)); const pythonType = this.pythonType(t); @@ -1265,14 +1330,14 @@ export class JSONPythonRenderer extends PythonRenderer { ["def ", fromDict, "(", this.typingDecl("s", "Any"), ")", this.typeHint(" -> ", pythonType), ":"], () => { this.emitLine("return ", makeValue(this.deserializer({ value: "s" }, t))); - } + }, ); this.ensureBlankLine(2); this.emitBlock( ["def ", toDict, "(x", this.typeHint(": ", pythonType), ")", this.typingReturn("Any"), ":"], () => { this.emitLine("return ", makeValue(this.serializer({ value: "x" }, t))); - } + }, ); }); } diff --git a/packages/quicktype-core/src/language/Rust.ts b/packages/quicktype-core/src/language/Rust.ts index 56b464161..b09b1dc7f 100644 --- a/packages/quicktype-core/src/language/Rust.ts +++ b/packages/quicktype-core/src/language/Rust.ts @@ -1,7 +1,8 @@ import { mapFirst } from "collection-utils"; import { TargetLanguage } from "../TargetLanguage"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { ConvenienceRenderer } from "../ConvenienceRenderer"; import { legalizeCharacters, splitIntoWords, @@ -14,16 +15,20 @@ import { escapeNonPrintableMapper, isPrintable, isAscii, - isLetterOrUnderscore + isLetterOrUnderscore, } from "../support/Strings"; -import { Name, Namer, funPrefixNamer } from "../Naming"; -import { UnionType, Type, ClassType, EnumType } from "../Type"; +import { type Name, type Namer} from "../Naming"; +import { funPrefixNamer } from "../Naming"; +import { type Type, type ClassType, type EnumType } from "../Type"; +import { UnionType } from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { Sourcelike, maybeAnnotated } from "../Source"; +import { type Sourcelike} from "../Source"; +import { maybeAnnotated } from "../Source"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { BooleanOption, EnumOption, Option, getOptionValues, OptionValues } from "../RendererOptions"; +import { type Option, type OptionValues } from "../RendererOptions"; +import { BooleanOption, EnumOption, getOptionValues } from "../RendererOptions"; import { defined } from "../support/Support"; -import { RenderContext } from "../Renderer"; +import { type RenderContext } from "../Renderer"; export enum Density { Normal, @@ -39,39 +44,39 @@ export enum Visibility { export const rustOptions = { density: new EnumOption("density", "Density", [ ["normal", Density.Normal], - ["dense", Density.Dense] + ["dense", Density.Dense], ]), visibility: new EnumOption("visibility", "Field visibility", [ ["private", Visibility.Private], ["crate", Visibility.Crate], - ["public", Visibility.Public] + ["public", Visibility.Public], ]), deriveDebug: new BooleanOption("derive-debug", "Derive Debug impl", false), deriveClone: new BooleanOption("derive-clone", "Derive Clone impl", false), derivePartialEq: new BooleanOption("derive-partial-eq", "Derive PartialEq impl", false), skipSerializingNone: new BooleanOption("skip-serializing-none", "Skip serializing empty Option fields", false), edition2018: new BooleanOption("edition-2018", "Edition 2018", true), - leadingComments: new BooleanOption("leading-comments", "Leading Comments", true) + leadingComments: new BooleanOption("leading-comments", "Leading Comments", true), }; type NameToParts = (name: string) => string[]; type PartsToName = (parts: string[]) => string; -type NamingStyle = { +interface NamingStyle { + fromParts: PartsToName; regex: RegExp; toParts: NameToParts; - fromParts: PartsToName; -}; +} const namingStyles: Record = { snake_case: { regex: /^[a-z][a-z0-9]*(_[a-z0-9]+)*$/, toParts: (name: string): string[] => name.split("_"), - fromParts: (parts: string[]): string => parts.map(p => p.toLowerCase()).join("_") + fromParts: (parts: string[]): string => parts.map(p => p.toLowerCase()).join("_"), }, SCREAMING_SNAKE_CASE: { regex: /^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$/, toParts: (name: string): string[] => name.split("_"), - fromParts: (parts: string[]): string => parts.map(p => p.toUpperCase()).join("_") + fromParts: (parts: string[]): string => parts.map(p => p.toUpperCase()).join("_"), }, camelCase: { regex: /^[a-z]+([A-Z0-9][a-z]*)*$/, @@ -79,48 +84,48 @@ const namingStyles: Record = { fromParts: (parts: string[]): string => parts .map((p, i) => - i === 0 ? p.toLowerCase() : p.substring(0, 1).toUpperCase() + p.substring(1).toLowerCase() + i === 0 ? p.toLowerCase() : p.substring(0, 1).toUpperCase() + p.substring(1).toLowerCase(), ) - .join("") + .join(""), }, PascalCase: { regex: /^[A-Z][a-z]*([A-Z0-9][a-z]*)*$/, toParts: (name: string): string[] => namingStyles.snake_case.toParts(name.replace(/(.)([A-Z])/g, "$1_$2")), fromParts: (parts: string[]): string => - parts.map(p => p.substring(0, 1).toUpperCase() + p.substring(1).toLowerCase()).join("") + parts.map(p => p.substring(0, 1).toUpperCase() + p.substring(1).toLowerCase()).join(""), }, "kebab-case": { regex: /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/, toParts: (name: string): string[] => name.split("-"), - fromParts: (parts: string[]): string => parts.map(p => p.toLowerCase()).join("-") + fromParts: (parts: string[]): string => parts.map(p => p.toLowerCase()).join("-"), }, "SCREAMING-KEBAB-CASE": { regex: /^[A-Z][A-Z0-9]*(-[A-Z0-9]+)*$/, toParts: (name: string): string[] => name.split("-"), - fromParts: (parts: string[]): string => parts.map(p => p.toUpperCase()).join("-") + fromParts: (parts: string[]): string => parts.map(p => p.toUpperCase()).join("-"), }, lowercase: { regex: /^[a-z][a-z0-9]*$/, toParts: (name: string): string[] => [name], - fromParts: (parts: string[]): string => parts.map(p => p.toLowerCase()).join("") + fromParts: (parts: string[]): string => parts.map(p => p.toLowerCase()).join(""), }, UPPERCASE: { regex: /^[A-Z][A-Z0-9]*$/, toParts: (name: string): string[] => [name], - fromParts: (parts: string[]): string => parts.map(p => p.toUpperCase()).join("") - } + fromParts: (parts: string[]): string => parts.map(p => p.toUpperCase()).join(""), + }, }; export class RustTargetLanguage extends TargetLanguage { - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): RustRenderer { + protected makeRenderer (renderContext: RenderContext, untypedOptionValues: { [name: string]: any, }): RustRenderer { return new RustRenderer(this, renderContext, getOptionValues(rustOptions, untypedOptionValues)); } - constructor() { + constructor () { super("Rust", ["rust", "rs", "rustlang"], "rs"); } - protected getOptions(): Option[] { + protected getOptions (): Array> { return [ rustOptions.density, rustOptions.visibility, @@ -129,7 +134,7 @@ export class RustTargetLanguage extends TargetLanguage { rustOptions.derivePartialEq, rustOptions.edition2018, rustOptions.leadingComments, - rustOptions.skipSerializingNone + rustOptions.skipSerializingNone, ]; } } @@ -208,7 +213,7 @@ const keywords = [ "union", // Conflict between `std::Option` and potentially generated Option - "option" + "option", ]; const isAsciiLetterOrUnderscoreOrDigit = (codePoint: number): boolean => { @@ -229,7 +234,7 @@ const isAsciiLetterOrUnderscore = (codePoint: number): boolean => { const legalizeName = legalizeCharacters(isAsciiLetterOrUnderscoreOrDigit); -function rustStyle(original: string, isSnakeCase: boolean): string { +function rustStyle (original: string, isSnakeCase: boolean): string { const words = splitIntoWords(original); const wordStyle = isSnakeCase ? allLowerWordStyle : firstUpperWordStyle; @@ -242,7 +247,7 @@ function rustStyle(original: string, isSnakeCase: boolean): string { wordStyle, wordStyle, isSnakeCase ? "_" : "", - isAsciiLetterOrUnderscore + isAsciiLetterOrUnderscore, ); return combined === "_" ? "_underscore" : combined; @@ -262,60 +267,60 @@ const standardUnicodeRustEscape = (codePoint: number): string => { const rustStringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, standardUnicodeRustEscape)); export class RustRenderer extends ConvenienceRenderer { - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues + private readonly _options: OptionValues, ) { super(targetLanguage, renderContext); } - protected makeNamedTypeNamer(): Namer { + protected makeNamedTypeNamer (): Namer { return camelNamingFunction; } - protected namerForObjectProperty(): Namer | null { + protected namerForObjectProperty (): Namer | null { return snakeNamingFunction; } - protected makeUnionMemberNamer(): Namer | null { + protected makeUnionMemberNamer (): Namer | null { return camelNamingFunction; } - protected makeEnumCaseNamer(): Namer | null { + protected makeEnumCaseNamer (): Namer | null { return camelNamingFunction; } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace (): string[] { return keywords; } - protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties (_c: ClassType, _className: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { + protected forbiddenForUnionMembers (_u: UnionType, _unionName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { + protected forbiddenForEnumCases (_e: EnumType, _enumName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected get commentLineStart(): string { + protected get commentLineStart (): string { return "/// "; } - private nullableRustType(t: Type, withIssues: boolean): Sourcelike { + private nullableRustType (t: Type, withIssues: boolean): Sourcelike { return ["Option<", this.breakCycle(t, withIssues), ">"]; } - protected isImplicitCycleBreaker(t: Type): boolean { + protected isImplicitCycleBreaker (t: Type): boolean { const kind = t.kind; return kind === "array" || kind === "map"; } - private rustType(t: Type, withIssues = false): Sourcelike { + private rustType (t: Type, withIssues = false): Sourcelike { return matchType( t, _anyType => maybeAnnotated(withIssues, anyTypeIssueAnnotation, "Option"), @@ -342,60 +347,61 @@ export class RustRenderer extends ConvenienceRenderer { : this.nameForNamedType(unionType); return hasNull !== null ? (["Option<", name, ">"] as Sourcelike) : name; - } + }, ); } - private breakCycle(t: Type, withIssues: boolean): any { + private breakCycle (t: Type, withIssues: boolean): any { const rustType = this.rustType(t, withIssues); const isCycleBreaker = this.isCycleBreakerType(t); return isCycleBreaker ? ["Box<", rustType, ">"] : rustType; } - private emitRenameAttribute( + private emitRenameAttribute ( propName: Name, jsonName: string, defaultNamingStyle: string, - preferedNamingStyle: string + preferedNamingStyle: string, ) { const escapedName = rustStringEscape(jsonName); const name = namingStyles[defaultNamingStyle].fromParts(this.sourcelikeToString(propName).split(" ")); const styledName = nameToNamingStyle(name, preferedNamingStyle); const namesDiffer = escapedName !== styledName; if (namesDiffer) { - this.emitLine('#[serde(rename = "', escapedName, '")]'); + this.emitLine("#[serde(rename = \"", escapedName, "\")]"); } } - private emitSkipSerializeNone(t: Type) { + private emitSkipSerializeNone (t: Type) { if (t instanceof UnionType) { const nullable = nullableFromUnion(t); - if (nullable !== null) this.emitLine('#[serde(skip_serializing_if = "Option::is_none")]'); + if (nullable !== null) this.emitLine("#[serde(skip_serializing_if = \"Option::is_none\")]"); } } - private get visibility(): string { + private get visibility (): string { if (this._options.visibility === Visibility.Crate) { return "pub(crate) "; } else if (this._options.visibility === Visibility.Public) { return "pub "; } + return ""; } - protected emitStructDefinition(c: ClassType, className: Name): void { + protected emitStructDefinition (c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); this.emitLine( "#[derive(", this._options.deriveDebug ? "Debug, " : "", this._options.deriveClone ? "Clone, " : "", this._options.derivePartialEq ? "PartialEq, " : "", - "Serialize, Deserialize)]" + "Serialize, Deserialize)]", ); // List the possible naming styles for every class property - const propertiesNamingStyles: { [key: string]: string[] } = {}; + const propertiesNamingStyles: { [key: string]: string[], } = {}; this.forEachClassProperty(c, "none", (_name, jsonName, _prop) => { propertiesNamingStyles[jsonName] = listMatchingNamingStyles(jsonName); }); @@ -419,13 +425,13 @@ export class RustRenderer extends ConvenienceRenderer { this.emitBlock(["pub struct ", className], structBody); } - protected emitBlock(line: Sourcelike, f: () => void): void { + protected emitBlock (line: Sourcelike, f: () => void): void { this.emitLine(line, " {"); this.indent(f); this.emitLine("}"); } - protected emitUnion(u: UnionType, unionName: Name): void { + protected emitUnion (u: UnionType, unionName: Name): void { const isMaybeWithSingleType = nullableFromUnion(u); if (isMaybeWithSingleType !== null) { @@ -438,7 +444,7 @@ export class RustRenderer extends ConvenienceRenderer { this._options.deriveDebug ? "Debug, " : "", this._options.deriveClone ? "Clone, " : "", this._options.derivePartialEq ? "PartialEq, " : "", - "Serialize, Deserialize)]" + "Serialize, Deserialize)]", ); this.emitLine("#[serde(untagged)]"); @@ -449,22 +455,22 @@ export class RustRenderer extends ConvenienceRenderer { this.forEachUnionMember(u, nonNulls, blankLines, null, (fieldName, t) => { const rustType = this.breakCycle(t, true); this.emitLine([fieldName, "(", rustType, "),"]); - }) + }), ); } - protected emitEnumDefinition(e: EnumType, enumName: Name): void { + protected emitEnumDefinition (e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); this.emitLine( "#[derive(", this._options.deriveDebug ? "Debug, " : "", this._options.deriveClone ? "Clone, " : "", this._options.derivePartialEq ? "PartialEq, " : "", - "Serialize, Deserialize)]" + "Serialize, Deserialize)]", ); // List the possible naming styles for every enum case - const enumCasesNamingStyles: { [key: string]: string[] } = {}; + const enumCasesNamingStyles: { [key: string]: string[], } = {}; this.forEachEnumCase(e, "none", (_name, jsonName) => { enumCasesNamingStyles[jsonName] = listMatchingNamingStyles(jsonName); }); @@ -481,15 +487,15 @@ export class RustRenderer extends ConvenienceRenderer { this.forEachEnumCase(e, blankLines, (name, jsonName) => { this.emitRenameAttribute(name, jsonName, defaultStyle, preferedNamingStyle); this.emitLine([name, ","]); - }) + }), ); } - protected emitTopLevelAlias(t: Type, name: Name): void { + protected emitTopLevelAlias (t: Type, name: Name): void { this.emitLine("pub type ", name, " = ", this.rustType(t), ";"); } - protected emitLeadingComments(): void { + protected emitLeadingComments (): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); return; @@ -508,14 +514,15 @@ export class RustRenderer extends ConvenienceRenderer { // fn main() { // let json = r#"{"answer": 42}"#; // let model: ${topLevelName} = serde_json::from_str(&json).unwrap(); -// }` +// }`, ); } - protected emitSourceStructure(): void { + protected emitSourceStructure (): void { if (this._options.leadingComments) { this.emitLeadingComments(); } + this.ensureBlankLine(); if (this._options.edition2018) { this.emitLine("use serde::{Serialize, Deserialize};"); @@ -530,19 +537,19 @@ export class RustRenderer extends ConvenienceRenderer { this.forEachTopLevel( "leading", (t, name) => this.emitTopLevelAlias(t, name), - t => this.namedTypeToNameForTopLevel(t) === undefined + t => this.namedTypeToNameForTopLevel(t) === undefined, ); this.forEachNamedType( "leading-and-interposing", (c: ClassType, name: Name) => this.emitStructDefinition(c, name), (e, name) => this.emitEnumDefinition(e, name), - (u, name) => this.emitUnion(u, name) + (u, name) => this.emitUnion(u, name), ); } } -function getPreferedNamingStyle(namingStyleOccurences: string[], defaultStyle: string): string { +function getPreferedNamingStyle (namingStyleOccurences: string[], defaultStyle: string): string { const occurrences = Object.fromEntries(Object.keys(namingStyles).map(key => [key, 0])); namingStyleOccurences.forEach(style => ++occurrences[style]); const max = Math.max(...Object.values(occurrences)); @@ -552,22 +559,25 @@ function getPreferedNamingStyle(namingStyleOccurences: string[], defaultStyle: s if (preferedStyles.includes(defaultStyle)) { return defaultStyle; } + return preferedStyles[0]; } -function listMatchingNamingStyles(name: string): string[] { +function listMatchingNamingStyles (name: string): string[] { return Object.entries(namingStyles) .filter(([_, { regex }]) => regex.test(name)) .map(([namingStyle, _]) => namingStyle); } -function nameToNamingStyle(name: string, style: string): string { +function nameToNamingStyle (name: string, style: string): string { if (namingStyles[style].regex.test(name)) { return name; } + const fromStyle = listMatchingNamingStyles(name)[0]; if (fromStyle === undefined) { return name; } + return namingStyles[style].fromParts(namingStyles[fromStyle].toParts(name)); } diff --git a/packages/quicktype-core/src/language/Scala3.ts b/packages/quicktype-core/src/language/Scala3.ts index 56437c02b..3d93c0343 100644 --- a/packages/quicktype-core/src/language/Scala3.ts +++ b/packages/quicktype-core/src/language/Scala3.ts @@ -1,8 +1,12 @@ import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { Name, Namer, funPrefixNamer } from "../Naming"; -import { EnumOption, Option, StringOption, OptionValues, getOptionValues } from "../RendererOptions"; -import { Sourcelike, maybeAnnotated } from "../Source"; +import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { ConvenienceRenderer } from "../ConvenienceRenderer"; +import { type Name, type Namer} from "../Naming"; +import { funPrefixNamer } from "../Naming"; +import { type Option, type OptionValues} from "../RendererOptions"; +import { EnumOption, StringOption, getOptionValues } from "../RendererOptions"; +import { type Sourcelike} from "../Source"; +import { maybeAnnotated } from "../Source"; import { allLowerWordStyle, allUpperWordStyle, @@ -12,13 +16,14 @@ import { isLetterOrUnderscore, isNumeric, legalizeCharacters, - splitIntoWords + splitIntoWords, } from "../support/Strings"; import { assertNever } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; -import { ArrayType, ClassProperty, ClassType, EnumType, MapType, ObjectType, Type, UnionType } from "../Type"; +import { type ClassProperty, type ClassType, type EnumType, type ObjectType, type Type, type UnionType } from "../Type"; +import { ArrayType, MapType } from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { RenderContext } from "../Renderer"; +import { type RenderContext } from "../Renderer"; export enum Framework { None, @@ -33,11 +38,11 @@ export const scala3Options = { [ ["just-types", Framework.None], ["circe", Framework.Circe], - ["upickle", Framework.Upickle] + ["upickle", Framework.Upickle], ], - undefined + undefined, ), - packageName: new StringOption("package", "Package", "PACKAGE", "quicktype") + packageName: new StringOption("package", "Package", "PACKAGE", "quicktype"), }; // Use backticks for param names with symbols @@ -60,13 +65,13 @@ const invalidSymbols = [ "/", ";", "'", - '"', + "\"", "{", "}", ":", "~", "`", - "." + ".", ]; const keywords = [ @@ -125,7 +130,7 @@ const keywords = [ "Array", "List", "Map", - "Enum" + "Enum", ]; /** @@ -149,17 +154,17 @@ const wrapOption = (s: string, optional: boolean): string => { } }; -function isPartCharacter(codePoint: number): boolean { +function isPartCharacter (codePoint: number): boolean { return isLetterOrUnderscore(codePoint) || isNumeric(codePoint); } -function isStartCharacter(codePoint: number): boolean { +function isStartCharacter (codePoint: number): boolean { return isPartCharacter(codePoint) && !isDigit(codePoint); } const legalizeName = legalizeCharacters(isPartCharacter); -function scalaNameStyle(isUpper: boolean, original: string): string { +function scalaNameStyle (isUpper: boolean, original: string): string { const words = splitIntoWords(original); return combineWords( words, @@ -169,7 +174,7 @@ function scalaNameStyle(isUpper: boolean, original: string): string { isUpper ? allUpperWordStyle : allLowerWordStyle, allUpperWordStyle, "", - isStartCharacter + isStartCharacter, ); } @@ -177,7 +182,7 @@ function scalaNameStyle(isUpper: boolean, original: string): string { return "\\u" + intToHex(codePoint, 4); } */ -//const _stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, unicodeEscape)); +// const _stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, unicodeEscape)); /* function stringEscape(s: string): string { // "$this" is a template string in Kotlin so we have to escape $ @@ -188,94 +193,94 @@ const upperNamingFunction = funPrefixNamer("upper", s => scalaNameStyle(true, s) const lowerNamingFunction = funPrefixNamer("lower", s => scalaNameStyle(false, s)); export class Scala3Renderer extends ConvenienceRenderer { - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - protected readonly _scalaOptions: OptionValues + protected readonly _scalaOptions: OptionValues, ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace (): string[] { return keywords; } - protected forbiddenForObjectProperties(_: ObjectType, _classNamed: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties (_: ObjectType, _classNamed: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForEnumCases(_: EnumType, _enumName: Name): ForbiddenWordsInfo { + protected forbiddenForEnumCases (_: EnumType, _enumName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { + protected forbiddenForUnionMembers (_u: UnionType, _unionName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: false }; } - protected topLevelNameStyle(rawName: string): string { + protected topLevelNameStyle (rawName: string): string { return scalaNameStyle(true, rawName); } - protected makeNamedTypeNamer(): Namer { + protected makeNamedTypeNamer (): Namer { return upperNamingFunction; } - protected namerForObjectProperty(): Namer { + protected namerForObjectProperty (): Namer { return lowerNamingFunction; } - protected makeUnionMemberNamer(): Namer { + protected makeUnionMemberNamer (): Namer { return funPrefixNamer("upper", s => scalaNameStyle(true, s) + "Value"); } - protected makeEnumCaseNamer(): Namer { + protected makeEnumCaseNamer (): Namer { return funPrefixNamer("upper", s => s.replace(" ", "")); // TODO - add backticks where appropriate } - protected emitDescriptionBlock(lines: Sourcelike[]): void { + protected emitDescriptionBlock (lines: Sourcelike[]): void { this.emitCommentLines(lines, { lineStart: " * ", beforeComment: "/**", afterComment: " */" }); } - protected emitBlock( + protected emitBlock ( line: Sourcelike, f: () => void, - delimiter: "curly" | "paren" | "lambda" | "none" = "curly" + delimiter: "curly" | "paren" | "lambda" | "none" = "curly", ): void { const [open, close] = delimiter === "curly" ? ["{", "}"] : delimiter === "paren" - ? ["(", ")"] - : delimiter === "none" - ? ["", ""] - : ["{", "})"]; + ? ["(", ")"] + : delimiter === "none" + ? ["", ""] + : ["{", "})"]; this.emitLine(line, " ", open); this.indent(f); this.emitLine(close); } - protected anySourceType(optional: boolean): Sourcelike { + protected anySourceType (optional: boolean): Sourcelike { return [wrapOption("Any", optional)]; } // (asarazan): I've broken out the following two functions // because some renderers, such as kotlinx, can cope with `any`, while some get mad. - protected arrayType(arrayType: ArrayType, withIssues = false): Sourcelike { + protected arrayType (arrayType: ArrayType, withIssues = false): Sourcelike { return ["Seq[", this.scalaType(arrayType.items, withIssues), "]"]; } - protected mapType(mapType: MapType, withIssues = false): Sourcelike { + protected mapType (mapType: MapType, withIssues = false): Sourcelike { return ["Map[String, ", this.scalaType(mapType.values, withIssues), "]"]; } - protected scalaType(t: Type, withIssues = false, noOptional = false): Sourcelike { + protected scalaType (t: Type, withIssues = false, noOptional = false): Sourcelike { return matchType( t, _anyType => { return maybeAnnotated(withIssues, anyTypeIssueAnnotation, this.anySourceType(!noOptional)); }, _nullType => { - //return "None.type" + // return "None.type" return maybeAnnotated(withIssues, nullTypeIssueAnnotation, this.anySourceType(!noOptional)); }, _boolType => "Boolean", @@ -295,15 +300,17 @@ export class Scala3Renderer extends ConvenienceRenderer { return ["Option[", this.scalaType(nullable, withIssues), "]"]; } } + return this.nameForNamedType(unionType); - } + }, ); } - protected emitUsageHeader(): void { + + protected emitUsageHeader (): void { // To be overridden } - protected emitHeader(): void { + protected emitHeader (): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } else { @@ -315,22 +322,22 @@ export class Scala3Renderer extends ConvenienceRenderer { this.ensureBlankLine(); } - protected emitTopLevelArray(t: ArrayType, name: Name): void { + protected emitTopLevelArray (t: ArrayType, name: Name): void { const elementType = this.scalaType(t.items); this.emitLine(["type ", name, " = List[", elementType, "]"]); } - protected emitTopLevelMap(t: MapType, name: Name): void { + protected emitTopLevelMap (t: MapType, name: Name): void { const elementType = this.scalaType(t.values); this.emitLine(["type ", name, " = Map[String, ", elementType, "]"]); } - protected emitEmptyClassDefinition(c: ClassType, className: Name): void { + protected emitEmptyClassDefinition (c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); this.emitLine("case class ", className, "()"); } - protected emitClassDefinition(c: ClassType, className: Name): void { + protected emitClassDefinition (c: ClassType, className: Name): void { if (c.getProperties().size === 0) { this.emitEmptyClassDefinition(c, className); return; @@ -367,6 +374,7 @@ export class Scala3Renderer extends ConvenienceRenderer { for (const emit of meta) { emit(); } + const nameNeedsBackticks = jsonName.endsWith("_") || shouldAddBacktick(jsonName); const nameWithBackticks = nameNeedsBackticks ? "`" + jsonName + "`" : jsonName; this.emitLine( @@ -375,7 +383,7 @@ export class Scala3Renderer extends ConvenienceRenderer { " : ", scalaType(p), p.isOptional ? " = None" : nullableOrOptional ? " = None" : "", - last ? "" : "," + last ? "" : ",", ); if (meta.length > 0 && !last) { @@ -389,11 +397,11 @@ export class Scala3Renderer extends ConvenienceRenderer { this.emitClassDefinitionMethods(); } - protected emitClassDefinitionMethods() { + protected emitClassDefinitionMethods () { this.emitLine(")"); } - protected emitEnumDefinition(e: EnumType, enumName: Name): void { + protected emitEnumDefinition (e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); this.emitBlock( @@ -403,6 +411,7 @@ export class Scala3Renderer extends ConvenienceRenderer { if (count > 0) { this.emitItem("\t case "); } + this.forEachEnumCase(e, "none", (name, jsonName) => { if (!(jsonName == "")) { const backticks = @@ -412,22 +421,24 @@ export class Scala3Renderer extends ConvenienceRenderer { if (backticks) { this.emitItem("`"); } + this.emitItemOnce([name]); if (backticks) { this.emitItem("`"); } + if (--count > 0) this.emitItem([","]); } else { --count; } }); }, - "none" + "none", ); } - protected emitUnionDefinition(u: UnionType, unionName: Name): void { - function sortBy(t: Type): string { + protected emitUnionDefinition (u: UnionType, unionName: Name): void { + function sortBy (t: Type): string { const kind = t.kind; if (kind === "class") return kind; return "_" + kind; @@ -436,7 +447,7 @@ export class Scala3Renderer extends ConvenienceRenderer { this.emitDescription(this.descriptionForType(u)); const [maybeNull, nonNulls] = removeNullFromUnion(u, sortBy); - const theTypes: Array = []; + const theTypes: Sourcelike[] = []; this.forEachUnionMember(u, nonNulls, "none", null, (_, t) => { theTypes.push(this.scalaType(t)); }); @@ -451,7 +462,7 @@ export class Scala3Renderer extends ConvenienceRenderer { this.ensureBlankLine(); } - protected emitSourceStructure(): void { + protected emitSourceStructure (): void { this.emitHeader(); // Top-level arrays, maps @@ -467,17 +478,17 @@ export class Scala3Renderer extends ConvenienceRenderer { "leading-and-interposing", (c: ClassType, n: Name) => this.emitClassDefinition(c, n), (e, n) => this.emitEnumDefinition(e, n), - (u, n) => this.emitUnionDefinition(u, n) + (u, n) => this.emitUnionDefinition(u, n), ); } } export class UpickleRenderer extends Scala3Renderer { - protected emitClassDefinitionMethods() { + protected emitClassDefinitionMethods () { this.emitLine(") derives ReadWriter "); } - protected emitHeader(): void { + protected emitHeader (): void { super.emitHeader(); this.emitLine("import upickle.default.*"); @@ -486,7 +497,7 @@ export class UpickleRenderer extends Scala3Renderer { } export class Smithy4sRenderer extends Scala3Renderer { - protected emitHeader(): void { + protected emitHeader (): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } else { @@ -498,22 +509,22 @@ export class Smithy4sRenderer extends Scala3Renderer { this.ensureBlankLine(); } - protected emitTopLevelArray(t: ArrayType, name: Name): void { + protected emitTopLevelArray (t: ArrayType, name: Name): void { const elementType = this.scalaType(t.items); this.emitLine(["list ", name, " { member : ", elementType, "}"]); } - protected emitTopLevelMap(t: MapType, name: Name): void { + protected emitTopLevelMap (t: MapType, name: Name): void { const elementType = this.scalaType(t.values); this.emitLine(["map ", name, " { map[ key : String , value : ", elementType, "}"]); } - protected emitEmptyClassDefinition(c: ClassType, className: Name): void { + protected emitEmptyClassDefinition (c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); this.emitLine("structure ", className, "{}"); } - protected emitEnumDefinition(e: EnumType, enumName: Name): void { + protected emitEnumDefinition (e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); this.ensureBlankLine(); @@ -527,12 +538,12 @@ export class Smithy4sRenderer extends Scala3Renderer { !isNaN(parseInt(jsonName.charAt(0))) if (backticks) {this.emitItem("`")} else */ this.emitLine(); - this.emitItem([name, ' = "', jsonName, '"']); + this.emitItem([name, " = \"", jsonName, "\""]); // if (backticks) {this.emitItem("`")} if (--count > 0) this.emitItem([","]); - //} else { - //--count - //} + // } else { + // --count + // } }); this.ensureBlankLine(); this.emitItem(["}"]); @@ -540,9 +551,9 @@ export class Smithy4sRenderer extends Scala3Renderer { } export class CirceRenderer extends Scala3Renderer { - seenUnionTypes: Array = []; + seenUnionTypes: string[] = []; - protected circeEncoderForType(t: Type, _ = false, noOptional = false, paramName: string = ""): Sourcelike { + protected circeEncoderForType (t: Type, _ = false, noOptional = false, paramName: string = ""): Sourcelike { return matchType( t, _anyType => ["Encoder.encodeJson(", paramName, ")"], @@ -564,26 +575,27 @@ export class CirceRenderer extends Scala3Renderer { return ["Encoder.AsObject[Option[", this.nameForNamedType(nullable), "]]"]; } } + return ["Encoder.AsObject[", this.nameForNamedType(unionType), "]"]; - } + }, ); } - protected emitEmptyClassDefinition(c: ClassType, className: Name): void { + protected emitEmptyClassDefinition (c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); this.ensureBlankLine(); this.emitLine("case class ", className, "() derives Encoder.AsObject, Decoder"); } - protected anySourceType(optional: boolean): Sourcelike { + protected anySourceType (optional: boolean): Sourcelike { return [wrapOption("Json", optional)]; } - protected emitClassDefinitionMethods() { + protected emitClassDefinitionMethods () { this.emitLine(") derives Encoder.AsObject, Decoder"); } - protected emitEnumDefinition(e: EnumType, enumName: Name): void { + protected emitEnumDefinition (e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); this.ensureBlankLine(); @@ -596,17 +608,17 @@ export class CirceRenderer extends Scala3Renderer { jsonName.includes(" ") || !isNaN(parseInt(jsonName.charAt(0))) if (backticks) {this.emitItem("`")} else */ - this.emitItem(['"', jsonName, '"']); + this.emitItem(["\"", jsonName, "\""]); // if (backticks) {this.emitItem("`")} if (--count > 0) this.emitItem([" | "]); - //} else { - //--count - //} + // } else { + // --count + // } }); this.ensureBlankLine(); } - protected emitHeader(): void { + protected emitHeader (): void { super.emitHeader(); this.emitLine("import scala.util.Try"); @@ -617,17 +629,17 @@ export class CirceRenderer extends Scala3Renderer { this.emitLine("// For serialising string unions"); this.emitLine( - "given [A <: Singleton](using A <:< String): Decoder[A] = Decoder.decodeString.emapTry(x => Try(x.asInstanceOf[A])) " + "given [A <: Singleton](using A <:< String): Decoder[A] = Decoder.decodeString.emapTry(x => Try(x.asInstanceOf[A])) ", ); this.emitLine( - "given [A <: Singleton](using ev: A <:< String): Encoder[A] = Encoder.encodeString.contramap(ev) " + "given [A <: Singleton](using ev: A <:< String): Encoder[A] = Encoder.encodeString.contramap(ev) ", ); this.ensureBlankLine(); this.emitLine("// If a union has a null in, then we'll need this too... "); this.emitLine("type NullValue = None.type"); } - protected emitTopLevelArray(t: ArrayType, name: Name): void { + protected emitTopLevelArray (t: ArrayType, name: Name): void { super.emitTopLevelArray(t, name); const elementType = this.scalaType(t.items); this.emitLine([ @@ -637,11 +649,11 @@ export class CirceRenderer extends Scala3Renderer { elementType, "]] = Encoder.encodeMap[String, ", elementType, - "]" + "]", ]); } - protected emitTopLevelMap(t: MapType, name: Name): void { + protected emitTopLevelMap (t: MapType, name: Name): void { super.emitTopLevelMap(t, name); const elementType = this.scalaType(t.values); this.ensureBlankLine(); @@ -652,12 +664,12 @@ export class CirceRenderer extends Scala3Renderer { elementType, "]] = Encoder.encodeMap[String, ", elementType, - "]" + "]", ]); } - protected emitUnionDefinition(u: UnionType, unionName: Name): void { - function sortBy(t: Type): string { + protected emitUnionDefinition (u: UnionType, unionName: Name): void { + function sortBy (t: Type): string { const kind = t.kind; if (kind === "class") return kind; return "_" + kind; @@ -666,7 +678,7 @@ export class CirceRenderer extends Scala3Renderer { this.emitDescription(this.descriptionForType(u)); const [maybeNull, nonNulls] = removeNullFromUnion(u, sortBy); - const theTypes: Array = []; + const theTypes: Sourcelike[] = []; this.forEachUnionMember(u, nonNulls, "none", null, (_, t) => { theTypes.push(this.scalaType(t)); }); @@ -715,7 +727,7 @@ export class CirceRenderer extends Scala3Renderer { " : ", t[0], " => ", - this.circeEncoderForType(t[1], false, false, paramTemp) + this.circeEncoderForType(t[1], false, false, paramTemp), ]); }); }); @@ -725,25 +737,25 @@ export class CirceRenderer extends Scala3Renderer { } export class Scala3TargetLanguage extends TargetLanguage { - constructor() { + constructor () { super("Scala3", ["scala3"], "scala"); } - protected getOptions(): Option[] { + protected getOptions (): Array> { return [scala3Options.framework, scala3Options.packageName]; } - get supportsOptionalClassProperties(): boolean { + get supportsOptionalClassProperties (): boolean { return true; } - get supportsUnionsWithBothNumberTypes(): boolean { + get supportsUnionsWithBothNumberTypes (): boolean { return true; } - protected makeRenderer( + protected makeRenderer ( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } + untypedOptionValues: { [name: string]: any, }, ): ConvenienceRenderer { const options = getOptionValues(scala3Options, untypedOptionValues); diff --git a/packages/quicktype-core/src/language/Smithy4s.ts b/packages/quicktype-core/src/language/Smithy4s.ts index 3a875be64..8e794fbd5 100644 --- a/packages/quicktype-core/src/language/Smithy4s.ts +++ b/packages/quicktype-core/src/language/Smithy4s.ts @@ -1,8 +1,12 @@ import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { Name, Namer, funPrefixNamer } from "../Naming"; -import { EnumOption, Option, StringOption, OptionValues, getOptionValues } from "../RendererOptions"; -import { Sourcelike, maybeAnnotated } from "../Source"; +import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { ConvenienceRenderer } from "../ConvenienceRenderer"; +import { type Name, type Namer} from "../Naming"; +import { funPrefixNamer } from "../Naming"; +import { type Option, type OptionValues} from "../RendererOptions"; +import { EnumOption, StringOption, getOptionValues } from "../RendererOptions"; +import { type Sourcelike} from "../Source"; +import { maybeAnnotated } from "../Source"; import { allLowerWordStyle, allUpperWordStyle, @@ -12,13 +16,14 @@ import { isLetterOrUnderscore, isNumeric, legalizeCharacters, - splitIntoWords + splitIntoWords, } from "../support/Strings"; import { assertNever } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; -import { ArrayType, ClassProperty, ClassType, EnumType, MapType, ObjectType, Type, UnionType } from "../Type"; +import { type ClassProperty, type ClassType, type EnumType, type ObjectType, type Type, type UnionType } from "../Type"; +import { ArrayType, MapType } from "../Type"; import { matchCompoundType, matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { RenderContext } from "../Renderer"; +import { type RenderContext } from "../Renderer"; export enum Framework { None @@ -26,7 +31,7 @@ export enum Framework { export const SmithyOptions = { framework: new EnumOption("framework", "Serialization framework", [["just-types", Framework.None]], undefined), - packageName: new StringOption("package", "Package", "PACKAGE", "quicktype") + packageName: new StringOption("package", "Package", "PACKAGE", "quicktype"), }; // Use backticks for param names with symbols @@ -48,13 +53,13 @@ const invalidSymbols = [ "/", ";", "'", - '"', + "\"", "{", "}", ":", "~", "`", - "." + ".", ]; const keywords = [ @@ -104,7 +109,7 @@ const keywords = [ "Array", "List", "Map", - "Enum" + "Enum", ]; /** @@ -120,17 +125,17 @@ const shouldAddBacktick = (paramName: string): boolean => { ); }; -function isPartCharacter(codePoint: number): boolean { +function isPartCharacter (codePoint: number): boolean { return isLetterOrUnderscore(codePoint) || isNumeric(codePoint); } -function isStartCharacter(codePoint: number): boolean { +function isStartCharacter (codePoint: number): boolean { return isPartCharacter(codePoint) && !isDigit(codePoint); } const legalizeName = legalizeCharacters(isPartCharacter); -function scalaNameStyle(isUpper: boolean, original: string): string { +function scalaNameStyle (isUpper: boolean, original: string): string { const words = splitIntoWords(original); return combineWords( words, @@ -140,7 +145,7 @@ function scalaNameStyle(isUpper: boolean, original: string): string { isUpper ? allUpperWordStyle : allLowerWordStyle, allUpperWordStyle, "", - isStartCharacter + isStartCharacter, ); } @@ -148,100 +153,100 @@ const upperNamingFunction = funPrefixNamer("upper", s => scalaNameStyle(true, s) const lowerNamingFunction = funPrefixNamer("lower", s => scalaNameStyle(false, s)); export class Smithy4sRenderer extends ConvenienceRenderer { - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - protected readonly _scalaOptions: OptionValues + protected readonly _scalaOptions: OptionValues, ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace (): string[] { return keywords; } - protected forbiddenForObjectProperties(_: ObjectType, _classNamed: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties (_: ObjectType, _classNamed: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForEnumCases(_: EnumType, _enumName: Name): ForbiddenWordsInfo { + protected forbiddenForEnumCases (_: EnumType, _enumName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { + protected forbiddenForUnionMembers (_u: UnionType, _unionName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: false }; } - protected topLevelNameStyle(rawName: string): string { + protected topLevelNameStyle (rawName: string): string { return scalaNameStyle(true, rawName); } - protected makeNamedTypeNamer(): Namer { + protected makeNamedTypeNamer (): Namer { return upperNamingFunction; } - protected namerForObjectProperty(): Namer { + protected namerForObjectProperty (): Namer { return lowerNamingFunction; } - protected makeUnionMemberNamer(): Namer { + protected makeUnionMemberNamer (): Namer { return funPrefixNamer("upper", s => scalaNameStyle(true, s) + "Value"); } - protected makeEnumCaseNamer(): Namer { + protected makeEnumCaseNamer (): Namer { return funPrefixNamer("upper", s => s.replace(" ", "")); // TODO - add backticks where appropriate } - protected emitDescriptionBlock(lines: Sourcelike[]): void { + protected emitDescriptionBlock (lines: Sourcelike[]): void { this.emitCommentLines(lines, { lineStart: " * ", beforeComment: "/**", afterComment: " */" }); } - protected emitBlock( + protected emitBlock ( line: Sourcelike, f: () => void, - delimiter: "curly" | "paren" | "lambda" | "none" = "curly" + delimiter: "curly" | "paren" | "lambda" | "none" = "curly", ): void { const [open, close] = delimiter === "curly" ? ["{", "}"] : delimiter === "paren" - ? ["(", ")"] - : delimiter === "none" - ? ["", ""] - : ["{", "})"]; + ? ["(", ")"] + : delimiter === "none" + ? ["", ""] + : ["{", "})"]; this.emitLine(line, " ", open); this.indent(f); this.emitLine(close); } - protected anySourceType(_: boolean): Sourcelike { + protected anySourceType (_: boolean): Sourcelike { return ["Document"]; } // (asarazan): I've broken out the following two functions // because some renderers, such as kotlinx, can cope with `any`, while some get mad. - protected arrayType(arrayType: ArrayType, _ = false): Sourcelike { - //this.emitTopLevelArray(arrayType, new Name(arrayType.getCombinedName().toString() + "List")) + protected arrayType (arrayType: ArrayType, _ = false): Sourcelike { + // this.emitTopLevelArray(arrayType, new Name(arrayType.getCombinedName().toString() + "List")) return arrayType.getCombinedName().toString() + "List"; } - protected emitArrayType(_: ArrayType, smithyType: Sourcelike): void { + protected emitArrayType (_: ArrayType, smithyType: Sourcelike): void { this.emitLine(["list ", smithyType, " { member : ", "}"]); } - protected mapType(mapType: MapType, _ = false): Sourcelike { + protected mapType (mapType: MapType, _ = false): Sourcelike { return mapType.getCombinedName().toString() + "Map"; - //return [this.scalaType(mapType.values, withIssues), "Map"]; + // return [this.scalaType(mapType.values, withIssues), "Map"]; } - protected scalaType(t: Type, withIssues = false, noOptional = false): Sourcelike { + protected scalaType (t: Type, withIssues = false, noOptional = false): Sourcelike { return matchType( t, _anyType => { return maybeAnnotated(withIssues, anyTypeIssueAnnotation, this.anySourceType(!noOptional)); }, _nullType => { - //return "None.type" + // return "None.type" return maybeAnnotated(withIssues, nullTypeIssueAnnotation, this.anySourceType(!noOptional)); }, _boolType => "Boolean", @@ -257,16 +262,17 @@ export class Smithy4sRenderer extends ConvenienceRenderer { if (nullable !== null) { return [this.scalaType(nullable, withIssues)]; } + return this.nameForNamedType(unionType); - } + }, ); } - protected emitUsageHeader(): void { + protected emitUsageHeader (): void { // To be overridden } - protected emitHeader(): void { + protected emitHeader (): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } else { @@ -274,7 +280,7 @@ export class Smithy4sRenderer extends ConvenienceRenderer { } this.ensureBlankLine(); - this.emitLine('$version: "2"'); + this.emitLine("$version: \"2\""); this.emitLine("namespace ", this._scalaOptions.packageName); this.ensureBlankLine(); @@ -282,22 +288,22 @@ export class Smithy4sRenderer extends ConvenienceRenderer { this.ensureBlankLine(); } - protected emitTopLevelArray(t: ArrayType, name: Name): void { + protected emitTopLevelArray (t: ArrayType, name: Name): void { const elementType = this.scalaType(t.items); this.emitLine(["list ", name, " { member : ", elementType, "}"]); } - protected emitTopLevelMap(t: MapType, name: Name): void { + protected emitTopLevelMap (t: MapType, name: Name): void { const elementType = this.scalaType(t.values); this.emitLine(["map ", name, " { map[ key : String , value : ", elementType, "}"]); } - protected emitEmptyClassDefinition(c: ClassType, className: Name): void { + protected emitEmptyClassDefinition (c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); this.emitLine("structure ", className, "{}"); } - protected emitClassDefinition(c: ClassType, className: Name): void { + protected emitClassDefinition (c: ClassType, className: Name): void { if (c.getProperties().size === 0) { this.emitEmptyClassDefinition(c, className); return; @@ -311,7 +317,7 @@ export class Smithy4sRenderer extends ConvenienceRenderer { } }; - const emitLater: Array = []; + const emitLater: ClassProperty[] = []; this.emitDescription(this.descriptionForType(c)); this.emitLine("structure ", className, " {"); @@ -342,6 +348,7 @@ export class Smithy4sRenderer extends ConvenienceRenderer { for (const emit of meta) { emit(); } + const nameNeedsBackticks = jsonName.endsWith("_") || shouldAddBacktick(jsonName); const nameWithBackticks = nameNeedsBackticks ? "`" + jsonName + "`" : jsonName; this.emitLine( @@ -350,7 +357,7 @@ export class Smithy4sRenderer extends ConvenienceRenderer { " : ", scalaType(p), - last ? "" : "," + last ? "" : ",", ); if (meta.length > 0 && !last) { @@ -363,12 +370,13 @@ export class Smithy4sRenderer extends ConvenienceRenderer { this.emitClassDefinitionMethods(emitLater); } - protected emitClassDefinitionMethods(arrayTypes: ClassProperty[]) { + protected emitClassDefinitionMethods (arrayTypes: ClassProperty[]) { this.emitLine("}"); arrayTypes.forEach(p => { - function ignore(_: T): void { + function ignore (_: T): void { return; } + matchCompoundType( p.type, at => { @@ -377,7 +385,7 @@ export class Smithy4sRenderer extends ConvenienceRenderer { this.scalaType(at, true), "{ member: ", this.scalaType(at.items, true), - "}" + "}", ]); }, ignore, @@ -387,16 +395,16 @@ export class Smithy4sRenderer extends ConvenienceRenderer { this.scalaType(mt, true), "{ key: String , value: ", this.scalaType(mt.values, true), - "}" + "}", ]); }, ignore, - ignore + ignore, ); }); } - protected emitEnumDefinition(e: EnumType, enumName: Name): void { + protected emitEnumDefinition (e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); this.ensureBlankLine(); @@ -412,37 +420,38 @@ export class Smithy4sRenderer extends ConvenienceRenderer { if (backticks) {this.emitItem("`")} else */ this.emitLine(); - this.emitItem([name, ' = "', jsonName, '"']); + this.emitItem([name, " = \"", jsonName, "\""]); // if (backticks) {this.emitItem("`")} if (--count > 0) this.emitItem([","]); - //} else { - //--count - //} + // } else { + // --count + // } }); this.ensureBlankLine(); this.emitItem(["}"]); } - protected emitUnionDefinition(u: UnionType, unionName: Name): void { - function sortBy(t: Type): string { + protected emitUnionDefinition (u: UnionType, unionName: Name): void { + function sortBy (t: Type): string { const kind = t.kind; if (kind === "class") return kind; return "_" + kind; } - const emitLater: Array = []; + const emitLater: Type[] = []; this.emitDescription(this.descriptionForType(u)); const [maybeNull, nonNulls] = removeNullFromUnion(u, sortBy); - const theTypes: Array = []; + const theTypes: Sourcelike[] = []; this.forEachUnionMember(u, nonNulls, "none", null, (_, t) => { const laterType = t.kind === "array" || t.kind === "map"; if (laterType) { emitLater.push(t); } + theTypes.push(this.scalaType(t)); }); if (maybeNull !== null) { @@ -459,9 +468,10 @@ export class Smithy4sRenderer extends ConvenienceRenderer { this.ensureBlankLine(); emitLater.forEach(p => { - function ignore(_: T): void { + function ignore (_: T): void { return; } + matchCompoundType( p, at => { @@ -470,7 +480,7 @@ export class Smithy4sRenderer extends ConvenienceRenderer { this.scalaType(at, true), "{ member: ", this.scalaType(at.items, true), - "}" + "}", ]); }, ignore, @@ -480,16 +490,16 @@ export class Smithy4sRenderer extends ConvenienceRenderer { this.scalaType(mt, true), "{ key: String , value: ", this.scalaType(mt.values, true), - "}" + "}", ]); }, ignore, - ignore + ignore, ); }); } - protected emitSourceStructure(): void { + protected emitSourceStructure (): void { this.emitHeader(); // Top-level arrays, maps @@ -505,31 +515,31 @@ export class Smithy4sRenderer extends ConvenienceRenderer { "leading-and-interposing", (c: ClassType, n: Name) => this.emitClassDefinition(c, n), (e, n) => this.emitEnumDefinition(e, n), - (u, n) => this.emitUnionDefinition(u, n) + (u, n) => this.emitUnionDefinition(u, n), ); } } export class SmithyTargetLanguage extends TargetLanguage { - constructor() { + constructor () { super("Smithy", ["Smithy"], "smithy"); } - protected getOptions(): Option[] { + protected getOptions (): Array> { return [SmithyOptions.framework, SmithyOptions.packageName]; } - get supportsOptionalClassProperties(): boolean { + get supportsOptionalClassProperties (): boolean { return true; } - get supportsUnionsWithBothNumberTypes(): boolean { + get supportsUnionsWithBothNumberTypes (): boolean { return true; } - protected makeRenderer( + protected makeRenderer ( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } + untypedOptionValues: { [name: string]: any, }, ): ConvenienceRenderer { const options = getOptionValues(SmithyOptions, untypedOptionValues); diff --git a/packages/quicktype-core/src/language/Swift.ts b/packages/quicktype-core/src/language/Swift.ts index 04fc431a1..bc8cd35ca 100644 --- a/packages/quicktype-core/src/language/Swift.ts +++ b/packages/quicktype-core/src/language/Swift.ts @@ -3,23 +3,29 @@ import { assert, defined } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; import { - Type, - ClassType, + type Type, + type ClassType, + type UnionType, + type TypeKind, + type ClassProperty, + type TransformedStringTypeKind, + type PrimitiveStringTypeKind, +} from "../Type"; +import { EnumType, - UnionType, ArrayType, MapType, - TypeKind, - ClassProperty, - TransformedStringTypeKind, - PrimitiveStringTypeKind } from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { Name, Namer, funPrefixNamer } from "../Naming"; -import { BooleanOption, EnumOption, Option, StringOption, OptionValues, getOptionValues } from "../RendererOptions"; -import { Sourcelike, maybeAnnotated, modifySource } from "../Source"; +import { type Name, type Namer} from "../Naming"; +import { funPrefixNamer } from "../Naming"; +import { type Option, type OptionValues} from "../RendererOptions"; +import { BooleanOption, EnumOption, StringOption, getOptionValues } from "../RendererOptions"; +import { type Sourcelike} from "../Source"; +import { maybeAnnotated, modifySource } from "../Source"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { ConvenienceRenderer } from "../ConvenienceRenderer"; import { legalizeCharacters, isLetterOrUnderscore, @@ -35,12 +41,13 @@ import { allLowerWordStyle, allUpperWordStyle, camelCase, - addPrefixIfNecessary + addPrefixIfNecessary, } from "../support/Strings"; -import { RenderContext, ForEachPosition } from "../Renderer"; -import { StringTypeMapping } from "../TypeBuilder"; +import { type RenderContext, type ForEachPosition } from "../Renderer"; +import { type StringTypeMapping } from "../TypeBuilder"; import { panic } from "../support/Support"; -import { DefaultDateTimeRecognizer, DateTimeRecognizer } from "../DateTime"; +import { type DateTimeRecognizer } from "../DateTime"; +import { DefaultDateTimeRecognizer } from "../DateTime"; import { acronymOption, acronymStyle, AcronymStyleOptions } from "../support/Acronyms"; const MAX_SAMELINE_PROPERTIES = 4; @@ -53,7 +60,7 @@ export const swiftOptions = { namedTypePrefix: new StringOption("type-prefix", "Prefix for type names", "PREFIX", "", "secondary"), useClasses: new EnumOption("struct-or-class", "Structs or classes", [ ["struct", false], - ["class", true] + ["class", true], ]), mutableProperties: new BooleanOption("mutable-properties", "Use var instead of let for object properties", false), acronymStyle: acronymOption(AcronymStyleOptions.Pascal), @@ -62,16 +69,16 @@ export const swiftOptions = { "Code density", [ ["dense", true], - ["normal", false] + ["normal", false], ], "dense", - "secondary" + "secondary", ), linux: new BooleanOption("support-linux", "Support Linux", false, "secondary"), objcSupport: new BooleanOption( "objective-c-support", "Objects inherit from NSObject and @objcMembers is added to classes", - false + false, ), optionalEnums: new BooleanOption("optional-enums", "If no matching case is found enum value is set to null", false), swift5Support: new BooleanOption("swift-5-support", "Renders output in a Swift 5 compatible mode", false), @@ -79,17 +86,17 @@ export const swiftOptions = { multiFileOutput: new BooleanOption( "multi-file-output", "Renders each top-level object in its own Swift file", - false + false, ), accessLevel: new EnumOption( "access-level", "Access level", [ ["internal", "internal"], - ["public", "public"] + ["public", "public"], ], "internal", - "secondary" + "secondary", ), protocol: new EnumOption( "protocol", @@ -97,11 +104,11 @@ export const swiftOptions = { [ ["none", { equatable: false, hashable: false }], ["equatable", { equatable: true, hashable: false }], - ["hashable", { equatable: false, hashable: true }] + ["hashable", { equatable: false, hashable: true }], ], "none", - "secondary" - ) + "secondary", + ), }; // These are all recognized by Swift as ISO8601 date-times: @@ -118,24 +125,24 @@ export const swiftOptions = { const swiftDateTimeRegex = /^\d+-\d+-\d+T\d+:\d+:\d+([zZ]|[+-]\d+(:\d+)?)$/; class SwiftDateTimeRecognizer extends DefaultDateTimeRecognizer { - isDateTime(str: string): boolean { - return str.match(swiftDateTimeRegex) !== null; + isDateTime (str: string): boolean { + return swiftDateTimeRegex.exec(str) !== null; } } export interface SwiftProperty { - name: Name; jsonName: string; + name: Name; parameter: ClassProperty; position: ForEachPosition; } export class SwiftTargetLanguage extends TargetLanguage { - constructor() { + constructor () { super("Swift", ["swift", "swift4"], "swift"); } - protected getOptions(): Option[] { + protected getOptions (): Array> { return [ swiftOptions.justTypes, swiftOptions.useClasses, @@ -153,29 +160,29 @@ export class SwiftTargetLanguage extends TargetLanguage { swiftOptions.sendable, swiftOptions.swift5Support, swiftOptions.multiFileOutput, - swiftOptions.mutableProperties + swiftOptions.mutableProperties, ]; } - get stringTypeMapping(): StringTypeMapping { + get stringTypeMapping (): StringTypeMapping { const mapping: Map = new Map(); mapping.set("date-time", "date-time"); return mapping; } - get supportsOptionalClassProperties(): boolean { + get supportsOptionalClassProperties (): boolean { return true; } - get supportsUnionsWithBothNumberTypes(): boolean { + get supportsUnionsWithBothNumberTypes (): boolean { return true; } - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): SwiftRenderer { + protected makeRenderer (renderContext: RenderContext, untypedOptionValues: { [name: string]: any, }): SwiftRenderer { return new SwiftRenderer(this, renderContext, getOptionValues(swiftOptions, untypedOptionValues)); } - get dateTimeRecognizer(): DateTimeRecognizer { + get dateTimeRecognizer (): DateTimeRecognizer { return new SwiftDateTimeRecognizer(); } } @@ -279,24 +286,24 @@ const keywords = [ "convertDict", "convertDouble", "jsonString", - "jsonData" + "jsonData", ]; -function isPartCharacter(codePoint: number): boolean { +function isPartCharacter (codePoint: number): boolean { return isLetterOrUnderscore(codePoint) || isNumeric(codePoint); } -function isStartCharacter(codePoint: number): boolean { +function isStartCharacter (codePoint: number): boolean { return isPartCharacter(codePoint) && !isDigit(codePoint); } const legalizeName = legalizeCharacters(isPartCharacter); -function swiftNameStyle( +function swiftNameStyle ( prefix: string, isUpper: boolean, original: string, - acronymsStyle: (s: string) => string = allUpperWordStyle + acronymsStyle: (s: string) => string = allUpperWordStyle, ): string { const words = splitIntoWords(original); const combined = combineWords( @@ -307,12 +314,12 @@ function swiftNameStyle( isUpper ? allUpperWordStyle : allLowerWordStyle, acronymsStyle, "", - isStartCharacter + isStartCharacter, ); return addPrefixIfNecessary(prefix, combined); } -function unicodeEscape(codePoint: number): string { +function unicodeEscape (codePoint: number): string { return "\\u{" + intToHex(codePoint, 0) + "}"; } @@ -320,91 +327,94 @@ const stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, unicod export class SwiftRenderer extends ConvenienceRenderer { private _currentFilename: string | undefined; + private _needAny = false; + private _needNull = false; - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues + private readonly _options: OptionValues, ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace (): string[] { if (this._options.alamofire) { return ["DataRequest", ...keywords]; } + return keywords; } - protected forbiddenForObjectProperties(_c: ClassType, _classNamed: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties (_c: ClassType, _classNamed: Name): ForbiddenWordsInfo { return { names: ["fromURL", "json"], includeGlobalForbidden: true }; } - protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { + protected forbiddenForEnumCases (_e: EnumType, _enumName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { + protected forbiddenForUnionMembers (_u: UnionType, _unionName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected makeNamedTypeNamer(): Namer { + protected makeNamedTypeNamer (): Namer { return funPrefixNamer("upper", s => - swiftNameStyle(this._options.namedTypePrefix, true, s, acronymStyle(this._options.acronymStyle)) + swiftNameStyle(this._options.namedTypePrefix, true, s, acronymStyle(this._options.acronymStyle)), ); } - protected namerForObjectProperty(): Namer { + protected namerForObjectProperty (): Namer { return this.lowerNamingFunction; } - protected makeUnionMemberNamer(): Namer { + protected makeUnionMemberNamer (): Namer { return this.lowerNamingFunction; } - protected makeEnumCaseNamer(): Namer { + protected makeEnumCaseNamer (): Namer { return this.lowerNamingFunction; } - protected isImplicitCycleBreaker(t: Type): boolean { + protected isImplicitCycleBreaker (t: Type): boolean { const kind = t.kind; return kind === "array" || kind === "map"; } - protected emitDescriptionBlock(lines: Sourcelike[]): void { + protected emitDescriptionBlock (lines: Sourcelike[]): void { this.emitCommentLines(lines, { lineStart: "/// " }); } - private emitBlock(line: Sourcelike, f: () => void): void { + private emitBlock (line: Sourcelike, f: () => void): void { this.emitLine(line, " {"); this.indent(f); this.emitLine("}"); } - private emitBlockWithAccess(line: Sourcelike, f: () => void): void { + private emitBlockWithAccess (line: Sourcelike, f: () => void): void { this.emitBlock([this.accessLevel, line], f); } - private justTypesCase(justTypes: Sourcelike, notJustTypes: Sourcelike): Sourcelike { + private justTypesCase (justTypes: Sourcelike, notJustTypes: Sourcelike): Sourcelike { if (this._options.justTypes) return justTypes; else return notJustTypes; } - private get lowerNamingFunction() { + private get lowerNamingFunction () { return funPrefixNamer("lower", s => swiftNameStyle("", false, s, acronymStyle(this._options.acronymStyle))); } - protected swiftPropertyType(p: ClassProperty): Sourcelike { - if (p.isOptional || (this._options.optionalEnums && p.type.kind === "enum")) { + protected swiftPropertyType (p: ClassProperty): Sourcelike { + if (p.isOptional || this._options.optionalEnums && p.type.kind === "enum") { return [this.swiftType(p.type, true, true), "?"]; } else { return this.swiftType(p.type, true); } } - protected swiftType(t: Type, withIssues = false, noOptional = false): Sourcelike { + protected swiftType (t: Type, withIssues = false, noOptional = false): Sourcelike { const optional = noOptional ? "" : "?"; return matchType( t, @@ -413,7 +423,7 @@ export class SwiftRenderer extends ConvenienceRenderer { return maybeAnnotated( withIssues, anyTypeIssueAnnotation, - this.justTypesCase(["Any", optional], "JSONAny") + this.justTypesCase(["Any", optional], "JSONAny"), ); }, _nullType => { @@ -421,7 +431,7 @@ export class SwiftRenderer extends ConvenienceRenderer { return maybeAnnotated( withIssues, nullTypeIssueAnnotation, - this.justTypesCase("NSNull", ["JSONNull", optional]) + this.justTypesCase("NSNull", ["JSONNull", optional]), ); }, _boolType => "Bool", @@ -443,21 +453,23 @@ export class SwiftRenderer extends ConvenienceRenderer { } else { return panic(`Transformed string type ${transformedStringType.kind} not supported`); } - } + }, ); } - protected proposedUnionMemberNameForTypeKind(kind: TypeKind): string | null { + protected proposedUnionMemberNameForTypeKind (kind: TypeKind): string | null { if (kind === "enum") { return "enumeration"; } + if (kind === "union") { return "one_of"; } + return null; } - private renderSingleFileHeaderComments(): void { + private renderSingleFileHeaderComments (): void { this.emitLineOnce("// This file was generated from JSON Schema using quicktype, do not modify it directly."); this.emitLineOnce("// To parse the JSON, add this file to your project and do:"); this.emitLineOnce("//"); @@ -468,7 +480,7 @@ export class SwiftRenderer extends ConvenienceRenderer { modifySource(camelCase, topLevelName), " = try ", topLevelName, - "(json)" + "(json)", ); } else { this.emitLineOnce( @@ -477,19 +489,19 @@ export class SwiftRenderer extends ConvenienceRenderer { " = ", "try? JSONDecoder().decode(", topLevelName, - ".self, from: jsonData)" + ".self, from: jsonData)", ); } }); } - private renderHeader(type: Type, name: Name): void { + private renderHeader (type: Type, name: Name): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } else if (!this._options.justTypes) { if (this._options.multiFileOutput) { this.emitLineOnce( - "// This file was generated from JSON Schema using quicktype, do not modify it directly." + "// This file was generated from JSON Schema using quicktype, do not modify it directly.", ); this.emitLineOnce("// To parse the JSON, add this file to your project and do:"); this.emitLineOnce("//"); @@ -502,7 +514,7 @@ export class SwiftRenderer extends ConvenienceRenderer { " = ", "try? newJSONDecoder().decode(", name, - ".self, from: jsonData)" + ".self, from: jsonData)", ); } } @@ -522,30 +534,33 @@ export class SwiftRenderer extends ConvenienceRenderer { this.emitLine("//"); this.emitLine("// Hashable or Equatable:"); this.emitLine( - "// The compiler will not be able to synthesize the implementation of Hashable or Equatable" + "// The compiler will not be able to synthesize the implementation of Hashable or Equatable", ); this.emitLine( - "// for types that require the use of JSONAny, nor will the implementation of Hashable be" + "// for types that require the use of JSONAny, nor will the implementation of Hashable be", ); this.emitLine("// synthesized for types that have collections (such as arrays or dictionaries)."); } } + this.ensureBlankLine(); this.emitLineOnce("import Foundation"); if (!this._options.justTypes && this._options.alamofire) { this.emitLineOnce("import Alamofire"); } + if (this._options.optionalEnums) { this.emitLineOnce("import OptionallyDecodable // https://github.com/idrougge/OptionallyDecodable"); } + this.ensureBlankLine(); } - private renderTopLevelAlias(t: Type, name: Name): void { + private renderTopLevelAlias (t: Type, name: Name): void { this.emitLine(this.accessLevel, "typealias ", name, " = ", this.swiftType(t, true)); } - protected getProtocolsArray(kind: "struct" | "class" | "enum"): string[] { + protected getProtocolsArray (kind: "struct" | "class" | "enum"): string[] { const protocols: string[] = []; // [Michael Fey (@MrRooni), 2019-4-24] Technically NSObject isn't a "protocol" in this instance, but this felt like the best place to slot in this superclass declaration. @@ -574,19 +589,20 @@ export class SwiftRenderer extends ConvenienceRenderer { return protocols; } - private getProtocolString( + private getProtocolString ( kind: "struct" | "class" | "enum", - baseClass: string | undefined = undefined + baseClass: string | undefined = undefined, ): Sourcelike { let protocols = this.getProtocolsArray(kind); if (baseClass) { protocols.unshift(baseClass); } + return protocols.length > 0 ? ": " + protocols.join(", ") : ""; } - private getEnumPropertyGroups(c: ClassType) { - type PropertyGroup = { name: Name; label?: string }[]; + private getEnumPropertyGroups (c: ClassType) { + type PropertyGroup = Array<{ label?: string, name: Name, }>; let groups: PropertyGroup[] = []; let group: PropertyGroup = []; @@ -602,6 +618,7 @@ export class SwiftRenderer extends ConvenienceRenderer { groups.push(group); group = []; } + groups.push([{ name, label }]); } }); @@ -614,13 +631,13 @@ export class SwiftRenderer extends ConvenienceRenderer { } /// Access level with trailing space (e.g. "public "), or empty string - private get accessLevel(): string { + private get accessLevel (): string { return this._options.accessLevel === "internal" ? "" // internal is default, so we don't have to emit it : this._options.accessLevel + " "; } - private get objcMembersDeclaration(): string { + private get objcMembersDeclaration (): string { if (this._options.objcSupport) { return "@objcMembers "; } @@ -629,7 +646,7 @@ export class SwiftRenderer extends ConvenienceRenderer { } /// startFile takes a file name, appends ".swift" to it and sets it as the current filename. - protected startFile(basename: Sourcelike): void { + protected startFile (basename: Sourcelike): void { if (this._options.multiFileOutput === false) { return; } @@ -641,7 +658,7 @@ export class SwiftRenderer extends ConvenienceRenderer { } /// endFile pushes the current file name onto the collection of finished files and then resets the current file name. These finished files are used in index.ts to write the output. - protected endFile(): void { + protected endFile (): void { if (this._options.multiFileOutput === false) { return; } @@ -650,18 +667,18 @@ export class SwiftRenderer extends ConvenienceRenderer { this._currentFilename = undefined; } - protected propertyLinesDefinition(name: Name, parameter: ClassProperty): Sourcelike { + protected propertyLinesDefinition (name: Name, parameter: ClassProperty): Sourcelike { const useMutableProperties = this._options.mutableProperties; return [ this.accessLevel, useMutableProperties ? "var " : "let ", name, ": ", - this.swiftPropertyType(parameter) + this.swiftPropertyType(parameter), ]; } - private renderClassDefinition(c: ClassType, className: Name): void { + private renderClassDefinition (c: ClassType, className: Name): void { this.startFile(className); this.renderHeader(c, className); @@ -690,13 +707,13 @@ export class SwiftRenderer extends ConvenienceRenderer { let sources: Sourcelike[] = [ [ this._options.optionalEnums && lastProperty.type.kind === "enum" - ? `@OptionallyDecodable ` + ? "@OptionallyDecodable " : "", this.accessLevel, - useMutableProperties || (this._options.optionalEnums && lastProperty.type.kind === "enum") + useMutableProperties || this._options.optionalEnums && lastProperty.type.kind === "enum" ? "var " - : "let " - ] + : "let ", + ], ]; lastNames.forEach((n, i) => { if (i > 0) sources.push(", "); @@ -719,9 +736,11 @@ export class SwiftRenderer extends ConvenienceRenderer { ) { emitLastProperty(); } + if (lastProperty === undefined) { lastProperty = p; } + lastNames.push(name); if (description !== undefined) { this.emitDescription(description); @@ -749,11 +768,11 @@ export class SwiftRenderer extends ConvenienceRenderer { for (const group of groups) { const { name, label } = group[0]; if (this._options.explicitCodingKeys && label !== undefined) { - this.emitLine("case ", name, ' = "', label, '"'); + this.emitLine("case ", name, " = \"", label, "\""); } else { const names = arrayIntercalate( ", ", - group.map(p => p.name) + group.map(p => p.name), ); this.emitLine("case ", names); } @@ -778,6 +797,7 @@ export class SwiftRenderer extends ConvenienceRenderer { if (propertiesLines.length > 0) propertiesLines.push(", "); propertiesLines.push(property.name, ": ", this.swiftPropertyType(property.parameter)); } + if (this.propertyCount(c) === 0 && this._options.objcSupport) { this.emitBlockWithAccess(["override init()"], () => { return ""; @@ -806,7 +826,7 @@ export class SwiftRenderer extends ConvenienceRenderer { this.endFile(); } - protected initializableProperties(c: ClassType): SwiftProperty[] { + protected initializableProperties (c: ClassType): SwiftProperty[] { const properties: SwiftProperty[] = []; this.forEachClassProperty(c, "none", (name, jsonName, parameter, position) => { const property = { name, jsonName, parameter, position }; @@ -815,7 +835,7 @@ export class SwiftRenderer extends ConvenienceRenderer { return properties; } - private emitNewEncoderDecoder(): void { + private emitNewEncoderDecoder (): void { this.emitBlock("func newJSONDecoder() -> JSONDecoder", () => { this.emitLine("let decoder = JSONDecoder()"); if (!this._options.linux) { @@ -842,6 +862,7 @@ export class SwiftRenderer extends ConvenienceRenderer { throw DecodingError.typeMismatch(Date.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Could not decode date")) })`); } + this.emitLine("return decoder"); }); this.ensureBlankLine(); @@ -859,11 +880,12 @@ formatter.timeZone = TimeZone(secondsFromGMT: 0) formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXXXX" encoder.dateEncodingStrategy = .formatted(formatter)`); } + this.emitLine("return encoder"); }); } - private emitConvenienceInitializersExtension(c: ClassType, className: Name): void { + private emitConvenienceInitializersExtension (c: ClassType, className: Name): void { const isClass = this._options.useClasses || this.isCycleBreakerType(c); const convenience = isClass ? "convenience " : ""; @@ -875,6 +897,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); } else { this.emitLine("let _ = try newJSONDecoder().decode(", this.swiftType(c), ".self, from: data)"); } + let args: Sourcelike[] = []; this.forEachClassProperty(c, "none", name => { if (args.length > 0) args.push(", "); @@ -887,18 +910,19 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); this.emitLine("self = try newJSONDecoder().decode(", this.swiftType(c), ".self, from: data)"); }); } + this.ensureBlankLine(); this.emitBlock( [convenience, "init(_ json: String, using encoding: String.Encoding = .utf8) throws"], () => { this.emitBlock("guard let data = json.data(using: encoding) else", () => { - this.emitLine(`throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)`); + this.emitLine("throw NSError(domain: \"JSONDecoding\", code: 0, userInfo: nil)"); }); this.emitLine("try self.init(data: data)"); - } + }, ); this.ensureBlankLine(); - this.emitBlock([convenience, `init(fromURL url: URL) throws`], () => { + this.emitBlock([convenience, "init(fromURL url: URL) throws"], () => { this.emitLine("try self.init(data: try Data(contentsOf: url))"); }); @@ -907,17 +931,17 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); // Convenience serializers this.ensureBlankLine(); - this.emitBlock(`func jsonData() throws -> Data`, () => { + this.emitBlock("func jsonData() throws -> Data", () => { this.emitLine("return try newJSONEncoder().encode(self)"); }); this.ensureBlankLine(); - this.emitBlock(`func jsonString(encoding: String.Encoding = .utf8) throws -> String?`, () => { + this.emitBlock("func jsonString(encoding: String.Encoding = .utf8) throws -> String?", () => { this.emitLine("return String(data: try self.jsonData(), encoding: encoding)"); }); }); } - private renderEnumDefinition(e: EnumType, enumName: Name): void { + private renderEnumDefinition (e: EnumType, enumName: Name): void { this.startFile(enumName); this.emitLineOnce("import Foundation"); @@ -935,7 +959,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); } else { this.emitBlockWithAccess(["enum ", enumName, protocolString], () => { this.forEachEnumCase(e, "none", (name, jsonName) => { - this.emitLine("case ", name, ' = "', stringEscape(jsonName), '"'); + this.emitLine("case ", name, " = \"", stringEscape(jsonName), "\""); }); }); } @@ -943,13 +967,13 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); this.endFile(); } - private renderUnionDefinition(u: UnionType, unionName: Name): void { + private renderUnionDefinition (u: UnionType, unionName: Name): void { this.startFile(unionName); this.emitLineOnce("import Foundation"); this.ensureBlankLine(); - function sortBy(t: Type): string { + function sortBy (t: Type): string { const kind = t.kind; if (kind === "class") return kind; return "_" + kind; @@ -986,12 +1010,14 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); if (t.kind === "bool" || t.kind === "integer") continue; renderUnionCase(t); } + if (maybeNull !== null) { this.emitBlock("if container.decodeNil()", () => { this.emitLine("self = .", this.nameForUnionMember(u, maybeNull)); this.emitLine("return"); }); } + this.emitDecodingError(unionName); }); this.ensureBlankLine(); @@ -1006,6 +1032,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); this.emitLine("case .", this.nameForUnionMember(u, maybeNull), ":"); this.indent(() => this.emitLine("try container.encodeNil()")); } + this.emitLine("}"); }); } @@ -1013,7 +1040,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); this.endFile(); } - private emitTopLevelMapAndArrayConvenienceInitializerExtensions(t: Type, name: Name): void { + private emitTopLevelMapAndArrayConvenienceInitializerExtensions (t: Type, name: Name): void { let extensionSource: Sourcelike; if (t instanceof ArrayType) { @@ -1031,12 +1058,12 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); this.ensureBlankLine(); this.emitBlock("init(_ json: String, using encoding: String.Encoding = .utf8) throws", () => { this.emitBlock("guard let data = json.data(using: encoding) else", () => { - this.emitLine(`throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)`); + this.emitLine("throw NSError(domain: \"JSONDecoding\", code: 0, userInfo: nil)"); }); this.emitLine("try self.init(data: data)"); }); this.ensureBlankLine(); - this.emitBlock(`init(fromURL url: URL) throws`, () => { + this.emitBlock("init(fromURL url: URL) throws", () => { this.emitLine("try self.init(data: try Data(contentsOf: url))"); }); this.ensureBlankLine(); @@ -1050,17 +1077,17 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); }); } - private emitDecodingError(name: Name): void { + private emitDecodingError (name: Name): void { this.emitLine( "throw DecodingError.typeMismatch(", name, - '.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for ', + ".self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: \"Wrong type for ", name, - '"))' + "\"))", ); } - private emitSupportFunctions4 = (): void => { + private readonly emitSupportFunctions4 = (): void => { this.startFile("JSONSchemaSupport"); this.emitLineOnce("import Foundation"); @@ -1068,17 +1095,17 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); this.forEachTopLevel( "leading", (t: Type, name: Name) => this.renderTopLevelAlias(t, name), - t => this.namedTypeToNameForTopLevel(t) === undefined + t => this.namedTypeToNameForTopLevel(t) === undefined, ); if (this._options.convenienceInitializers) { this.ensureBlankLine(); this.forEachTopLevel("leading-and-interposing", (t: Type, name: Name) => - this.emitTopLevelMapAndArrayConvenienceInitializerExtensions(t, name) + this.emitTopLevelMapAndArrayConvenienceInitializerExtensions(t, name), ); } - if ((!this._options.justTypes && this._options.convenienceInitializers) || this._options.alamofire) { + if (!this._options.justTypes && this._options.convenienceInitializers || this._options.alamofire) { this.ensureBlankLine(); this.emitMark("Helper functions for creating encoders and decoders", true); this.ensureBlankLine(); @@ -1103,6 +1130,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); } else { this.emitLine(this.accessLevel, "class JSONNull: Codable, Hashable {"); } + this.ensureBlankLine(); this.emitMultiline(` public static func == (lhs: JSONNull, rhs: JSONNull) -> Bool { return true @@ -1128,6 +1156,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); } else { this.emitItem(" "); } + this.emitMultiline(`public init() {} public required init(from decoder: Decoder) throws { @@ -1143,6 +1172,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); } }`); } + if (this._needAny) { this.ensureBlankLine(); this.emitMultiline(`class JSONCodingKey: CodingKey { @@ -1171,6 +1201,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); } else { this.emitLine(this.accessLevel, "class JSONAny: Codable {"); } + this.ensureBlankLine(); this.emitMultiline(` ${this.accessLevel}let value: Any @@ -1369,7 +1400,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); this.endFile(); }; - private emitConvenienceMutator(c: ClassType, className: Name) { + private emitConvenienceMutator (c: ClassType, className: Name) { this.emitLine("func with("); this.indent(() => { this.forEachClassProperty(c, "none", (name, _, p, position) => { @@ -1378,7 +1409,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); ": ", this.swiftPropertyType(p), "? = nil", - position !== "only" && position !== "last" ? "," : "" + position !== "only" && position !== "last" ? "," : "", ); }); }); @@ -1392,7 +1423,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); name, " ?? self.", name, - position !== "only" && position !== "last" ? "," : "" + position !== "only" && position !== "last" ? "," : "", ); }); }); @@ -1400,11 +1431,11 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); }); } - protected emitMark(line: Sourcelike, horizontalLine = false) { + protected emitMark (line: Sourcelike, horizontalLine = false) { this.emitLine("// MARK:", horizontalLine ? " - " : " ", line); } - protected emitSourceStructure(): void { + protected emitSourceStructure (): void { if (this._options.multiFileOutput === false) { this.renderSingleFileHeaderComments(); } @@ -1413,7 +1444,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); "leading-and-interposing", (c: ClassType, className: Name) => this.renderClassDefinition(c, className), (e: EnumType, enumName: Name) => this.renderEnumDefinition(e, enumName), - (u: UnionType, unionName: Name) => this.renderUnionDefinition(u, unionName) + (u: UnionType, unionName: Name) => this.renderUnionDefinition(u, unionName), ); if (!this._options.justTypes) { @@ -1421,7 +1452,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); } } - private emitAlamofireExtension() { + private emitAlamofireExtension () { this.ensureBlankLine(); this.emitBlockWithAccess("extension DataRequest", () => { this @@ -1450,11 +1481,11 @@ fileprivate func responseDecodable(queue: DispatchQueue? = nil, co name, "(queue: DispatchQueue? = nil, completionHandler: @escaping (DataResponse<", name, - ">) -> Void) -> Self" + ">) -> Void) -> Self", ], () => { - this.emitLine(`return responseDecodable(queue: queue, completionHandler: completionHandler)`); - } + this.emitLine("return responseDecodable(queue: queue, completionHandler: completionHandler)"); + }, ); }); }); diff --git a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts index 22a1b9bdd..2629cff39 100644 --- a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts +++ b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts @@ -1,9 +1,12 @@ import { arrayIntercalate } from "collection-utils"; -import { ArrayType, ClassProperty, EnumType, MapType, ObjectType, Type } from "../Type"; +import { type ClassProperty, type ObjectType, type Type } from "../Type"; +import { ArrayType, EnumType, MapType } from "../Type"; import { matchType } from "../TypeUtils"; -import { funPrefixNamer, Name, Namer } from "../Naming"; -import { RenderContext } from "../Renderer"; -import { BooleanOption, getOptionValues, Option, OptionValues } from "../RendererOptions"; +import { type Name, type Namer } from "../Naming"; +import { funPrefixNamer } from "../Naming"; +import { type RenderContext } from "../Renderer"; +import { type Option, type OptionValues } from "../RendererOptions"; +import { BooleanOption, getOptionValues } from "../RendererOptions"; import { acronymStyle, AcronymStyleOptions } from "../support/Acronyms"; import { allLowerWordStyle, @@ -13,57 +16,57 @@ import { isLetterOrUnderscore, splitIntoWords, stringEscape, - utf16StringEscape + utf16StringEscape, } from "../support/Strings"; import { TargetLanguage } from "../TargetLanguage"; import { legalizeName } from "./JavaScript"; -import { Sourcelike } from "../Source"; +import { type Sourcelike } from "../Source"; import { panic } from "../support/Support"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; export const typeScriptEffectSchemaOptions = { - justSchema: new BooleanOption("just-schema", "Schema only", false) + justSchema: new BooleanOption("just-schema", "Schema only", false), }; export class TypeScriptEffectSchemaTargetLanguage extends TargetLanguage { - protected getOptions(): Option[] { + protected getOptions (): Array> { return []; } - constructor( + constructor ( displayName: string = "TypeScript Effect Schema", names: string[] = ["typescript-effect-schema"], - extension: string = "ts" + extension: string = "ts", ) { super(displayName, names, extension); } - protected makeRenderer( + protected makeRenderer ( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } + untypedOptionValues: { [name: string]: any, }, ): TypeScriptEffectSchemaRenderer { return new TypeScriptEffectSchemaRenderer( this, renderContext, - getOptionValues(typeScriptEffectSchemaOptions, untypedOptionValues) + getOptionValues(typeScriptEffectSchemaOptions, untypedOptionValues), ); } } export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues + private readonly _options: OptionValues, ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace (): string[] { return ["Class", "Date", "Object", "String", "Array", "JSON", "Error"]; } - protected nameStyle(original: string, upper: boolean): string { + protected nameStyle (original: string, upper: boolean): string { const acronyms = acronymStyle(AcronymStyleOptions.Camel); const words = splitIntoWords(original); return combineWords( @@ -74,48 +77,49 @@ export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { upper ? s => capitalize(acronyms(s)) : allLowerWordStyle, acronyms, "", - isLetterOrUnderscore + isLetterOrUnderscore, ); } - protected makeNamedTypeNamer(): Namer { + protected makeNamedTypeNamer (): Namer { return funPrefixNamer("types", s => this.nameStyle(s, true)); } - protected makeUnionMemberNamer(): Namer { + protected makeUnionMemberNamer (): Namer { return funPrefixNamer("properties", s => this.nameStyle(s, true)); } - protected namerForObjectProperty(): Namer { + protected namerForObjectProperty (): Namer { return funPrefixNamer("properties", s => this.nameStyle(s, true)); } - protected makeEnumCaseNamer(): Namer { + protected makeEnumCaseNamer (): Namer { return funPrefixNamer("enum-cases", s => this.nameStyle(s, false)); } - private importStatement(lhs: Sourcelike, moduleName: Sourcelike): Sourcelike { + private importStatement (lhs: Sourcelike, moduleName: Sourcelike): Sourcelike { return ["import ", lhs, " from ", moduleName, ";"]; } - protected emitImports(): void { + protected emitImports (): void { this.ensureBlankLine(); - this.emitLine(this.importStatement("* as S", '"@effect/schema/Schema"')); + this.emitLine(this.importStatement("* as S", "\"@effect/schema/Schema\"")); } - typeMapTypeForProperty(p: ClassProperty): Sourcelike { + typeMapTypeForProperty (p: ClassProperty): Sourcelike { const typeMap = this.typeMapTypeFor(p.type); return p.isOptional ? ["S.optional(", typeMap, ")"] : typeMap; } emittedObjects = new Set(); - typeMapTypeFor(t: Type, required: boolean = true): Sourcelike { + typeMapTypeFor (t: Type, required: boolean = true): Sourcelike { if (t.kind === "class" || t.kind === "object" || t.kind === "enum") { const name = this.nameForNamedType(t); if (this.emittedObjects.has(name)) { return [name]; } + return ["S.suspend(() => ", name, ")"]; } @@ -133,13 +137,13 @@ export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { _enumType => panic("Should already be handled."), unionType => { const children = Array.from(unionType.getChildren()).map((type: Type) => - this.typeMapTypeFor(type, false) + this.typeMapTypeFor(type, false), ); return ["S.union(", ...arrayIntercalate(", ", children), ")"]; }, _transformedStringType => { return "S.string"; - } + }, ); if (required) { @@ -149,10 +153,10 @@ export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { return match; } - private emitObject(name: Name, t: ObjectType) { + private emitObject (name: Name, t: ObjectType) { this.emittedObjects.add(name); this.ensureBlankLine(); - this.emitLine("\nexport class ", name, " extends S.Class<", name, '>("', name, '")({'); + this.emitLine("\nexport class ", name, " extends S.Class<", name, ">(\"", name, "\")({"); this.indent(() => { this.forEachClassProperty(t, "none", (_, jsonName, property) => { this.emitLine(`"${utf16StringEscape(jsonName)}"`, ": ", this.typeMapTypeForProperty(property), ","); @@ -161,15 +165,15 @@ export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { this.emitLine("}) {}"); } - private emitEnum(e: EnumType, enumName: Name): void { + private emitEnum (e: EnumType, enumName: Name): void { this.emittedObjects.add(enumName); this.ensureBlankLine(); this.emitDescription(this.descriptionForType(e)); this.emitLine("\nexport const ", enumName, " = ", "S.literal("); this.indent(() => this.forEachEnumCase(e, "none", (_, jsonName) => { - this.emitLine('"', stringEscape(jsonName), '",'); - }) + this.emitLine("\"", stringEscape(jsonName), "\","); + }), ); this.emitLine(");"); if (!this._options.justSchema) { @@ -177,8 +181,8 @@ export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { } } - protected walkObjectNames(type: ObjectType) { - const names: Array = []; + protected walkObjectNames (type: ObjectType) { + const names: Name[] = []; const recurse = (type: Type) => { if (type.kind === "object" || type.kind === "class") { @@ -204,7 +208,7 @@ export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { return names; } - protected emitSchemas(): void { + protected emitSchemas (): void { this.ensureBlankLine(); this.forEachEnum("leading-and-interposing", (u: EnumType, enumName: Name) => { @@ -249,7 +253,7 @@ export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { order.forEach(i => this.emitGatheredSource(this.gatherSource(() => this.emitObject(mapKey[i], mapValue[i])))); } - protected emitSourceStructure(): void { + protected emitSourceStructure (): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } diff --git a/packages/quicktype-core/src/language/TypeScriptFlow.ts b/packages/quicktype-core/src/language/TypeScriptFlow.ts index f21202056..f3dcb0765 100644 --- a/packages/quicktype-core/src/language/TypeScriptFlow.ts +++ b/packages/quicktype-core/src/language/TypeScriptFlow.ts @@ -1,20 +1,25 @@ -import { Type, ArrayType, UnionType, ClassType, EnumType } from "../Type"; +import { type Type, type ClassType} from "../Type"; +import { ArrayType, UnionType, EnumType } from "../Type"; import { matchType, nullableFromUnion, isNamedType } from "../TypeUtils"; import { utf16StringEscape, camelCase } from "../support/Strings"; -import { Sourcelike, modifySource, MultiWord, singleWord, parenIfNeeded, multiWord } from "../Source"; -import { Name, Namer, funPrefixNamer } from "../Naming"; -import { BooleanOption, Option, OptionValues, getOptionValues } from "../RendererOptions"; +import { type Sourcelike, type MultiWord} from "../Source"; +import { modifySource, singleWord, parenIfNeeded, multiWord } from "../Source"; +import { type Name, type Namer} from "../Naming"; +import { funPrefixNamer } from "../Naming"; +import { type Option, type OptionValues} from "../RendererOptions"; +import { BooleanOption, getOptionValues } from "../RendererOptions"; +import { + type JavaScriptTypeAnnotations} from "./JavaScript"; import { javaScriptOptions, JavaScriptTargetLanguage, JavaScriptRenderer, - JavaScriptTypeAnnotations, - legalizeName + legalizeName, } from "./JavaScript"; import { defined, panic } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; -import { RenderContext } from "../Renderer"; +import { type TargetLanguage } from "../TargetLanguage"; +import { type RenderContext } from "../Renderer"; import { isES3IdentifierStart } from "./JavaScriptUnicodeMaps"; export const tsFlowOptions = Object.assign({}, javaScriptOptions, { @@ -26,9 +31,9 @@ export const tsFlowOptions = Object.assign({}, javaScriptOptions, { preferConstValues: new BooleanOption( "prefer-const-values", "Use string instead of enum for string enums with single value", - false + false, ), - readonly: new BooleanOption("readonly", "Use readonly type members", false) + readonly: new BooleanOption("readonly", "Use readonly type members", false), }); const tsFlowTypeAnnotations = { @@ -37,11 +42,11 @@ const tsFlowTypeAnnotations = { anyMap: ": { [k: string]: any }", string: ": string", stringArray: ": string[]", - boolean: ": boolean" + boolean: ": boolean", }; export abstract class TypeScriptFlowBaseTargetLanguage extends JavaScriptTargetLanguage { - protected getOptions(): Option[] { + protected getOptions (): Array> { return [ tsFlowOptions.justTypes, tsFlowOptions.nicePropertyNames, @@ -54,34 +59,34 @@ export abstract class TypeScriptFlowBaseTargetLanguage extends JavaScriptTargetL tsFlowOptions.preferUnions, tsFlowOptions.preferTypes, tsFlowOptions.preferConstValues, - tsFlowOptions.readonly + tsFlowOptions.readonly, ]; } - get supportsOptionalClassProperties(): boolean { + get supportsOptionalClassProperties (): boolean { return true; } - protected abstract makeRenderer( + protected abstract makeRenderer ( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } + untypedOptionValues: { [name: string]: any, } ): JavaScriptRenderer; } export class TypeScriptTargetLanguage extends TypeScriptFlowBaseTargetLanguage { - constructor() { + constructor () { super("TypeScript", ["typescript", "ts", "tsx"], "ts"); } - protected makeRenderer( + protected makeRenderer ( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } + untypedOptionValues: { [name: string]: any, }, ): TypeScriptRenderer { return new TypeScriptRenderer(this, renderContext, getOptionValues(tsFlowOptions, untypedOptionValues)); } } -function quotePropertyName(original: string): string { +function quotePropertyName (original: string): string { const escaped = utf16StringEscape(original); const quoted = `"${escaped}"`; @@ -99,15 +104,15 @@ function quotePropertyName(original: string): string { } export abstract class TypeScriptFlowBaseRenderer extends JavaScriptRenderer { - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - protected readonly _tsFlowOptions: OptionValues + protected readonly _tsFlowOptions: OptionValues, ) { super(targetLanguage, renderContext, _tsFlowOptions); } - protected namerForObjectProperty(): Namer { + protected namerForObjectProperty (): Namer { if (this._tsFlowOptions.nicePropertyNames) { return funPrefixNamer("properties", s => this.nameStyle(s, false)); } else { @@ -115,14 +120,16 @@ export abstract class TypeScriptFlowBaseRenderer extends JavaScriptRenderer { } } - protected sourceFor(t: Type): MultiWord { + protected sourceFor (t: Type): MultiWord { if (this._tsFlowOptions.preferConstValues && t.kind === "enum" && t instanceof EnumType && t.cases.size === 1) { const item = t.cases.values().next().value; return singleWord(`"${utf16StringEscape(item)}"`); } - if (["class", "object", "enum"].indexOf(t.kind) >= 0) { + + if (["class", "object", "enum"].includes(t.kind)) { return singleWord(this.nameForNamedType(t)); } + return matchType( t, _anyType => singleWord("any"), @@ -134,7 +141,7 @@ export abstract class TypeScriptFlowBaseRenderer extends JavaScriptRenderer { arrayType => { const itemType = this.sourceFor(arrayType.items); if ( - (arrayType.items instanceof UnionType && !this._tsFlowOptions.declareUnions) || + arrayType.items instanceof UnionType && !this._tsFlowOptions.declareUnions || arrayType.items instanceof ArrayType ) { return singleWord(["Array<", itemType.source, ">"]); @@ -157,16 +164,17 @@ export abstract class TypeScriptFlowBaseRenderer extends JavaScriptRenderer { if (transformedStringType.kind === "date-time") { return singleWord("Date"); } + return singleWord("string"); - } + }, ); } - protected abstract emitEnum(e: EnumType, enumName: Name): void; + protected abstract emitEnum (e: EnumType, enumName: Name): void; - protected abstract emitClassBlock(c: ClassType, className: Name): void; + protected abstract emitClassBlock (c: ClassType, className: Name): void; - protected emitClassBlockBody(c: ClassType): void { + protected emitClassBlockBody (c: ClassType): void { this.emitPropertyTable(c, (name, _jsonName, p) => { const t = p.type; @@ -179,7 +187,7 @@ export abstract class TypeScriptFlowBaseRenderer extends JavaScriptRenderer { return [ [propertyName, p.isOptional ? "?" : "", ": "], - [this.sourceFor(t).source, ";"] + [this.sourceFor(t).source, ";"], ]; }); @@ -189,12 +197,12 @@ export abstract class TypeScriptFlowBaseRenderer extends JavaScriptRenderer { } } - private emitClass(c: ClassType, className: Name) { + private emitClass (c: ClassType, className: Name) { this.emitDescription(this.descriptionForType(c)); this.emitClassBlock(c, className); } - emitUnion(u: UnionType, unionName: Name) { + emitUnion (u: UnionType, unionName: Name) { if (!this._tsFlowOptions.declareUnions) { return; } @@ -205,54 +213,54 @@ export abstract class TypeScriptFlowBaseRenderer extends JavaScriptRenderer { this.emitLine("export type ", unionName, " = ", children.source, ";"); } - protected emitTypes(): void { + protected emitTypes (): void { this.forEachNamedType( "leading-and-interposing", (c: ClassType, n: Name) => this.emitClass(c, n), (e, n) => this.emitEnum(e, n), - (u, n) => this.emitUnion(u, n) + (u, n) => this.emitUnion(u, n), ); } - protected emitUsageComments(): void { + protected emitUsageComments (): void { if (this._tsFlowOptions.justTypes) return; super.emitUsageComments(); } - protected deserializerFunctionLine(t: Type, name: Name): Sourcelike { + protected deserializerFunctionLine (t: Type, name: Name): Sourcelike { const jsonType = this._tsFlowOptions.rawType === "json" ? "string" : "any"; return ["function to", name, "(json: ", jsonType, "): ", this.sourceFor(t).source]; } - protected serializerFunctionLine(t: Type, name: Name): Sourcelike { + protected serializerFunctionLine (t: Type, name: Name): Sourcelike { const camelCaseName = modifySource(camelCase, name); const returnType = this._tsFlowOptions.rawType === "json" ? "string" : "any"; return ["function ", camelCaseName, "ToJson(value: ", this.sourceFor(t).source, "): ", returnType]; } - protected get moduleLine(): string | undefined { + protected get moduleLine (): string | undefined { return undefined; } - protected get castFunctionLines(): [string, string] { + protected get castFunctionLines (): [string, string] { return ["function cast(val: any, typ: any): T", "function uncast(val: T, typ: any): any"]; } - protected get typeAnnotations(): JavaScriptTypeAnnotations { + protected get typeAnnotations (): JavaScriptTypeAnnotations { throw new Error("not implemented"); } - protected emitConvertModule(): void { + protected emitConvertModule (): void { if (this._tsFlowOptions.justTypes) return; super.emitConvertModule(); } - protected emitConvertModuleHelpers(): void { + protected emitConvertModuleHelpers (): void { if (this._tsFlowOptions.justTypes) return; super.emitConvertModuleHelpers(); } - protected emitModuleExports(): void { + protected emitModuleExports (): void { if (this._tsFlowOptions.justTypes) { return; } else { @@ -262,46 +270,46 @@ export abstract class TypeScriptFlowBaseRenderer extends JavaScriptRenderer { } export class TypeScriptRenderer extends TypeScriptFlowBaseRenderer { - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace (): string[] { return ["Array", "Date"]; } - protected deserializerFunctionLine(t: Type, name: Name): Sourcelike { + protected deserializerFunctionLine (t: Type, name: Name): Sourcelike { const jsonType = this._tsFlowOptions.rawType === "json" ? "string" : "any"; return ["public static to", name, "(json: ", jsonType, "): ", this.sourceFor(t).source]; } - protected serializerFunctionLine(t: Type, name: Name): Sourcelike { + protected serializerFunctionLine (t: Type, name: Name): Sourcelike { const camelCaseName = modifySource(camelCase, name); const returnType = this._tsFlowOptions.rawType === "json" ? "string" : "any"; return ["public static ", camelCaseName, "ToJson(value: ", this.sourceFor(t).source, "): ", returnType]; } - protected get moduleLine(): string | undefined { + protected get moduleLine (): string | undefined { return "export class Convert"; } - protected get typeAnnotations(): JavaScriptTypeAnnotations { + protected get typeAnnotations (): JavaScriptTypeAnnotations { return Object.assign({ never: ": never" }, tsFlowTypeAnnotations); } - protected emitModuleExports(): void { + protected emitModuleExports (): void { return; } - protected emitUsageImportComment(): void { + protected emitUsageImportComment (): void { const topLevelNames: Sourcelike[] = []; this.forEachTopLevel( "none", (_t, name) => { topLevelNames.push(", ", name); }, - isNamedType + isNamedType, ); - this.emitLine("// import { Convert", topLevelNames, ' } from "./file";'); + this.emitLine("// import { Convert", topLevelNames, " } from \"./file\";"); } - protected emitEnum(e: EnumType, enumName: Name): void { + protected emitEnum (e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); // enums with only one value are emitted as constants @@ -314,6 +322,7 @@ export class TypeScriptRenderer extends TypeScriptFlowBaseRenderer { items += `"${utf16StringEscape(item)}"`; return; } + items += ` | "${utf16StringEscape(item)}"`; }); this.emitLine("export type ", enumName, " = ", items, ";"); @@ -326,7 +335,7 @@ export class TypeScriptRenderer extends TypeScriptFlowBaseRenderer { } } - protected emitClassBlock(c: ClassType, className: Name): void { + protected emitClassBlock (c: ClassType, className: Name): void { this.emitBlock( this._tsFlowOptions.preferTypes ? ["export type ", className, " = "] @@ -334,36 +343,36 @@ export class TypeScriptRenderer extends TypeScriptFlowBaseRenderer { "", () => { this.emitClassBlockBody(c); - } + }, ); } } export class FlowTargetLanguage extends TypeScriptFlowBaseTargetLanguage { - constructor() { + constructor () { super("Flow", ["flow"], "js"); } - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): FlowRenderer { + protected makeRenderer (renderContext: RenderContext, untypedOptionValues: { [name: string]: any, }): FlowRenderer { return new FlowRenderer(this, renderContext, getOptionValues(tsFlowOptions, untypedOptionValues)); } } export class FlowRenderer extends TypeScriptFlowBaseRenderer { - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace (): string[] { return ["Class", "Date", "Object", "String", "Array", "JSON", "Error"]; } - protected get typeAnnotations(): JavaScriptTypeAnnotations { + protected get typeAnnotations (): JavaScriptTypeAnnotations { return Object.assign({ never: "" }, tsFlowTypeAnnotations); } - protected emitEnum(e: EnumType, enumName: Name): void { + protected emitEnum (e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); const lines: string[][] = []; this.forEachEnumCase(e, "none", (_, jsonName) => { const maybeOr = lines.length === 0 ? " " : "| "; - lines.push([maybeOr, '"', utf16StringEscape(jsonName), '"']); + lines.push([maybeOr, "\"", utf16StringEscape(jsonName), "\""]); }); defined(lines[lines.length - 1]).push(";"); @@ -375,13 +384,13 @@ export class FlowRenderer extends TypeScriptFlowBaseRenderer { }); } - protected emitClassBlock(c: ClassType, className: Name): void { + protected emitClassBlock (c: ClassType, className: Name): void { this.emitBlock(["export type ", className, " = "], ";", () => { this.emitClassBlockBody(c); }); } - protected emitSourceStructure() { + protected emitSourceStructure () { this.emitLine("// @flow"); this.ensureBlankLine(); super.emitSourceStructure(); diff --git a/packages/quicktype-core/src/language/TypeScriptZod.ts b/packages/quicktype-core/src/language/TypeScriptZod.ts index b2197624a..75b9e7f96 100644 --- a/packages/quicktype-core/src/language/TypeScriptZod.ts +++ b/packages/quicktype-core/src/language/TypeScriptZod.ts @@ -1,21 +1,25 @@ -import { StringTypeMapping } from "TypeBuilder"; +import { type StringTypeMapping } from "TypeBuilder"; import { arrayIntercalate } from "collection-utils"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { Name, Namer, funPrefixNamer } from "../Naming"; -import { RenderContext } from "../Renderer"; -import { BooleanOption, Option, OptionValues, getOptionValues } from "../RendererOptions"; -import { Sourcelike } from "../Source"; +import { type Name, type Namer} from "../Naming"; +import { funPrefixNamer } from "../Naming"; +import { type RenderContext } from "../Renderer"; +import { type Option, type OptionValues} from "../RendererOptions"; +import { BooleanOption, getOptionValues } from "../RendererOptions"; +import { type Sourcelike } from "../Source"; import { TargetLanguage } from "../TargetLanguage"; +import { + type ClassProperty, + type EnumType, + type PrimitiveStringTypeKind, + type TransformedStringTypeKind, + type Type, +} from "../Type"; import { ArrayType, - ClassProperty, ClassType, - EnumType, ObjectType, - PrimitiveStringTypeKind, SetOperationType, - TransformedStringTypeKind, - Type } from "../Type"; import { matchType } from "../TypeUtils"; import { AcronymStyleOptions, acronymStyle } from "../support/Acronyms"; @@ -27,65 +31,65 @@ import { isLetterOrUnderscore, splitIntoWords, stringEscape, - utf16StringEscape + utf16StringEscape, } from "../support/Strings"; import { panic } from "../support/Support"; import { legalizeName } from "./JavaScript"; export const typeScriptZodOptions = { - justSchema: new BooleanOption("just-schema", "Schema only", false) + justSchema: new BooleanOption("just-schema", "Schema only", false), }; export class TypeScriptZodTargetLanguage extends TargetLanguage { - protected getOptions(): Option[] { + protected getOptions (): Array> { return []; } - constructor( + constructor ( displayName: string = "TypeScript Zod", names: string[] = ["typescript-zod"], - extension: string = "ts" + extension: string = "ts", ) { super(displayName, names, extension); } - get stringTypeMapping(): StringTypeMapping { + get stringTypeMapping (): StringTypeMapping { const mapping: Map = new Map(); const dateTimeType = "date-time"; mapping.set("date-time", dateTimeType); return mapping; } - get supportsOptionalClassProperties(): boolean { + get supportsOptionalClassProperties (): boolean { return true; } - protected makeRenderer( + protected makeRenderer ( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } + untypedOptionValues: { [name: string]: any, }, ): TypeScriptZodRenderer { return new TypeScriptZodRenderer( this, renderContext, - getOptionValues(typeScriptZodOptions, untypedOptionValues) + getOptionValues(typeScriptZodOptions, untypedOptionValues), ); } } export class TypeScriptZodRenderer extends ConvenienceRenderer { - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - protected readonly _options: OptionValues + protected readonly _options: OptionValues, ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace (): string[] { return ["Class", "Date", "Object", "String", "Array", "JSON", "Error"]; } - protected nameStyle(original: string, upper: boolean): string { + protected nameStyle (original: string, upper: boolean): string { const acronyms = acronymStyle(AcronymStyleOptions.Camel); const words = splitIntoWords(original); return combineWords( @@ -96,42 +100,42 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { upper ? s => capitalize(acronyms(s)) : allLowerWordStyle, acronyms, "", - isLetterOrUnderscore + isLetterOrUnderscore, ); } - protected makeNamedTypeNamer(): Namer { + protected makeNamedTypeNamer (): Namer { return funPrefixNamer("types", s => this.nameStyle(s, true)); } - protected makeUnionMemberNamer(): Namer { + protected makeUnionMemberNamer (): Namer { return funPrefixNamer("properties", s => this.nameStyle(s, true)); } - protected namerForObjectProperty(): Namer { + protected namerForObjectProperty (): Namer { return funPrefixNamer("properties", s => this.nameStyle(s, true)); } - protected makeEnumCaseNamer(): Namer { + protected makeEnumCaseNamer (): Namer { return funPrefixNamer("enum-cases", s => this.nameStyle(s, false)); } - protected importStatement(lhs: Sourcelike, moduleName: Sourcelike): Sourcelike { + protected importStatement (lhs: Sourcelike, moduleName: Sourcelike): Sourcelike { return ["import ", lhs, " from ", moduleName, ";"]; } - protected emitImports(): void { + protected emitImports (): void { this.ensureBlankLine(); - this.emitLine(this.importStatement("* as z", '"zod"')); + this.emitLine(this.importStatement("* as z", "\"zod\"")); } - protected typeMapTypeForProperty(p: ClassProperty): Sourcelike { + protected typeMapTypeForProperty (p: ClassProperty): Sourcelike { const typeMap = this.typeMapTypeFor(p.type); return p.isOptional ? [typeMap, ".optional()"] : typeMap; } - protected typeMapTypeFor(t: Type, required: boolean = true): Sourcelike { - if (["class", "object", "enum"].indexOf(t.kind) >= 0) { + protected typeMapTypeFor (t: Type, required: boolean = true): Sourcelike { + if (["class", "object", "enum"].includes(t.kind)) { return [this.nameForNamedType(t), "Schema"]; } @@ -149,7 +153,7 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { _enumType => panic("Should already be handled."), unionType => { const children = Array.from(unionType.getChildren()).map((type: Type) => - this.typeMapTypeFor(type, false) + this.typeMapTypeFor(type, false), ); return ["z.union([", ...arrayIntercalate(", ", children), "])"]; }, @@ -157,8 +161,9 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { if (_transformedStringType.kind === "date-time") { return "z.coerce.date()"; } + return "z.string()"; - } + }, ); if (required) { @@ -168,7 +173,7 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { return match; } - protected emitObject(name: Name, t: ObjectType) { + protected emitObject (name: Name, t: ObjectType) { this.ensureBlankLine(); this.emitLine("\nexport const ", name, "Schema = ", "z.object({"); this.indent(() => { @@ -182,14 +187,14 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { } } - protected emitEnum(e: EnumType, enumName: Name): void { + protected emitEnum (e: EnumType, enumName: Name): void { this.ensureBlankLine(); this.emitDescription(this.descriptionForType(e)); this.emitLine("\nexport const ", enumName, "Schema = ", "z.enum(["); this.indent(() => this.forEachEnumCase(e, "none", (_, jsonName) => { - this.emitLine('"', stringEscape(jsonName), '",'); - }) + this.emitLine("\"", stringEscape(jsonName), "\","); + }), ); this.emitLine("]);"); if (!this._options.justSchema) { @@ -204,46 +209,47 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { * Primitive types don't need defining and enums are output before other types, hence, * these are ignored. */ - static extractUnderlyingTyperefs(type: Type): number[] { + static extractUnderlyingTyperefs (type: Type): number[] { let typeRefs: number[] = []; - //Ignore enums and primitives + // Ignore enums and primitives if (!type.isPrimitive() && type.kind != "enum") { - //need to extract constituent types for unions and intersections (which both extend SetOperationType) - //and can ignore the union/intersection itself + // need to extract constituent types for unions and intersections (which both extend SetOperationType) + // and can ignore the union/intersection itself if (type instanceof SetOperationType) { (type as SetOperationType).members.forEach(member => { - //recurse as the underlying type could itself be a union, instersection or array etc. + // recurse as the underlying type could itself be a union, instersection or array etc. typeRefs.push(...TypeScriptZodRenderer.extractUnderlyingTyperefs(member)); }); } - //need to extract additional properties for object, class and map types (which all extend ObjectType) + // need to extract additional properties for object, class and map types (which all extend ObjectType) if (type instanceof ObjectType) { const addType = (type as ObjectType).getAdditionalProperties(); if (addType) { - //recurse as the underlying type could itself be a union, instersection or array etc. + // recurse as the underlying type could itself be a union, instersection or array etc. typeRefs.push(...TypeScriptZodRenderer.extractUnderlyingTyperefs(addType)); } } - //need to extract items types for ArrayType + // need to extract items types for ArrayType if (type instanceof ArrayType) { const itemsType = (type as ArrayType).items; if (itemsType) { - //recurse as the underlying type could itself be a union, instersection or array etc. + // recurse as the underlying type could itself be a union, instersection or array etc. typeRefs.push(...TypeScriptZodRenderer.extractUnderlyingTyperefs(itemsType)); } } - //Finally return the reference to a class as that will need to be defined (where objects, maps, unions, intersections and arrays do not) + // Finally return the reference to a class as that will need to be defined (where objects, maps, unions, intersections and arrays do not) if (type instanceof ClassType) { typeRefs.push(type.typeRef); } } + return typeRefs; } - protected emitSchemas(): void { + protected emitSchemas (): void { this.ensureBlankLine(); this.forEachEnum("leading-and-interposing", (u: EnumType, enumName: Name) => { @@ -275,15 +281,15 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { mapChildTypeRefs.push(childTypeRefs); }); - //Items to process on this pass + // Items to process on this pass let indices: number[] = []; mapType.forEach((_, index) => { indices.push(index); }); - //items to process on the next pass + // items to process on the next pass let deferredIndices: number[] = []; - //defensive: make sure we don't loop forever, even complex sets shouldn't require many passes + // defensive: make sure we don't loop forever, even complex sets shouldn't require many passes const MAX_PASSES = 999; let passNum = 0; do { @@ -293,11 +299,11 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { let foundAllChildren = true; childTypeRefs.forEach(childRef => { - //defensive: first check if there is a definition for the referenced type (there should be) - if (mapTypeRef.indexOf(childRef) > -1) { + // defensive: first check if there is a definition for the referenced type (there should be) + if (mapTypeRef.includes(childRef)) { let found = false; // find this childs's ordinal, if it has already been added - //faster to go through what we've defined so far than all definitions + // faster to go through what we've defined so far than all definitions for (let j = 0; j < order.length; j++) { const childIndex = order[j]; if (mapTypeRef[childIndex] === childRef) { @@ -305,10 +311,11 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { break; } } + foundAllChildren = foundAllChildren && found; } else { console.error( - "A child type reference was not found amongst all Object definitions! TypeRef: " + childRef + "A child type reference was not found amongst all Object definitions! TypeRef: " + childRef, ); } }); @@ -317,7 +324,7 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { // insert index into order as we are safe to define this type order.push(index); } else { - //defer to a subsequent pass as we need to define other types + // defer to a subsequent pass as we need to define other types deferredIndices.push(index); } }); @@ -326,7 +333,7 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { passNum++; if (passNum > MAX_PASSES) { - //giving up + // giving up order.push(...deferredIndices); console.warn("Exceeded maximum number of passes when determining output order, output may contain forward references"); } @@ -336,7 +343,7 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { order.forEach(i => this.emitGatheredSource(this.gatherSource(() => this.emitObject(mapName[i], mapType[i])))); } - protected emitSourceStructure(): void { + protected emitSourceStructure (): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } diff --git a/packages/quicktype-core/src/language/ruby/index.ts b/packages/quicktype-core/src/language/ruby/index.ts index 383bdd5ae..42868baa7 100644 --- a/packages/quicktype-core/src/language/ruby/index.ts +++ b/packages/quicktype-core/src/language/ruby/index.ts @@ -1,16 +1,21 @@ import unicode from "unicode-properties"; -import { Sourcelike, modifySource } from "../../Source"; -import { Namer, Name } from "../../Naming"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../../ConvenienceRenderer"; +import { type Sourcelike} from "../../Source"; +import { modifySource } from "../../Source"; +import { type Name } from "../../Naming"; +import { Namer } from "../../Naming"; +import { type ForbiddenWordsInfo } from "../../ConvenienceRenderer"; +import { ConvenienceRenderer } from "../../ConvenienceRenderer"; import { TargetLanguage } from "../../TargetLanguage"; -import { Option, BooleanOption, EnumOption, OptionValues, getOptionValues, StringOption } from "../../RendererOptions"; +import { type Option, type OptionValues} from "../../RendererOptions"; +import { BooleanOption, EnumOption, getOptionValues, StringOption } from "../../RendererOptions"; import * as keywords from "./keywords"; const forbiddenForObjectProperties = Array.from(new Set([...keywords.keywords, ...keywords.reservedProperties])); -import { Type, EnumType, ClassType, UnionType, ArrayType, MapType, ClassProperty } from "../../Type"; +import { type Type, type EnumType, type UnionType, type ClassProperty } from "../../Type"; +import { ClassType, ArrayType, MapType } from "../../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../../TypeUtils"; import { @@ -25,20 +30,20 @@ import { escapeNonPrintableMapper, intToHex, snakeCase, - isLetterOrUnderscore + isLetterOrUnderscore, } from "../../support/Strings"; -import { RenderContext } from "../../Renderer"; +import { type RenderContext } from "../../Renderer"; -function unicodeEscape(codePoint: number): string { +function unicodeEscape (codePoint: number): string { return "\\u{" + intToHex(codePoint, 0) + "}"; } const stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, unicodeEscape)); export enum Strictness { - Strict = "Strict::", Coercible = "Coercible::", - None = "Types::" + None = "Types::", + Strict = "Strict::" } export const rubyOptions = { @@ -46,46 +51,47 @@ export const rubyOptions = { strictness: new EnumOption("strictness", "Type strictness", [ ["strict", Strictness.Strict], ["coercible", Strictness.Coercible], - ["none", Strictness.None] + ["none", Strictness.None], ]), - namespace: new StringOption("namespace", "Specify a wrapping Namespace", "NAME", "", "secondary") + namespace: new StringOption("namespace", "Specify a wrapping Namespace", "NAME", "", "secondary"), }; export class RubyTargetLanguage extends TargetLanguage { - constructor() { + constructor () { super("Ruby", ["ruby"], "rb"); } - protected getOptions(): Option[] { + protected getOptions (): Array> { return [rubyOptions.justTypes, rubyOptions.strictness, rubyOptions.namespace]; } - get supportsOptionalClassProperties(): boolean { + get supportsOptionalClassProperties (): boolean { return true; } - protected get defaultIndentation(): string { + protected get defaultIndentation (): string { return " "; } - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): RubyRenderer { + protected makeRenderer (renderContext: RenderContext, untypedOptionValues: { [name: string]: any, }): RubyRenderer { return new RubyRenderer(this, renderContext, getOptionValues(rubyOptions, untypedOptionValues)); } } const isStartCharacter = isLetterOrUnderscore; -function isPartCharacter(utf16Unit: number): boolean { +function isPartCharacter (utf16Unit: number): boolean { const category: string = unicode.getCategory(utf16Unit); - return ["Nd", "Pc", "Mn", "Mc"].indexOf(category) >= 0 || isStartCharacter(utf16Unit); + return ["Nd", "Pc", "Mn", "Mc"].includes(category) || isStartCharacter(utf16Unit); } const legalizeName = legalizeCharacters(isPartCharacter); -function simpleNameStyle(original: string, uppercase: boolean): string { +function simpleNameStyle (original: string, uppercase: boolean): string { if (/^[0-9]+$/.test(original)) { original = original + "N"; } + const words = splitIntoWords(original); return combineWords( words, @@ -95,11 +101,11 @@ function simpleNameStyle(original: string, uppercase: boolean): string { allUpperWordStyle, allUpperWordStyle, "", - isStartCharacter + isStartCharacter, ); } -function memberNameStyle(original: string): string { +function memberNameStyle (original: string): string { const words = splitIntoWords(original); return combineWords( words, @@ -109,56 +115,56 @@ function memberNameStyle(original: string): string { allLowerWordStyle, allLowerWordStyle, "_", - isStartCharacter + isStartCharacter, ); } export class RubyRenderer extends ConvenienceRenderer { - constructor( + constructor ( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues + private readonly _options: OptionValues, ) { super(targetLanguage, renderContext); } - protected get commentLineStart(): string { + protected get commentLineStart (): string { return "# "; } - protected get needsTypeDeclarationBeforeUse(): boolean { + protected get needsTypeDeclarationBeforeUse (): boolean { return true; } - protected canBeForwardDeclared(t: Type): boolean { + protected canBeForwardDeclared (t: Type): boolean { return "class" === t.kind; } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace (): string[] { return keywords.globals.concat(["Types", "JSON", "Dry", "Constructor", "Self"]); } - protected forbiddenForObjectProperties(_c: ClassType, _classNamed: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties (_c: ClassType, _classNamed: Name): ForbiddenWordsInfo { return { names: forbiddenForObjectProperties, includeGlobalForbidden: true }; } - protected makeNamedTypeNamer(): Namer { + protected makeNamedTypeNamer (): Namer { return new Namer("types", n => simpleNameStyle(n, true), []); } - protected namerForObjectProperty(): Namer { + protected namerForObjectProperty (): Namer { return new Namer("properties", memberNameStyle, []); } - protected makeUnionMemberNamer(): Namer { + protected makeUnionMemberNamer (): Namer { return new Namer("properties", memberNameStyle, []); } - protected makeEnumCaseNamer(): Namer { + protected makeEnumCaseNamer (): Namer { return new Namer("enum-cases", n => simpleNameStyle(n, true), []); } - private dryType(t: Type, isOptional = false): Sourcelike { + private dryType (t: Type, isOptional = false): Sourcelike { const optional = isOptional ? ".optional" : ""; return matchType( t, @@ -177,12 +183,13 @@ export class RubyRenderer extends ConvenienceRenderer { if (nullable !== null) { return [this.dryType(nullable), ".optional"]; } + return ["Types.Instance(", this.nameForNamedType(unionType), ")", optional]; - } + }, ); } - private exampleUse(t: Type, exp: Sourcelike, depth = 6, optional = false): Sourcelike { + private exampleUse (t: Type, exp: Sourcelike, depth = 6, optional = false): Sourcelike { if (depth-- <= 0) { return exp; } @@ -199,9 +206,9 @@ export class RubyRenderer extends ConvenienceRenderer { _stringType => exp, arrayType => this.exampleUse(arrayType.items, [exp, safeNav, ".first"], depth), classType => { - let info: { name: Name; prop: ClassProperty } | undefined; + let info: { name: Name, prop: ClassProperty, } | undefined; this.forEachClassProperty(classType, "none", (name, _json, prop) => { - if (["class", "map", "array"].indexOf(prop.type.kind) >= 0) { + if (["class", "map", "array"].includes(prop.type.kind)) { info = { name, prop }; } else if (info === undefined) { info = { name, prop }; @@ -210,9 +217,10 @@ export class RubyRenderer extends ConvenienceRenderer { if (info !== undefined) { return this.exampleUse(info.prop.type, [exp, safeNav, ".", info.name], depth, info.prop.isOptional); } + return exp; }, - mapType => this.exampleUse(mapType.values, [exp, safeNav, `["…"]`], depth), + mapType => this.exampleUse(mapType.values, [exp, safeNav, "[\"…\"]"], depth), enumType => { let name: Name | undefined; // FIXME: This is a terrible way to get the first enum case name. @@ -224,23 +232,26 @@ export class RubyRenderer extends ConvenienceRenderer { if (name !== undefined) { return [exp, " == ", this.nameForNamedType(enumType), "::", name]; } + return exp; }, unionType => { const nullable = nullableFromUnion(unionType); if (nullable !== null) { - if (["class", "map", "array"].indexOf(nullable.kind) >= 0) { + if (["class", "map", "array"].includes(nullable.kind)) { return this.exampleUse(nullable, exp, depth, true); } + return [exp, ".nil?"]; } + return exp; - } + }, ); } - private jsonSample(t: Type): Sourcelike { - function inner() { + private jsonSample (t: Type): Sourcelike { + function inner () { if (t instanceof ArrayType) { return "[…]"; } else if (t instanceof MapType) { @@ -251,10 +262,11 @@ export class RubyRenderer extends ConvenienceRenderer { return "…"; } } + return `"${inner()}"`; } - private fromDynamic(t: Type, e: Sourcelike, optional = false, castPrimitives = false): Sourcelike { + private fromDynamic (t: Type, e: Sourcelike, optional = false, castPrimitives = false): Sourcelike { const primitiveCast = [this.dryType(t, optional), "[", e, "]"]; const primitive = castPrimitives ? primitiveCast : e; const safeAccess = optional ? "&" : ""; @@ -278,7 +290,7 @@ export class RubyRenderer extends ConvenienceRenderer { this.fromDynamic(mapType.values, "v", false, true), "] }", safeAccess, - ".to_h" + ".to_h", ], enumType => { const expression = ["Types::", this.nameForNamedType(enumType), "[", e, "]"]; @@ -289,16 +301,18 @@ export class RubyRenderer extends ConvenienceRenderer { if (nullable !== null) { return this.fromDynamic(nullable, e, true); } + const expression = [this.nameForNamedType(unionType), ".from_dynamic!(", e, ")"]; return optional ? [e, " ? ", expression, " : nil"] : expression; - } + }, ); } - private toDynamic(t: Type, e: Sourcelike, optional = false): Sourcelike { + private toDynamic (t: Type, e: Sourcelike, optional = false): Sourcelike { if (this.marshalsImplicitlyToDynamic(t)) { return e; } + return matchType( t, _anyType => e, @@ -316,15 +330,17 @@ export class RubyRenderer extends ConvenienceRenderer { if (nullable !== null) { return this.toDynamic(nullable, e, true); } + if (this.marshalsImplicitlyToDynamic(unionType)) { return e; } + return [e, optional ? "&" : "", ".to_dynamic"]; - } + }, ); } - private marshalsImplicitlyToDynamic(t: Type): boolean { + private marshalsImplicitlyToDynamic (t: Type): boolean { return matchType( t, _anyType => true, @@ -342,15 +358,16 @@ export class RubyRenderer extends ConvenienceRenderer { if (nullable !== null) { return this.marshalsImplicitlyToDynamic(nullable); } + return false; - } + }, ); } // This is only to be used to allow class properties to possibly // marshal implicitly. They are allowed to do this because they will // be checked in Dry::Struct.new - private propertyTypeMarshalsImplicitlyFromDynamic(t: Type): boolean { + private propertyTypeMarshalsImplicitlyFromDynamic (t: Type): boolean { return matchType( t, _anyType => true, @@ -369,18 +386,19 @@ export class RubyRenderer extends ConvenienceRenderer { if (nullable !== null) { return this.propertyTypeMarshalsImplicitlyFromDynamic(nullable); } + return false; - } + }, ); } - private emitBlock(source: Sourcelike, emit: () => void) { + private emitBlock (source: Sourcelike, emit: () => void) { this.emitLine(source); this.indent(emit); this.emitLine("end"); } - private emitModule(emit: () => void) { + private emitModule (emit: () => void) { const emitModuleInner = (moduleName: string) => { const [firstModule, ...subModules] = moduleName.split("::"); if (subModules.length > 0) { @@ -391,6 +409,7 @@ export class RubyRenderer extends ConvenienceRenderer { this.emitBlock(["module ", moduleName], emit); } }; + if (this._options.namespace !== undefined && this._options.namespace !== "") { emitModuleInner(this._options.namespace); } else { @@ -398,7 +417,7 @@ export class RubyRenderer extends ConvenienceRenderer { } } - private emitClass(c: ClassType, className: Name) { + private emitClass (c: ClassType, className: Name) { this.emitDescription(this.descriptionForType(c)); this.emitBlock(["class ", className, " < Dry::Struct"], () => { let table: Sourcelike[][] = []; @@ -408,13 +427,14 @@ export class RubyRenderer extends ConvenienceRenderer { const description = this.descriptionForClassProperty(c, jsonName); const attribute = [ ["attribute :", name, ","], - [" ", this.dryType(p.type), p.isOptional ? ".optional" : ""] + [" ", this.dryType(p.type), p.isOptional ? ".optional" : ""], ]; if (description !== undefined) { if (table.length > 0) { this.emitTable(table); table = []; } + this.ensureBlankLine(); this.emitDescriptionBlock(description); this.emitLine(attribute); @@ -442,20 +462,20 @@ export class RubyRenderer extends ConvenienceRenderer { this.forEachClassProperty(c, "none", (name, jsonName, p) => { const dynamic = p.isOptional ? // If key is not found in hash, this will be nil - `d["${stringEscape(jsonName)}"]` + `d["${stringEscape(jsonName)}"]` : // This will raise a runtime error if the key is not found in the hash - `d.fetch("${stringEscape(jsonName)}")`; + `d.fetch("${stringEscape(jsonName)}")`; if (this.propertyTypeMarshalsImplicitlyFromDynamic(p.type)) { inits.push([ [name, ": "], - [dynamic, ","] + [dynamic, ","], ]); } else { const expression = this.fromDynamic(p.type, dynamic, p.isOptional); inits.push([ [name, ": "], - [expression, ","] + [expression, ","], ]); } }); @@ -489,7 +509,7 @@ export class RubyRenderer extends ConvenienceRenderer { }); } - private emitEnum(e: EnumType, enumName: Name) { + private emitEnum (e: EnumType, enumName: Name) { this.emitDescription(this.descriptionForType(e)); this.emitBlock(["module ", enumName], () => { const table: Sourcelike[][] = []; @@ -500,7 +520,7 @@ export class RubyRenderer extends ConvenienceRenderer { }); } - private emitUnion(u: UnionType, unionName: Name) { + private emitUnion (u: UnionType, unionName: Name) { this.emitDescription(this.descriptionForType(u)); this.emitBlock(["class ", unionName, " < Dry::Struct"], () => { const table: Sourcelike[][] = []; @@ -537,7 +557,7 @@ export class RubyRenderer extends ConvenienceRenderer { this.emitLine("end"); } }); - this.emitLine(`raise "Invalid union"`); + this.emitLine("raise \"Invalid union\""); }); this.ensureBlankLine(); @@ -561,6 +581,7 @@ export class RubyRenderer extends ConvenienceRenderer { this.emitLine("nil"); }); } + this.emitLine("end"); }); @@ -571,7 +592,7 @@ export class RubyRenderer extends ConvenienceRenderer { }); } - private emitTypesModule() { + private emitTypesModule () { this.emitBlock(["module Types"], () => { this.emitLine("include Dry.Types(default: :nominal)"); @@ -586,20 +607,21 @@ export class RubyRenderer extends ConvenienceRenderer { bool: has.bool || t.kind === "bool", hash: has.hash || t.kind === "map" || t.kind === "class", string: has.string || t.kind === "string" || t.kind === "enum", - double: has.double || t.kind === "double" + double: has.double || t.kind === "double", }; }); if (has.int) declarations.push([["Integer"], [` = ${this._options.strictness}Integer`]]); if (this._options.strictness === Strictness.Strict) { if (has.nil) declarations.push([["Nil"], [` = ${this._options.strictness}Nil`]]); } + if (has.bool) declarations.push([["Bool"], [` = ${this._options.strictness}Bool`]]); if (has.hash) declarations.push([["Hash"], [` = ${this._options.strictness}Hash`]]); if (has.string) declarations.push([["String"], [` = ${this._options.strictness}String`]]); if (has.double) declarations.push([ ["Double"], - [` = ${this._options.strictness}Float | ${this._options.strictness}Integer`] + [` = ${this._options.strictness}Float | ${this._options.strictness}Integer`], ]); } @@ -618,7 +640,7 @@ export class RubyRenderer extends ConvenienceRenderer { }); } - protected emitSourceStructure() { + protected emitSourceStructure () { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } else if (!this._options.justTypes) { @@ -635,6 +657,7 @@ export class RubyRenderer extends ConvenienceRenderer { }); this.emitLine("# If from_json! succeeds, the value returned matches the schema."); } + this.ensureBlankLine(); this.emitLine("require 'json'"); @@ -659,7 +682,7 @@ export class RubyRenderer extends ConvenienceRenderer { "leading-and-interposing", (c: ClassType, n: Name) => this.emitClass(c, n), (e, n) => this.emitEnum(e, n), - (u, n) => this.emitUnion(u, n) + (u, n) => this.emitUnion(u, n), ); if (!this._options.justTypes) { @@ -679,7 +702,7 @@ export class RubyRenderer extends ConvenienceRenderer { this.emitLine( self, " = ", - this.fromDynamic(topLevel, "JSON.parse(json, quirks_mode: true)") + this.fromDynamic(topLevel, "JSON.parse(json, quirks_mode: true)"), ); this.emitBlock([self, ".define_singleton_method(:to_json) do"], () => { this.emitLine("JSON.generate(", this.toDynamic(topLevel, "self"), ")"); @@ -687,7 +710,7 @@ export class RubyRenderer extends ConvenienceRenderer { this.emitLine(self); } else { this.emitLine( - this.fromDynamic(topLevel, "JSON.parse(json, quirks_mode: true)") + this.fromDynamic(topLevel, "JSON.parse(json, quirks_mode: true)"), ); } }); @@ -698,7 +721,7 @@ export class RubyRenderer extends ConvenienceRenderer { classDeclaration(); }); }, - t => this.namedTypeToNameForTopLevel(t) === undefined + t => this.namedTypeToNameForTopLevel(t) === undefined, ); } }); diff --git a/packages/quicktype-core/src/language/ruby/keywords.ts b/packages/quicktype-core/src/language/ruby/keywords.ts index e01c14b5f..0229d9044 100644 --- a/packages/quicktype-core/src/language/ruby/keywords.ts +++ b/packages/quicktype-core/src/language/ruby/keywords.ts @@ -39,7 +39,7 @@ export const keywords = [ "until", "when", "while", - "yield" + "yield", ]; const globalClasses = [ @@ -133,7 +133,7 @@ const globalClasses = [ "Undefined", "UnicodeNormalize", "Warning", - "ZeroDivisionError" + "ZeroDivisionError", ]; const kernel = [ @@ -286,7 +286,7 @@ const kernel = [ "untrace_var", "untrust", "untrusted?", - "warn" + "warn", ]; export const globals = kernel.concat(globalClasses); @@ -355,5 +355,5 @@ export const reservedProperties = [ "undef", "untrust", "while", - "with" + "with", ]; diff --git a/packages/quicktype-core/src/rewrites/CombineClasses.ts b/packages/quicktype-core/src/rewrites/CombineClasses.ts index 1f350644e..a89826f7c 100644 --- a/packages/quicktype-core/src/rewrites/CombineClasses.ts +++ b/packages/quicktype-core/src/rewrites/CombineClasses.ts @@ -1,27 +1,28 @@ -import { ClassType, Type, ClassProperty, setOperationCasesEqual } from "../Type"; +import { type Type, type ClassProperty} from "../Type"; +import { ClassType, setOperationCasesEqual } from "../Type"; import { nonNullTypeCases, combineTypeAttributesOfTypes } from "../TypeUtils"; -import { GraphRewriteBuilder } from "../GraphRewriting"; +import { type GraphRewriteBuilder } from "../GraphRewriting"; import { assert, panic } from "../support/Support"; -import { TypeGraph, TypeRef } from "../TypeGraph"; +import { type TypeGraph, type TypeRef } from "../TypeGraph"; import { unifyTypes, unionBuilderForUnification } from "../UnifyClasses"; -import { RunContext } from "../Run"; +import { type RunContext } from "../Run"; const REQUIRED_OVERLAP = 3 / 4; -type Clique = { +interface Clique { members: ClassType[]; prototypes: ClassType[]; -}; +} // FIXME: Allow some type combinations to unify, like different enums, // enums with strings, integers with doubles, maps with objects of // the correct type. -function typeSetsCanBeCombined(s1: Iterable, s2: Iterable): boolean { +function typeSetsCanBeCombined (s1: Iterable, s2: Iterable): boolean { return setOperationCasesEqual(s1, s2, true, (a, b) => a.structurallyCompatible(b, true)); } -function canBeCombined(c1: ClassType, c2: ClassType, onlyWithSameProperties: boolean): boolean { +function canBeCombined (c1: ClassType, c2: ClassType, onlyWithSameProperties: boolean): boolean { const p1 = c1.getProperties(); const p2 = c2.getProperties(); if (onlyWithSameProperties) { @@ -63,6 +64,7 @@ function canBeCombined(c1: ClassType, c2: ClassType, onlyWithSameProperties: boo if (faults > maxFaults) break; } } + if (faults > maxFaults) return false; for (const name of commonProperties) { let ts = smaller.get(name); @@ -70,22 +72,25 @@ function canBeCombined(c1: ClassType, c2: ClassType, onlyWithSameProperties: boo if (ts === undefined || tl === undefined) { return panic(`Both classes should have property ${name}`); } + const tsCases = nonNullTypeCases(ts.type); const tlCases = nonNullTypeCases(tl.type); if (tsCases.size > 0 && tlCases.size > 0 && !typeSetsCanBeCombined(tsCases, tlCases)) { return false; } } + return true; } -function tryAddToClique(c: ClassType, clique: Clique, onlyWithSameProperties: boolean): boolean { +function tryAddToClique (c: ClassType, clique: Clique, onlyWithSameProperties: boolean): boolean { for (const prototype of clique.prototypes) { if (prototype.structurallyCompatible(c)) { clique.members.push(c); return true; } } + for (const prototype of clique.prototypes) { if (canBeCombined(prototype, c, onlyWithSameProperties)) { clique.prototypes.push(c); @@ -93,16 +98,17 @@ function tryAddToClique(c: ClassType, clique: Clique, onlyWithSameProperties: bo return true; } } + return false; } -function findSimilarityCliques( +function findSimilarityCliques ( graph: TypeGraph, onlyWithSameProperties: boolean, - includeFixedClasses: boolean + includeFixedClasses: boolean, ): ClassType[][] { const classCandidates = Array.from(graph.allNamedTypesSeparated().objects).filter( - o => o instanceof ClassType && (includeFixedClasses || !o.isFixed) + o => o instanceof ClassType && (includeFixedClasses || !o.isFixed), ) as ClassType[]; const cliques: Clique[] = []; @@ -114,6 +120,7 @@ function findSimilarityCliques( break; } } + if (cliqueIndex === undefined) { // New clique cliqueIndex = cliques.length; @@ -131,22 +138,22 @@ function findSimilarityCliques( return cliques.map(clique => clique.members).filter(cl => cl.length > 1); } -export function combineClasses( +export function combineClasses ( ctx: RunContext, graph: TypeGraph, alphabetizeProperties: boolean, conflateNumbers: boolean, onlyWithSameProperties: boolean, - debugPrintReconstitution: boolean + debugPrintReconstitution: boolean, ): TypeGraph { const cliques = ctx.time(" find similarity cliques", () => - findSimilarityCliques(graph, onlyWithSameProperties, false) + findSimilarityCliques(graph, onlyWithSameProperties, false), ); - function makeCliqueClass( + function makeCliqueClass ( clique: ReadonlySet, builder: GraphRewriteBuilder, - forwardingRef: TypeRef + forwardingRef: TypeRef, ): TypeRef { assert(clique.size > 0, "Clique can't be empty"); const attributes = combineTypeAttributesOfTypes("union", clique); @@ -156,7 +163,7 @@ export function combineClasses( builder, unionBuilderForUnification(builder, false, false, conflateNumbers), conflateNumbers, - forwardingRef + forwardingRef, ); } @@ -166,6 +173,6 @@ export function combineClasses( alphabetizeProperties, cliques, debugPrintReconstitution, - makeCliqueClass + makeCliqueClass, ); } diff --git a/packages/quicktype-core/src/rewrites/ExpandStrings.ts b/packages/quicktype-core/src/rewrites/ExpandStrings.ts index 9cb886d9e..7f2bff226 100644 --- a/packages/quicktype-core/src/rewrites/ExpandStrings.ts +++ b/packages/quicktype-core/src/rewrites/ExpandStrings.ts @@ -6,17 +6,17 @@ import { setUnion, setIntersect, setIsSuperset, - areEqual + areEqual, } from "collection-utils"; -import { PrimitiveType } from "../Type"; +import { type PrimitiveType } from "../Type"; import { stringTypesForType } from "../TypeUtils"; -import { TypeGraph, TypeRef } from "../TypeGraph"; -import { GraphRewriteBuilder } from "../GraphRewriting"; +import { type TypeGraph, type TypeRef } from "../TypeGraph"; +import { type GraphRewriteBuilder } from "../GraphRewriting"; import { assert, defined } from "../support/Support"; import { emptyTypeAttributes } from "../attributes/TypeAttributes"; import { StringTypes } from "../attributes/StringTypes"; -import { RunContext } from "../Run"; +import { type RunContext } from "../Run"; const MIN_LENGTH_FOR_ENUM = 10; @@ -25,36 +25,36 @@ const REQUIRED_OVERLAP = 3 / 4; export type EnumInference = "none" | "all" | "infer"; -type EnumInfo = { +interface EnumInfo { cases: ReadonlySet; numValues: number; -}; +} -function isOwnEnum({ numValues, cases }: EnumInfo): boolean { +function isOwnEnum ({ numValues, cases }: EnumInfo): boolean { return numValues >= MIN_LENGTH_FOR_ENUM && cases.size < Math.sqrt(numValues); } -function enumCasesOverlap( +function enumCasesOverlap ( newCases: ReadonlySet, existingCases: ReadonlySet, - newAreSubordinate: boolean + newAreSubordinate: boolean, ): boolean { const smaller = newAreSubordinate ? newCases.size : Math.min(newCases.size, existingCases.size); const overlap = setIntersect(newCases, existingCases).size; return overlap >= smaller * REQUIRED_OVERLAP; } -function isAlwaysEmptyString(cases: string[]): boolean { +function isAlwaysEmptyString (cases: string[]): boolean { return cases.length === 1 && cases[0] === ""; } -export function expandStrings(ctx: RunContext, graph: TypeGraph, inference: EnumInference): TypeGraph { +export function expandStrings (ctx: RunContext, graph: TypeGraph, inference: EnumInference): TypeGraph { const stringTypeMapping = ctx.stringTypeMapping; const allStrings = Array.from(graph.allTypesUnordered()).filter( - t => t.kind === "string" && stringTypesForType(t as PrimitiveType).isRestricted + t => t.kind === "string" && stringTypesForType(t as PrimitiveType).isRestricted, ) as PrimitiveType[]; - function makeEnumInfo(t: PrimitiveType): EnumInfo | undefined { + function makeEnumInfo (t: PrimitiveType): EnumInfo | undefined { const stringTypes = stringTypesForType(t); const mappedStringTypes = stringTypes.applyStringTypeMapping(stringTypeMapping); if (!mappedStringTypes.isRestricted) return undefined; @@ -76,7 +76,7 @@ export function expandStrings(ctx: RunContext, graph: TypeGraph, inference: Enum } const enumInfos = new Map(); - const enumSets: ReadonlySet[] = []; + const enumSets: Array> = []; if (inference !== "none") { for (const t of allStrings) { @@ -85,7 +85,7 @@ export function expandStrings(ctx: RunContext, graph: TypeGraph, inference: Enum enumInfos.set(t, enumInfo); } - function findOverlap(newCases: ReadonlySet, newAreSubordinate: boolean): number { + function findOverlap (newCases: ReadonlySet, newAreSubordinate: boolean): number { return enumSets.findIndex(s => enumCasesOverlap(newCases, s, newAreSubordinate)); } @@ -117,6 +117,7 @@ export function expandStrings(ctx: RunContext, graph: TypeGraph, inference: Enum // Remove the ones we're done with. enumInfos.delete(t); } + if (inference === "all") { assert(enumInfos.size === 0); } @@ -138,10 +139,10 @@ export function expandStrings(ctx: RunContext, graph: TypeGraph, inference: Enum } } - function replaceString( + function replaceString ( group: ReadonlySet, builder: GraphRewriteBuilder, - forwardingRef: TypeRef + forwardingRef: TypeRef, ): TypeRef { assert(group.size === 1); const t = defined(iterableFirst(group)); @@ -166,6 +167,7 @@ export function expandStrings(ctx: RunContext, graph: TypeGraph, inference: Enum return builder.getStringType(attributes, StringTypes.unrestricted, forwardingRef); } } + const transformations = mappedStringTypes.transformations; // FIXME: This is probably wrong, or at least overly conservative. This is for the case // where some attributes are identity ones, i.e. where we can't merge the primitive types, @@ -177,6 +179,7 @@ export function expandStrings(ctx: RunContext, graph: TypeGraph, inference: Enum const kind = defined(iterableFirst(transformations)); return builder.getPrimitiveType(kind, attributes, forwardingRef); } + types.push(...Array.from(transformations).map(k => builder.getPrimitiveType(k))); assert(types.length > 0, "We got an empty string type"); return builder.getUnionType(attributes, new Set(types), forwardingRef); @@ -188,6 +191,6 @@ export function expandStrings(ctx: RunContext, graph: TypeGraph, inference: Enum false, allStrings.map(t => [t]), ctx.debugPrintReconstitution, - replaceString + replaceString, ); } diff --git a/packages/quicktype-core/src/rewrites/FlattenStrings.ts b/packages/quicktype-core/src/rewrites/FlattenStrings.ts index b700073f5..18ce4da1b 100644 --- a/packages/quicktype-core/src/rewrites/FlattenStrings.ts +++ b/packages/quicktype-core/src/rewrites/FlattenStrings.ts @@ -1,32 +1,32 @@ import { iterableFirst } from "collection-utils"; -import { PrimitiveType, UnionType, Type } from "../Type"; +import { type PrimitiveType, type UnionType, type Type } from "../Type"; import { stringTypesForType, combineTypeAttributesOfTypes } from "../TypeUtils"; -import { TypeGraph, TypeRef } from "../TypeGraph"; -import { StringTypeMapping } from "../TypeBuilder"; -import { GraphRewriteBuilder } from "../GraphRewriting"; +import { type TypeGraph, type TypeRef } from "../TypeGraph"; +import { type StringTypeMapping } from "../TypeBuilder"; +import { type GraphRewriteBuilder } from "../GraphRewriting"; import { assert, defined } from "../support/Support"; import { combineTypeAttributes } from "../attributes/TypeAttributes"; // A union needs replacing if it contains more than one string type, one of them being // a basic string type. -function unionNeedsReplacing(u: UnionType): ReadonlySet | undefined { +function unionNeedsReplacing (u: UnionType): ReadonlySet | undefined { const stringMembers = u.stringTypeMembers; if (stringMembers.size <= 1) return undefined; const stringType = u.findMember("string"); if (stringType === undefined) return undefined; assert( !stringTypesForType(stringType as PrimitiveType).isRestricted, - "We must only flatten strings if we have no restriced strings" + "We must only flatten strings if we have no restriced strings", ); return stringMembers; } // Replaces all string types in an enum with the basic string type. -function replaceUnion( +function replaceUnion ( group: ReadonlySet, builder: GraphRewriteBuilder, - forwardingRef: TypeRef + forwardingRef: TypeRef, ): TypeRef { assert(group.size === 1); const u = defined(iterableFirst(group)); @@ -37,21 +37,23 @@ function replaceUnion( if (stringMembers.has(t)) continue; types.push(builder.reconstituteType(t)); } + if (types.length === 0) { return builder.getStringType( combineTypeAttributes("union", stringAttributes, u.getAttributes()), undefined, - forwardingRef + forwardingRef, ); } + types.push(builder.getStringType(stringAttributes, undefined)); return builder.getUnionType(u.getAttributes(), new Set(types), forwardingRef); } -export function flattenStrings( +export function flattenStrings ( graph: TypeGraph, stringTypeMapping: StringTypeMapping, - debugPrintReconstitution: boolean + debugPrintReconstitution: boolean, ): TypeGraph { const allUnions = graph.allNamedTypesSeparated().unions; const unionsToReplace = Array.from(allUnions) @@ -63,6 +65,6 @@ export function flattenStrings( false, unionsToReplace, debugPrintReconstitution, - replaceUnion + replaceUnion, ); } diff --git a/packages/quicktype-core/src/rewrites/FlattenUnions.ts b/packages/quicktype-core/src/rewrites/FlattenUnions.ts index a88dca2e8..b9ef1d41e 100644 --- a/packages/quicktype-core/src/rewrites/FlattenUnions.ts +++ b/packages/quicktype-core/src/rewrites/FlattenUnions.ts @@ -1,31 +1,34 @@ import { setFilter, iterableSome } from "collection-utils"; -import { TypeGraph, TypeRef, derefTypeRef } from "../TypeGraph"; -import { Type, UnionType, IntersectionType } from "../Type"; +import { type TypeGraph, type TypeRef} from "../TypeGraph"; +import { derefTypeRef } from "../TypeGraph"; +import { type Type} from "../Type"; +import { UnionType, IntersectionType } from "../Type"; import { makeGroupsToFlatten } from "../TypeUtils"; import { assert } from "../support/Support"; -import { StringTypeMapping } from "../TypeBuilder"; -import { GraphRewriteBuilder } from "../GraphRewriting"; +import { type StringTypeMapping } from "../TypeBuilder"; +import { type GraphRewriteBuilder } from "../GraphRewriting"; import { unifyTypes, UnifyUnionBuilder } from "../UnifyClasses"; import { messageAssert } from "../Messages"; import { emptyTypeAttributes } from "../attributes/TypeAttributes"; -export function flattenUnions( +export function flattenUnions ( graph: TypeGraph, stringTypeMapping: StringTypeMapping, conflateNumbers: boolean, makeObjectTypes: boolean, - debugPrintReconstitution: boolean + debugPrintReconstitution: boolean, ): [TypeGraph, boolean] { let needsRepeat = false; - function replace(types: ReadonlySet, builder: GraphRewriteBuilder, forwardingRef: TypeRef): TypeRef { + function replace (types: ReadonlySet, builder: GraphRewriteBuilder, forwardingRef: TypeRef): TypeRef { const unionBuilder = new UnifyUnionBuilder(builder, makeObjectTypes, true, trefs => { assert(trefs.length > 0, "Must have at least one type to build union"); trefs = trefs.map(tref => builder.reconstituteType(derefTypeRef(tref, graph))); if (trefs.length === 1) { return trefs[0]; } + needsRepeat = true; return builder.getUnionType(emptyTypeAttributes, new Set(trefs)); }); diff --git a/packages/quicktype-core/src/rewrites/InferMaps.ts b/packages/quicktype-core/src/rewrites/InferMaps.ts index 9190b043b..0092d1dbf 100644 --- a/packages/quicktype-core/src/rewrites/InferMaps.ts +++ b/packages/quicktype-core/src/rewrites/InferMaps.ts @@ -1,27 +1,30 @@ import { iterableFirst, iterableEvery, setMap } from "collection-utils"; -import { Type, ClassType, setOperationCasesEqual, ClassProperty, isPrimitiveStringTypeKind } from "../Type"; +import { type Type, type ClassProperty} from "../Type"; +import { ClassType, setOperationCasesEqual, isPrimitiveStringTypeKind } from "../Type"; import { removeNullFromType } from "../TypeUtils"; import { defined, panic } from "../support/Support"; -import { TypeGraph, TypeRef } from "../TypeGraph"; -import { StringTypeMapping } from "../TypeBuilder"; -import { GraphRewriteBuilder } from "../GraphRewriting"; +import { type TypeGraph, type TypeRef } from "../TypeGraph"; +import { type StringTypeMapping } from "../TypeBuilder"; +import { type GraphRewriteBuilder } from "../GraphRewriting"; import { unifyTypes, unionBuilderForUnification } from "../UnifyClasses"; -import { MarkovChain, load, evaluate } from "../MarkovChain"; +import { type MarkovChain} from "../MarkovChain"; +import { load, evaluate } from "../MarkovChain"; const mapSizeThreshold = 20; const stringMapSizeThreshold = 50; let markovChain: MarkovChain | undefined = undefined; -function nameProbability(name: string): number { +function nameProbability (name: string): number { if (markovChain === undefined) { markovChain = load(); } + return evaluate(markovChain, name); } -function shouldBeMap(properties: ReadonlyMap): ReadonlySet | undefined { +function shouldBeMap (properties: ReadonlyMap): ReadonlySet | undefined { // Only classes with a certain number of properties are inferred // as maps. const numProperties = properties.size; @@ -94,24 +97,27 @@ function shouldBeMap(properties: ReadonlyMap): ReadonlySe firstNonNullCases = nn; } } + allCases.add(p.type); } + if (!canBeMap) { return undefined; } + return allCases; } -export function inferMaps( +export function inferMaps ( graph: TypeGraph, stringTypeMapping: StringTypeMapping, conflateNumbers: boolean, - debugPrintReconstitution: boolean + debugPrintReconstitution: boolean, ): TypeGraph { - function replaceClass( + function replaceClass ( setOfOneClass: ReadonlySet, builder: GraphRewriteBuilder, - forwardingRef: TypeRef + forwardingRef: TypeRef, ): TypeRef { const c = defined(iterableFirst(setOfOneClass)); const properties = c.getProperties(); @@ -134,9 +140,9 @@ export function inferMaps( c.getAttributes(), builder, unionBuilderForUnification(builder, false, false, conflateNumbers), - conflateNumbers + conflateNumbers, ), - forwardingRef + forwardingRef, ); } @@ -150,6 +156,6 @@ export function inferMaps( false, classesToReplace.map(c => [c]), debugPrintReconstitution, - replaceClass + replaceClass, ); } diff --git a/packages/quicktype-core/src/rewrites/ReplaceObjectType.ts b/packages/quicktype-core/src/rewrites/ReplaceObjectType.ts index a9245fe38..e225c3c42 100644 --- a/packages/quicktype-core/src/rewrites/ReplaceObjectType.ts +++ b/packages/quicktype-core/src/rewrites/ReplaceObjectType.ts @@ -1,40 +1,40 @@ import { setFilter, iterableFirst, mapMap, setMap } from "collection-utils"; -import { TypeGraph, TypeRef } from "../TypeGraph"; -import { StringTypeMapping } from "../TypeBuilder"; -import { GraphRewriteBuilder } from "../GraphRewriting"; -import { ObjectType, ClassProperty } from "../Type"; +import { type TypeGraph, type TypeRef } from "../TypeGraph"; +import { type StringTypeMapping } from "../TypeBuilder"; +import { type GraphRewriteBuilder } from "../GraphRewriting"; +import { type ObjectType, type ClassProperty } from "../Type"; import { defined } from "../support/Support"; import { emptyTypeAttributes } from "../attributes/TypeAttributes"; -export function replaceObjectType( +export function replaceObjectType ( graph: TypeGraph, stringTypeMapping: StringTypeMapping, _conflateNumbers: boolean, leaveFullObjects: boolean, - debugPrintReconstitution: boolean + debugPrintReconstitution: boolean, ): TypeGraph { - function replace( + function replace ( setOfOneType: ReadonlySet, builder: GraphRewriteBuilder, - forwardingRef: TypeRef + forwardingRef: TypeRef, ): TypeRef { const o = defined(iterableFirst(setOfOneType)); const attributes = o.getAttributes(); const properties = o.getProperties(); const additionalProperties = o.getAdditionalProperties(); - function reconstituteProperties(): ReadonlyMap { + function reconstituteProperties (): ReadonlyMap { return mapMap(properties, cp => - builder.makeClassProperty(builder.reconstituteTypeRef(cp.typeRef), cp.isOptional) + builder.makeClassProperty(builder.reconstituteTypeRef(cp.typeRef), cp.isOptional), ); } - function makeClass(): TypeRef { + function makeClass (): TypeRef { return builder.getUniqueClassType(attributes, true, reconstituteProperties(), forwardingRef); } - function reconstituteAdditionalProperties(): TypeRef { + function reconstituteAdditionalProperties (): TypeRef { return builder.reconstituteType(defined(additionalProperties)); } diff --git a/packages/quicktype-core/src/rewrites/ResolveIntersections.ts b/packages/quicktype-core/src/rewrites/ResolveIntersections.ts index c68159828..22f2984cb 100644 --- a/packages/quicktype-core/src/rewrites/ResolveIntersections.ts +++ b/packages/quicktype-core/src/rewrites/ResolveIntersections.ts @@ -9,56 +9,60 @@ import { setMap, iterableFind, setIntersect, - setUnionInto + setUnionInto, } from "collection-utils"; -import { TypeGraph, TypeRef } from "../TypeGraph"; -import { StringTypeMapping, TypeBuilder } from "../TypeBuilder"; -import { GraphRewriteBuilder, TypeLookerUp } from "../GraphRewriting"; -import { UnionTypeProvider, UnionBuilder, TypeAttributeMap } from "../UnionBuilder"; +import { type TypeGraph, type TypeRef } from "../TypeGraph"; +import { type StringTypeMapping, type TypeBuilder } from "../TypeBuilder"; +import { type GraphRewriteBuilder, type TypeLookerUp } from "../GraphRewriting"; +import { type UnionTypeProvider, type TypeAttributeMap } from "../UnionBuilder"; +import { UnionBuilder } from "../UnionBuilder"; +import { + type Type, + type PrimitiveTypeKind, + type TypeKind} from "../Type"; import { IntersectionType, - Type, UnionType, - PrimitiveTypeKind, ArrayType, isPrimitiveTypeKind, isNumberTypeKind, GenericClassProperty, - TypeKind, - ObjectType + ObjectType, } from "../Type"; import { setOperationMembersRecursively, matchTypeExhaustive, makeGroupsToFlatten } from "../TypeUtils"; import { assert, defined, panic, mustNotHappen } from "../support/Support"; +import { + type TypeAttributes} from "../attributes/TypeAttributes"; import { combineTypeAttributes, - TypeAttributes, emptyTypeAttributes, - makeTypeAttributesInferred + makeTypeAttributesInferred, } from "../attributes/TypeAttributes"; -function canResolve(t: IntersectionType): boolean { +function canResolve (t: IntersectionType): boolean { const members = setOperationMembersRecursively(t, undefined)[0]; if (members.size <= 1) return true; return iterableEvery(members, m => !(m instanceof UnionType) || m.isCanonical); } -function attributesForTypes(types: ReadonlySet): TypeAttributeMap { +function attributesForTypes (types: ReadonlySet): TypeAttributeMap { return mapMapEntries(types.entries(), t => [t.kind, t.getAttributes()] as [T, TypeAttributes]); } type PropertyMap = Map>>; class IntersectionAccumulator - implements UnionTypeProvider, [PropertyMap, ReadonlySet | undefined] | undefined> -{ +implements UnionTypeProvider, [PropertyMap, ReadonlySet | undefined] | undefined> { private _primitiveTypes: Set | undefined; + private readonly _primitiveAttributes: TypeAttributeMap = new Map(); // * undefined: We haven't seen any types yet. // * Set: All types we've seen can be arrays. // * false: At least one of the types seen can't be an array. private _arrayItemTypes: Set | undefined | false; + private _arrayAttributes: TypeAttributes = emptyTypeAttributes; // We start out with all object types allowed, which means @@ -70,12 +74,14 @@ class IntersectionAccumulator // undefined, no object types are allowed, in which case // _additionalPropertyTypes must also be undefined; private _objectProperties: PropertyMap | undefined = new Map(); + private _objectAttributes: TypeAttributes = emptyTypeAttributes; + private _additionalPropertyTypes: Set | undefined = new Set(); private _lostTypeAttributes = false; - private updatePrimitiveTypes(members: Iterable): void { + private updatePrimitiveTypes (members: Iterable): void { const types = setFilter(members, t => isPrimitiveTypeKind(t.kind)); const attributes = attributesForTypes(types); mapMergeWithInto(this._primitiveAttributes, (a, b) => combineTypeAttributes("intersect", a, b), attributes); @@ -97,7 +103,7 @@ class IntersectionAccumulator } } - private updateArrayItemTypes(members: Iterable): void { + private updateArrayItemTypes (members: Iterable): void { const maybeArray = iterableFind(members, t => t instanceof ArrayType) as ArrayType | undefined; if (maybeArray === undefined) { this._arrayItemTypes = false; @@ -113,7 +119,7 @@ class IntersectionAccumulator } } - private updateObjectProperties(members: Iterable): void { + private updateObjectProperties (members: Iterable): void { const maybeObject = iterableFind(members, t => t instanceof ObjectType) as ObjectType | undefined; if (maybeObject === undefined) { this._objectProperties = undefined; @@ -124,7 +130,7 @@ class IntersectionAccumulator this._objectAttributes = combineTypeAttributes( "intersect", this._objectAttributes, - maybeObject.getAttributes() + maybeObject.getAttributes(), ); const objectAdditionalProperties = maybeObject.getAdditionalProperties(); @@ -135,7 +141,7 @@ class IntersectionAccumulator const allPropertyNames = setUnionInto( new Set(this._objectProperties.keys()), - maybeObject.getProperties().keys() + maybeObject.getProperties().keys(), ); for (const name of allPropertyNames) { const existing = defined(this._objectProperties).get(name); @@ -144,13 +150,13 @@ class IntersectionAccumulator if (existing !== undefined && newProperty !== undefined) { const cp = new GenericClassProperty( existing.typeData.add(newProperty.type), - existing.isOptional && newProperty.isOptional + existing.isOptional && newProperty.isOptional, ); defined(this._objectProperties).set(name, cp); } else if (existing !== undefined && objectAdditionalProperties !== undefined) { const cp = new GenericClassProperty( existing.typeData.add(objectAdditionalProperties), - existing.isOptional + existing.isOptional, ); defined(this._objectProperties).set(name, cp); } else if (existing !== undefined) { @@ -174,13 +180,13 @@ class IntersectionAccumulator } } - private addUnionSet(members: Iterable): void { + private addUnionSet (members: Iterable): void { this.updatePrimitiveTypes(members); this.updateArrayItemTypes(members); this.updateObjectProperties(members); } - addType(t: Type): TypeAttributes { + addType (t: Type): TypeAttributes { let attributes = t.getAttributes(); matchTypeExhaustive( t, @@ -203,23 +209,24 @@ class IntersectionAccumulator unionType => { attributes = combineTypeAttributes( "intersect", - [attributes].concat(Array.from(unionType.members).map(m => m.getAttributes())) + [attributes].concat(Array.from(unionType.members).map(m => m.getAttributes())), ); this.addUnionSet(unionType.members); }, - transformedStringType => this.addUnionSet([transformedStringType]) + transformedStringType => this.addUnionSet([transformedStringType]), ); return makeTypeAttributesInferred(attributes); } - get arrayData(): ReadonlySet { + get arrayData (): ReadonlySet { if (this._arrayItemTypes === undefined || this._arrayItemTypes === false) { return panic("This should not be called if the type can't be an array"); } + return this._arrayItemTypes; } - get objectData(): [PropertyMap, ReadonlySet | undefined] | undefined { + get objectData (): [PropertyMap, ReadonlySet | undefined] | undefined { if (this._objectProperties === undefined) { assert(this._additionalPropertyTypes === undefined); return undefined; @@ -228,13 +235,13 @@ class IntersectionAccumulator return [this._objectProperties, this._additionalPropertyTypes]; } - get enumCases(): ReadonlySet { + get enumCases (): ReadonlySet { return panic("We don't support enums in intersections"); } - getMemberKinds(): TypeAttributeMap { + getMemberKinds (): TypeAttributeMap { const kinds: TypeAttributeMap = mapMap(defined(this._primitiveTypes).entries(), k => - defined(this._primitiveAttributes.get(k)) + defined(this._primitiveAttributes.get(k)), ); const maybeDoubleAttributes = this._primitiveAttributes.get("double"); // If double was eliminated, add its attributes to integer @@ -260,19 +267,19 @@ class IntersectionAccumulator return kinds; } - get lostTypeAttributes(): boolean { + get lostTypeAttributes (): boolean { return this._lostTypeAttributes; } } class IntersectionUnionBuilder extends UnionBuilder< - TypeBuilder & TypeLookerUp, - ReadonlySet, - [PropertyMap, ReadonlySet | undefined] | undefined +TypeBuilder & TypeLookerUp, +ReadonlySet, +[PropertyMap, ReadonlySet | undefined] | undefined > { private _createdNewIntersections = false; - private makeIntersection(members: ReadonlySet, attributes: TypeAttributes): TypeRef { + private makeIntersection (members: ReadonlySet, attributes: TypeAttributes): TypeRef { const reconstitutedMembers = setMap(members, t => this.typeBuilder.reconstituteTypeRef(t.typeRef)); const first = defined(iterableFirst(reconstitutedMembers)); @@ -285,14 +292,14 @@ class IntersectionUnionBuilder extends UnionBuilder< return this.typeBuilder.getUniqueIntersectionType(attributes, reconstitutedMembers); } - get createdNewIntersections(): boolean { + get createdNewIntersections (): boolean { return this._createdNewIntersections; } - protected makeObject( + protected makeObject ( maybeData: [PropertyMap, ReadonlySet | undefined] | undefined, typeAttributes: TypeAttributes, - forwardingRef: TypeRef | undefined + forwardingRef: TypeRef | undefined, ): TypeRef { if (maybeData === undefined) { return panic("Either properties or additional properties must be given to make an object type"); @@ -300,7 +307,7 @@ class IntersectionUnionBuilder extends UnionBuilder< const [propertyTypes, maybeAdditionalProperties] = maybeData; const properties = mapMap(propertyTypes, cp => - this.typeBuilder.makeClassProperty(this.makeIntersection(cp.typeData, emptyTypeAttributes), cp.isOptional) + this.typeBuilder.makeClassProperty(this.makeIntersection(cp.typeData, emptyTypeAttributes), cp.isOptional), ); const additionalProperties = maybeAdditionalProperties === undefined @@ -309,10 +316,10 @@ class IntersectionUnionBuilder extends UnionBuilder< return this.typeBuilder.getUniqueObjectType(typeAttributes, properties, additionalProperties, forwardingRef); } - protected makeArray( + protected makeArray ( arrays: ReadonlySet, typeAttributes: TypeAttributes, - forwardingRef: TypeRef | undefined + forwardingRef: TypeRef | undefined, ): TypeRef { // FIXME: attributes const itemsType = this.makeIntersection(arrays, emptyTypeAttributes); @@ -321,23 +328,24 @@ class IntersectionUnionBuilder extends UnionBuilder< } } -export function resolveIntersections( +export function resolveIntersections ( graph: TypeGraph, stringTypeMapping: StringTypeMapping, - debugPrintReconstitution: boolean + debugPrintReconstitution: boolean, ): [TypeGraph, boolean] { let needsRepeat = false; - function replace(types: ReadonlySet, builder: GraphRewriteBuilder, forwardingRef: TypeRef): TypeRef { + function replace (types: ReadonlySet, builder: GraphRewriteBuilder, forwardingRef: TypeRef): TypeRef { const intersections = setFilter(types, t => t instanceof IntersectionType) as Set; const [members, intersectionAttributes] = setOperationMembersRecursively( Array.from(intersections), - "intersect" + "intersect", ); if (members.size === 0) { const t = builder.getPrimitiveType("any", intersectionAttributes, forwardingRef); return t; } + if (members.size === 1) { return builder.reconstituteType(defined(iterableFirst(members)), intersectionAttributes, forwardingRef); } @@ -346,8 +354,8 @@ export function resolveIntersections( const extraAttributes = makeTypeAttributesInferred( combineTypeAttributes( "intersect", - Array.from(members).map(t => accumulator.addType(t)) - ) + Array.from(members).map(t => accumulator.addType(t)), + ), ); const attributes = combineTypeAttributes("intersect", intersectionAttributes, extraAttributes); @@ -356,13 +364,15 @@ export function resolveIntersections( if (unionBuilder.createdNewIntersections) { needsRepeat = true; } + return tref; } + // FIXME: We need to handle intersections that resolve to the same set of types. // See for example the intersections-nested.schema example. const allIntersections = setFilter( graph.allTypesUnordered(), - t => t instanceof IntersectionType + t => t instanceof IntersectionType, ) as Set; const resolvableIntersections = setFilter(allIntersections, canResolve); const groups = makeGroupsToFlatten(resolvableIntersections, undefined); diff --git a/packages/quicktype-core/src/support/Acronyms.ts b/packages/quicktype-core/src/support/Acronyms.ts index 21460b0cf..24a40dec1 100644 --- a/packages/quicktype-core/src/support/Acronyms.ts +++ b/packages/quicktype-core/src/support/Acronyms.ts @@ -1096,14 +1096,14 @@ export const acronyms: string[] = [ "zma", "zoi", "zope", - "zpl" + "zpl", ]; export enum AcronymStyleOptions { - Pascal = "pascal", Camel = "camel", + Lower = "lowerCase", Original = "original", - Lower = "lowerCase" + Pascal = "pascal" } export const acronymOption = function (defaultOption: AcronymStyleOptions) { @@ -1114,19 +1114,19 @@ export const acronymOption = function (defaultOption: AcronymStyleOptions) { [AcronymStyleOptions.Original, AcronymStyleOptions.Original], [AcronymStyleOptions.Pascal, AcronymStyleOptions.Pascal], [AcronymStyleOptions.Camel, AcronymStyleOptions.Camel], - [AcronymStyleOptions.Lower, AcronymStyleOptions.Lower] + [AcronymStyleOptions.Lower, AcronymStyleOptions.Lower], ], defaultOption, - "secondary" + "secondary", ); }; -export function acronymStyle(style: AcronymStyleOptions): (s: string) => string { - const options: { [key: string]: (s: string) => string } = { +export function acronymStyle (style: AcronymStyleOptions): (s: string) => string { + const options: { [key: string]: (s: string) => string, } = { [AcronymStyleOptions.Pascal]: allUpperWordStyle, [AcronymStyleOptions.Camel]: firstUpperWordStyle, [AcronymStyleOptions.Original]: originalWord, - [AcronymStyleOptions.Lower]: allLowerWordStyle + [AcronymStyleOptions.Lower]: allLowerWordStyle, }; return options[style]; diff --git a/packages/quicktype-core/src/support/Chance.ts b/packages/quicktype-core/src/support/Chance.ts index 5a368d7e8..72b58a0fb 100644 --- a/packages/quicktype-core/src/support/Chance.ts +++ b/packages/quicktype-core/src/support/Chance.ts @@ -34,20 +34,26 @@ email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) */ class MersenneTwister { - private N: number; - private M: number; - private MATRIX_A: number; - private UPPER_MASK: number; - private LOWER_MASK: number; + private readonly N: number; + + private readonly M: number; + + private readonly MATRIX_A: number; + + private readonly UPPER_MASK: number; + + private readonly LOWER_MASK: number; private mt: number[]; + private mti: number; - constructor(seed: number) { + constructor (seed: number) { if (seed === undefined) { // kept random number same size as time used previously to ensure no unexpected results downstream seed = Math.floor(Math.random() * Math.pow(10, 13)); } + /* Period parameters */ this.N = 624; this.M = 397; @@ -62,12 +68,12 @@ class MersenneTwister { } /* initializes mt[N] with a seed */ - private init_genrand(s: number) { + private init_genrand (s: number) { this.mt[0] = s >>> 0; for (this.mti = 1; this.mti < this.N; this.mti++) { - s = this.mt[this.mti - 1] ^ (this.mt[this.mti - 1] >>> 30); + s = this.mt[this.mti - 1] ^ this.mt[this.mti - 1] >>> 30; this.mt[this.mti] = - ((((s & 0xffff0000) >>> 16) * 1812433253) << 16) + (s & 0x0000ffff) * 1812433253 + this.mti; + (((s & 0xffff0000) >>> 16) * 1812433253 << 16) + (s & 0x0000ffff) * 1812433253 + this.mti; /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ /* In the previous versions, MSBs of the seed affect */ /* only MSBs of the array mt[]. */ @@ -78,9 +84,9 @@ class MersenneTwister { } /* generates a random number on [0,0xffffffff]-interval */ - private genrand_int32() { + private genrand_int32 () { let y; - let mag01 = new Array(0x0, this.MATRIX_A); + let mag01 = [0x0, this.MATRIX_A]; /* mag01[x] = x * MATRIX_A for x=0,1 */ if (this.mti >= this.N) { @@ -91,16 +97,19 @@ class MersenneTwister { /* if init_genrand() has not been called, */ this.init_genrand(5489); /* a default initial seed is used */ } + for (kk = 0; kk < this.N - this.M; kk++) { - y = (this.mt[kk] & this.UPPER_MASK) | (this.mt[kk + 1] & this.LOWER_MASK); - this.mt[kk] = this.mt[kk + this.M] ^ (y >>> 1) ^ mag01[y & 0x1]; + y = this.mt[kk] & this.UPPER_MASK | this.mt[kk + 1] & this.LOWER_MASK; + this.mt[kk] = this.mt[kk + this.M] ^ y >>> 1 ^ mag01[y & 0x1]; } + for (; kk < this.N - 1; kk++) { - y = (this.mt[kk] & this.UPPER_MASK) | (this.mt[kk + 1] & this.LOWER_MASK); - this.mt[kk] = this.mt[kk + (this.M - this.N)] ^ (y >>> 1) ^ mag01[y & 0x1]; + y = this.mt[kk] & this.UPPER_MASK | this.mt[kk + 1] & this.LOWER_MASK; + this.mt[kk] = this.mt[kk + (this.M - this.N)] ^ y >>> 1 ^ mag01[y & 0x1]; } - y = (this.mt[this.N - 1] & this.UPPER_MASK) | (this.mt[0] & this.LOWER_MASK); - this.mt[this.N - 1] = this.mt[this.M - 1] ^ (y >>> 1) ^ mag01[y & 0x1]; + + y = this.mt[this.N - 1] & this.UPPER_MASK | this.mt[0] & this.LOWER_MASK; + this.mt[this.N - 1] = this.mt[this.M - 1] ^ y >>> 1 ^ mag01[y & 0x1]; this.mti = 0; } @@ -109,15 +118,15 @@ class MersenneTwister { /* Tempering */ y ^= y >>> 11; - y ^= (y << 7) & 0x9d2c5680; - y ^= (y << 15) & 0xefc60000; + y ^= y << 7 & 0x9d2c5680; + y ^= y << 15 & 0xefc60000; y ^= y >>> 18; return y >>> 0; } /* generates a random number on [0,1)-real-interval */ - random() { + random () { return this.genrand_int32() * (1.0 / 4294967296.0); /* divided by 2^32 */ } @@ -125,14 +134,14 @@ class MersenneTwister { // https://github.com/chancejs/chancejs export class Chance { - private mt: MersenneTwister; + private readonly mt: MersenneTwister; - constructor(readonly seed: number) { + constructor (readonly seed: number) { // If no generator function was provided, use our MT this.mt = new MersenneTwister(this.seed); } - random(): number { + random (): number { return this.mt.random(); } @@ -147,7 +156,7 @@ export class Chance { * @returns {Number} a single random integer number * @throws {RangeError} min cannot be greater than max */ - integer(options: { min: number; max: number }): number { + integer (options: { max: number, min: number, }): number { return Math.floor(this.random() * (options.max - options.min + 1) + options.min); } @@ -162,7 +171,7 @@ export class Chance { * @returns {Number} a single random integer number * @throws {RangeError} min cannot be greater than max */ - natural(options: { max: number }): number { + natural (options: { max: number, }): number { return this.integer({ min: 0, max: options.max }); } @@ -170,21 +179,22 @@ export class Chance { if (arr.length === 0) { throw new RangeError("Chance: Cannot pick() from an empty array"); } + return arr[this.natural({ max: arr.length - 1 })]; } - animal(): string { + animal (): string { // if user does not put in any animal type, will return a random animal regardless const animalTypeArray = ["desert", "forest", "ocean", "zoo", "farm", "pet", "grassland"]; return this.pick(animals[this.pick(animalTypeArray)]); } - city(): string { + city (): string { return this.pick(cities); } } -const animals: { [kind: string]: string[] } = { +const animals: { [kind: string]: string[], } = { // list of ocean animals comes from https://owlcation.com/stem/list-of-ocean-animals ocean: [ "Acantharea", @@ -479,7 +489,7 @@ const animals: { [kind: string]: string[] } = { "Yellow Tube Sponge", "Yellowfin Tuna", "Zebrashark", - "Zooplankton" + "Zooplankton", ], // list of desert, grassland, and forest animals comes from http://www.skyenimals.com/ desert: [ @@ -572,7 +582,7 @@ const animals: { [kind: string]: string[] } = { "Vulture", "Waxwing", "Xerus", - "Zebra" + "Zebra", ], grassland: [ "Aardvark", @@ -715,7 +725,7 @@ const animals: { [kind: string]: string[] } = { "Thornbill", "Thrush", "Toad", - "Tortoise" + "Tortoise", ], forest: [ "Agouti", @@ -911,7 +921,7 @@ const animals: { [kind: string]: string[] } = { "Wolf", "Wombat", "Woodchuck", - "Woodpecker" + "Woodpecker", ], // list of farm animals comes from https://www.buzzle.com/articles/farm-animals-list.html farm: [ @@ -942,7 +952,7 @@ const animals: { [kind: string]: string[] } = { "Silkworm", "Turkey", "Yak", - "Zebu" + "Zebu", ], // list of pet animals comes from https://www.dogbreedinfo.com/pets/pet.htm pet: [ @@ -988,7 +998,7 @@ const animals: { [kind: string]: string[] } = { "Sugar Gliders", "Tarantula", "Turkeys", - "Turtles" + "Turtles", ], // list of zoo animals comes from https://bronxzoo.com/animals zoo: [ @@ -1058,8 +1068,8 @@ const animals: { [kind: string]: string[] } = { "Tufted Puffin", "White Cheeked Gibbon", "White-throated Bee Eater", - "Zebra" - ] + "Zebra", + ], }; // Source: https://en.wikipedia.org/wiki/List_of_population_centers_by_latitude @@ -2160,5 +2170,5 @@ const cities: string[] = [ "Villa Las Estrellas", "Esperanza", "Rothera", - "Concordia" + "Concordia", ]; diff --git a/packages/quicktype-core/src/support/Comments.ts b/packages/quicktype-core/src/support/Comments.ts index 3599cf133..d7d8a5194 100644 --- a/packages/quicktype-core/src/support/Comments.ts +++ b/packages/quicktype-core/src/support/Comments.ts @@ -1,17 +1,21 @@ -import { Sourcelike } from "../Source"; +import { type Sourcelike } from "../Source"; -export type CommentOptions = { - lineStart?: string; - lineEnd?: string; - beforeComment?: string; +export interface CommentOptions { afterComment?: string; + beforeComment?: string; firstLineStart?: string; -}; + lineEnd?: string; + lineStart?: string; +} -type DescriptionBlockCommentConfig = { descriptionBlock: Sourcelike[] }; -type InlineCommentConfig = { lines: Sourcelike[] }; +interface DescriptionBlockCommentConfig { + descriptionBlock: Sourcelike[]; +} +interface InlineCommentConfig { + lines: Sourcelike[]; +} type CustomCommentConfig = CommentOptions & { - customLines: Sourcelike[]; + customLines: Sourcelike[], }; export type CommentConfig = DescriptionBlockCommentConfig | InlineCommentConfig | CustomCommentConfig; diff --git a/packages/quicktype-core/src/support/Converters.ts b/packages/quicktype-core/src/support/Converters.ts index 4231237d3..a06301747 100644 --- a/packages/quicktype-core/src/support/Converters.ts +++ b/packages/quicktype-core/src/support/Converters.ts @@ -1,19 +1,19 @@ import { EnumOption } from "../RendererOptions"; export enum ConvertersOptions { - TopLevel = "top-level", - AllObjects = "all-objects" + AllObjects = "all-objects", + TopLevel = "top-level" } -export function convertersOption() { +export function convertersOption () { return new EnumOption( "converters", "Which converters to generate (top-level by default)", [ [ConvertersOptions.TopLevel, ConvertersOptions.TopLevel], - [ConvertersOptions.AllObjects, ConvertersOptions.AllObjects] + [ConvertersOptions.AllObjects, ConvertersOptions.AllObjects], ], ConvertersOptions.TopLevel, - "secondary" + "secondary", ); } diff --git a/packages/quicktype-core/src/support/Strings.ts b/packages/quicktype-core/src/support/Strings.ts index 8e2e91969..78e1ad378 100644 --- a/packages/quicktype-core/src/support/Strings.ts +++ b/packages/quicktype-core/src/support/Strings.ts @@ -12,9 +12,9 @@ export type NamingStyle = import unicode from "unicode-properties"; -function computeAsciiMap(mapper: (codePoint: number) => string): { - charStringMap: string[]; - charNoEscapeMap: number[]; +function computeAsciiMap (mapper: (codePoint: number) => string): { + charNoEscapeMap: number[], + charStringMap: string[], } { const charStringMap: string[] = []; const charNoEscapeMap: number[] = []; @@ -25,6 +25,7 @@ function computeAsciiMap(mapper: (codePoint: number) => string): { if (result === String.fromCharCode(i)) { noEscape = 1; } + charStringMap.push(result); charNoEscapeMap.push(noEscape); } @@ -34,21 +35,22 @@ function computeAsciiMap(mapper: (codePoint: number) => string): { type CodePointPredicate = (codePoint: number) => boolean; -function precomputedCodePointPredicate(p: CodePointPredicate): CodePointPredicate { +function precomputedCodePointPredicate (p: CodePointPredicate): CodePointPredicate { const asciiResults: boolean[] = []; for (let cp = 0; cp < 128; cp++) { asciiResults.push(p(cp)); } + return function (cp: number) { return cp < 128 ? asciiResults[cp] : p(cp); }; } // FIXME: This is a copy of code in src/Data/String/Util.js -export function utf16ConcatMap(mapper: (utf16Unit: number) => string): (s: string) => string { +export function utf16ConcatMap (mapper: (utf16Unit: number) => string): (s: string) => string { const { charStringMap, charNoEscapeMap } = computeAsciiMap(mapper); - return function stringConcatMap_inner(s: string): string { + return function stringConcatMap_inner (s: string): string { let cs: string[] | null = null; let start = 0; let i = 0; @@ -67,6 +69,7 @@ export function utf16ConcatMap(mapper: (utf16Unit: number) => string): (s: strin start = i + 1; } + i++; } @@ -78,18 +81,18 @@ export function utf16ConcatMap(mapper: (utf16Unit: number) => string): (s: strin }; } -function isHighSurrogate(cc: number): boolean { +function isHighSurrogate (cc: number): boolean { return cc >= 0xd800 && cc <= 0xdbff; } -function isLowSurrogate(cc: number): boolean { +function isLowSurrogate (cc: number): boolean { return cc >= 0xdc00 && cc <= 0xdfff; } -export function utf32ConcatMap(mapper: (codePoint: number) => string): (s: string) => string { +export function utf32ConcatMap (mapper: (codePoint: number) => string): (s: string) => string { const { charStringMap, charNoEscapeMap } = computeAsciiMap(mapper); - return function stringConcatMap_inner(s: string): string { + return function stringConcatMap_inner (s: string): string { let cs: string[] | null = null; let start = 0; let i = 0; @@ -118,6 +121,7 @@ export function utf32ConcatMap(mapper: (codePoint: number) => string): (s: strin start = i + 1; } + i++; } @@ -129,15 +133,15 @@ export function utf32ConcatMap(mapper: (codePoint: number) => string): (s: strin }; } -export function utf16LegalizeCharacters(isLegal: (utf16Unit: number) => boolean): (s: string) => string { - return utf16ConcatMap(u => (isLegal(u) ? String.fromCharCode(u) : "")); +export function utf16LegalizeCharacters (isLegal: (utf16Unit: number) => boolean): (s: string) => string { + return utf16ConcatMap(u => isLegal(u) ? String.fromCharCode(u) : ""); } -export function legalizeCharacters(isLegal: (codePoint: number) => boolean): (s: string) => string { - return utf32ConcatMap(u => (u <= 0xffff && isLegal(u) ? String.fromCharCode(u) : "")); +export function legalizeCharacters (isLegal: (codePoint: number) => boolean): (s: string) => string { + return utf32ConcatMap(u => u <= 0xffff && isLegal(u) ? String.fromCharCode(u) : ""); } -export function repeatString(s: string, n: number): string { +export function repeatString (s: string, n: number): string { assert(n >= 0, "Cannot repeat a string a negative number of times"); if (n === 0) return ""; @@ -149,21 +153,23 @@ export function repeatString(s: string, n: number): string { if (n % 2 !== 0) { result += s; } + n = Math.floor(n / 2); if (n > 0) { s += s; } } while (n > 0); + return result; } -export function intToHex(i: number, width: number): string { +export function intToHex (i: number, width: number): string { let str = i.toString(16); if (str.length >= width) return str; return repeatString("0", width - str.length) + str; } -export function standardUnicodeHexEscape(codePoint: number): string { +export function standardUnicodeHexEscape (codePoint: number): string { if (codePoint <= 0xffff) { return "\\u" + intToHex(codePoint, 4); } else { @@ -171,16 +177,16 @@ export function standardUnicodeHexEscape(codePoint: number): string { } } -export function escapeNonPrintableMapper( +export function escapeNonPrintableMapper ( printablePredicate: (codePoint: number) => boolean, - escaper: (codePoint: number) => string + escaper: (codePoint: number) => string, ): (u: number) => string { - function mapper(u: number): string { + function mapper (u: number): string { switch (u) { case 0x5c: return "\\\\"; case 0x22: - return '\\"'; + return "\\\""; case 0x0a: return "\\n"; case 0x09: @@ -189,16 +195,18 @@ export function escapeNonPrintableMapper( if (printablePredicate(u)) { return String.fromCharCode(u); } + return escaper(u); } } + return mapper; } export const utf16StringEscape = utf16ConcatMap(escapeNonPrintableMapper(isPrintable, standardUnicodeHexEscape)); export const stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, standardUnicodeHexEscape)); -export function isPrintable(codePoint: number): boolean { +export function isPrintable (codePoint: number): boolean { if (codePoint > 0xffff) return false; const category = unicode.getCategory(codePoint); return ( @@ -225,91 +233,92 @@ export function isPrintable(codePoint: number): boolean { "Pi", "Nl", "Mn", - "Lo" - ].indexOf(category) >= 0 + "Lo", + ].includes(category) ); } -export function isAscii(codePoint: number): boolean { +export function isAscii (codePoint: number): boolean { return codePoint < 128; } -export function isLetter(codePoint: number): boolean { +export function isLetter (codePoint: number): boolean { const category = unicode.getCategory(codePoint); // FIXME: Include Letter, modifier (Lm)? - return ["Lu", "Ll", "Lt", "Lo"].indexOf(category) >= 0; + return ["Lu", "Ll", "Lt", "Lo"].includes(category); } -export function isDigit(codePoint: number): boolean { +export function isDigit (codePoint: number): boolean { const category = unicode.getCategory(codePoint); - return ["Nd"].indexOf(category) >= 0; + return ["Nd"].includes(category); } -export function isNumeric(codePoint: number): boolean { +export function isNumeric (codePoint: number): boolean { const category = unicode.getCategory(codePoint); - return ["No", "Nd", "Nl"].indexOf(category) >= 0; + return ["No", "Nd", "Nl"].includes(category); } -export function isLetterOrDigit(codePoint: number): boolean { +export function isLetterOrDigit (codePoint: number): boolean { return isLetter(codePoint) || isDigit(codePoint); } -export function isLetterOrUnderscore(codePoint: number): boolean { +export function isLetterOrUnderscore (codePoint: number): boolean { return isLetter(codePoint) || codePoint === 0x5f; } -export function isLetterOrUnderscoreOrDigit(codePoint: number): boolean { +export function isLetterOrUnderscoreOrDigit (codePoint: number): boolean { return isLetterOrUnderscore(codePoint) || isDigit(codePoint); } -export function isWordCharacter(codePoint: number): boolean { +export function isWordCharacter (codePoint: number): boolean { return isLetter(codePoint) || isDigit(codePoint); } -export function trimEnd(str: string): string { +export function trimEnd (str: string): string { const l = str.length; let firstWS = l; for (let i = l - 1; i >= 0; i--) { if (!unicode.isWhiteSpace(str.charCodeAt(i))) break; firstWS = i; } + if (firstWS === l) return str; return str.slice(0, firstWS); } -function modifyFirstChar(f: (c: string) => string, s: string): string { +function modifyFirstChar (f: (c: string) => string, s: string): string { if (s === "") return s; return f(s[0]) + s.slice(1); } -export function capitalize(str: string): string { +export function capitalize (str: string): string { return modifyFirstChar(c => c.toUpperCase(), str); } -export function decapitalize(str: string): string { +export function decapitalize (str: string): string { return modifyFirstChar(c => c.toLowerCase(), str); } const wordSeparatorRegex = /[-_. ]+/; -export function pascalCase(str: string): string { +export function pascalCase (str: string): string { const words = str.split(wordSeparatorRegex).map(capitalize); return words.join(""); } -export function camelCase(str: string): string { +export function camelCase (str: string): string { return decapitalize(pascalCase(str)); } -export function snakeCase(str: string): string { +export function snakeCase (str: string): string { const words = splitIntoWords(str).map(({ word }) => word.toLowerCase()); return words.join("_"); } -export function startWithLetter( +export function startWithLetter ( isAllowedStart: (codePoint: number) => boolean, // FIXME: technically, this operates on UTF16 units upper: boolean, - str: string + str: string, ): string { const modify = upper ? capitalize : decapitalize; if (str === "") return modify("empty"); @@ -319,10 +328,10 @@ export function startWithLetter( const knownAcronyms = new Set(acronyms); -export type WordInName = { - word: string; +export interface WordInName { isAcronym: boolean; -}; + word: string; +} const fastIsWordCharacter = precomputedCodePointPredicate(isWordCharacter); const fastIsNonWordCharacter = precomputedCodePointPredicate(cp => !isWordCharacter(cp)); @@ -331,22 +340,23 @@ export const fastIsUpperCase = precomputedCodePointPredicate(cp => unicode.isUpp const fastNonLetter = precomputedCodePointPredicate(cp => !unicode.isLowerCase(cp) && !unicode.isUpperCase(cp)); const fastIsDigit = precomputedCodePointPredicate(isDigit); -export function splitIntoWords(s: string): WordInName[] { +export function splitIntoWords (s: string): WordInName[] { // [start, end, allUpper] - const intervals: [number, number, boolean][] = []; + const intervals: Array<[number, number, boolean]> = []; let intervalStart: number | undefined = undefined; const len = s.length; let i = 0; let lastLowerCaseIndex: number | undefined = undefined; - function atEnd(): boolean { + function atEnd (): boolean { return i >= len; } - function currentCodePoint(): number { + + function currentCodePoint (): number { return defined(s.codePointAt(i)); } - function skipWhile(p: (codePoint: number) => boolean): void { + function skipWhile (p: (codePoint: number) => boolean): void { while (!atEnd()) { const cp = currentCodePoint(); if (!p(cp)) break; @@ -355,31 +365,36 @@ export function splitIntoWords(s: string): WordInName[] { } } - function skipNonWord(): void { + function skipNonWord (): void { skipWhile(fastIsNonWordCharacter); } - function skipLowerCase(): void { + + function skipLowerCase (): void { skipWhile(fastIsLowerCase); } - function skipUpperCase(): void { + + function skipUpperCase (): void { skipWhile(fastIsUpperCase); } - function skipNonLetter(): void { + + function skipNonLetter (): void { skipWhile(fastNonLetter); } - function skipDigits(): void { + + function skipDigits (): void { skipWhile(fastIsDigit); } - function startInterval(): void { + function startInterval (): void { assert(intervalStart === undefined, "Interval started before last one was committed"); intervalStart = i; } - function commitInterval(): void { + function commitInterval (): void { if (intervalStart === undefined) { return panic("Tried to commit interval without starting one"); } + assert(i > intervalStart, "Interval must be non-empty"); // FIXME: This is a hack to avoid splitting up surrogates. We shouldn't // look at surrogates individually in the first place. When we @@ -389,15 +404,17 @@ export function splitIntoWords(s: string): WordInName[] { if (!atEnd() && isLowSurrogate(currentCodePoint())) { i += 1; } + const allUpper = lastLowerCaseIndex === undefined || lastLowerCaseIndex < intervalStart; intervals.push([intervalStart, i, allUpper]); intervalStart = undefined; } - function intervalLength(): number { + function intervalLength (): number { if (intervalStart === undefined) { return panic("Tried to get interval length without starting one"); } + return i - intervalStart; } @@ -425,6 +442,7 @@ export function splitIntoWords(s: string): WordInName[] { if (fastIsWordCharacter(currentCodePoint())) { i -= 1; } + commitInterval(); } } else { @@ -436,39 +454,40 @@ export function splitIntoWords(s: string): WordInName[] { const words: WordInName[] = []; for (const [start, end, allUpper] of intervals) { const word = s.slice(start, end); - const isAcronym = (lastLowerCaseIndex !== undefined && allUpper) || knownAcronyms.has(word.toLowerCase()); + const isAcronym = lastLowerCaseIndex !== undefined && allUpper || knownAcronyms.has(word.toLowerCase()); words.push({ word, isAcronym }); } + return words; } export type WordStyle = (word: string) => string; -export function firstUpperWordStyle(s: string): string { +export function firstUpperWordStyle (s: string): string { assert(s.length > 0, "Cannot style an empty string"); return s[0].toUpperCase() + s.slice(1).toLowerCase(); } -export function allUpperWordStyle(s: string): string { +export function allUpperWordStyle (s: string): string { return s.toUpperCase(); } -export function originalWord(s: string): string { +export function originalWord (s: string): string { return s; } -export function allLowerWordStyle(s: string): string { +export function allLowerWordStyle (s: string): string { return s.toLowerCase(); } -function styleWord(style: WordStyle, word: string): string { +function styleWord (style: WordStyle, word: string): string { assert(word.length > 0, "Tried to style an empty word"); const result = style(word); assert(result.length > 0, "Word style must not make word empty"); return result; } -export function combineWords( +export function combineWords ( words: WordInName[], removeInvalidCharacters: (s: string) => string, firstWordStyle: WordStyle, @@ -476,7 +495,7 @@ export function combineWords( firstWordAcronymStyle: WordStyle, restAcronymStyle: WordStyle, separator: string, - isStartCharacter: (codePoint: number) => boolean + isStartCharacter: (codePoint: number) => boolean, ): string { const legalizedWords: WordInName[] = []; for (const w of words) { @@ -487,7 +506,7 @@ export function combineWords( if (legalizedWords.length === 0) { const validEmpty = removeInvalidCharacters("empty"); - assert(validEmpty.length > 0, 'Word "empty" is invalid in target language'); + assert(validEmpty.length > 0, "Word \"empty\" is invalid in target language"); legalizedWords.push({ word: validEmpty, isAcronym: false }); } @@ -498,11 +517,11 @@ export function combineWords( let restWords: WordInName[]; if (!isStartCharacter(defined(styledFirstWord.codePointAt(0)))) { const validThe = removeInvalidCharacters("the"); - assert(validThe.length > 0, 'Word "the" is invalid in the target language'); + assert(validThe.length > 0, "Word \"the\" is invalid in the target language"); const styledThe = styleWord(firstWordStyle, validThe); assert( isStartCharacter(defined(styledThe.codePointAt(0))), - 'The first character of styling "the" is not a start character' + "The first character of styling \"the\" is not a start character", ); styledWords.push(styledThe); restWords = legalizedWords; @@ -519,15 +538,15 @@ export function combineWords( return styledWords.join(separator); } -export function addPrefixIfNecessary(prefix: string, name: string): string { +export function addPrefixIfNecessary (prefix: string, name: string): string { // Take care not to doubly-prefix type names return name.startsWith(prefix) ? name : prefix + name; } -export function makeNameStyle( +export function makeNameStyle ( namingStyle: NamingStyle, legalizeName: (name: string) => string, - prefix?: string + prefix?: string, ): (rawName: string) => string { let separator: string; let firstWordStyle: WordStyle; @@ -551,6 +570,7 @@ export function makeNameStyle( } else { separator = "_"; } + switch (namingStyle) { case "pascal": case "pascal-upper-acronyms": @@ -581,7 +601,7 @@ export function makeNameStyle( firstWordAcronymStyle, restAcronymStyle, separator, - isLetterOrUnderscore + isLetterOrUnderscore, ); if (prefix !== undefined) { diff --git a/packages/quicktype-core/src/support/Support.ts b/packages/quicktype-core/src/support/Support.ts index 810219df8..ab67bbefc 100644 --- a/packages/quicktype-core/src/support/Support.ts +++ b/packages/quicktype-core/src/support/Support.ts @@ -3,14 +3,17 @@ import * as pako from "pako"; import { messageError } from "../Messages"; import * as YAML from "yaml"; -export type StringMap = { [name: string]: any }; +export interface StringMap { + [name: string]: any; +} -export function isStringMap(x: any): x is StringMap; -export function isStringMap(x: any, checkValue: (v: any) => v is T): x is { [name: string]: T }; -export function isStringMap(x: any, checkValue?: (v: any) => v is T): boolean { +export function isStringMap (x: any): x is StringMap; +export function isStringMap (x: any, checkValue: (v: any) => v is T): x is { [name: string]: T, }; +export function isStringMap (x: any, checkValue?: (v: any) => v is T): boolean { if (typeof x !== "object" || Array.isArray(x) || x === null) { return false; } + if (checkValue !== undefined) { for (const k of Object.getOwnPropertyNames(x)) { const v = x[k]; @@ -19,26 +22,28 @@ export function isStringMap(x: any, checkValue?: (v: any) => v is T): boolean } } } + return true; } -export function checkString(x: any): x is string { +export function checkString (x: any): x is string { return typeof x === "string"; } -export function checkStringMap(x: any): StringMap; -export function checkStringMap(x: any, checkValue: (v: any) => v is T): { [name: string]: T }; -export function checkStringMap(x: any, checkValue?: (v: any) => v is T): StringMap { +export function checkStringMap (x: any): StringMap; +export function checkStringMap (x: any, checkValue: (v: any) => v is T): { [name: string]: T, }; +export function checkStringMap (x: any, checkValue?: (v: any) => v is T): StringMap { if (isStringMap(x, checkValue as any)) return x; return panic(`Value must be an object, but is ${x}`); } -export function checkArray(x: any): any[]; -export function checkArray(x: any, checkItem: (v: any) => v is T): T[]; -export function checkArray(x: any, checkItem?: (v: any) => v is T): T[] { +export function checkArray (x: any): any[]; +export function checkArray (x: any, checkItem: (v: any) => v is T): T[]; +export function checkArray (x: any, checkItem?: (v: any) => v is T): T[] { if (!Array.isArray(x)) { return panic(`Value must be an array, but is ${x}`); } + if (checkItem !== undefined) { for (const v of x) { if (!checkItem(v)) { @@ -46,71 +51,76 @@ export function checkArray(x: any, checkItem?: (v: any) => v is T): T[] { } } } + return x; } -export function defined(x: T | undefined): T { +export function defined (x: T | undefined): T { if (x !== undefined) return x; return panic("Defined value expected, but got undefined"); } -export function nonNull(x: T | null): T { +export function nonNull (x: T | null): T { if (x !== null) return x; return panic("Non-null value expected, but got null"); } -export function assertNever(x: never): never { +export function assertNever (x: never): never { return messageError("InternalError", { message: `Unexpected object ${x as any}` }); } -export function assert(condition: boolean, message = "Assertion failed"): void { +export function assert (condition: boolean, message = "Assertion failed"): void { if (!condition) { return messageError("InternalError", { message }); } } -export function panic(message: string): never { +export function panic (message: string): never { return messageError("InternalError", { message }); } -export function mustNotHappen(): never { +export function mustNotHappen (): never { return panic("This must not happen"); } -export function repeated(n: number, value: T): T[] { +export function repeated (n: number, value: T): T[] { const arr: T[] = []; for (let i = 0; i < n; i++) { arr.push(value); } + return arr; } -export function repeatedCall(n: number, producer: () => T): T[] { +export function repeatedCall (n: number, producer: () => T): T[] { const arr: T[] = []; for (let i = 0; i < n; i++) { arr.push(producer()); } + return arr; } -export function errorMessage(e: any): string { +export function errorMessage (e: any): string { if (e instanceof Error) { return e.message; } + return e.toString(); } -export function inflateBase64(encoded: string): string { +export function inflateBase64 (encoded: string): string { const bytes = Base64.atob(encoded); return pako.inflate(bytes, { to: "string" }); } -export function parseJSON(text: string, description: string, address = ""): any { +export function parseJSON (text: string, description: string, address = ""): any { try { // https://gist.github.com/pbakondy/f5045eff725193dad9c7 if (text.charCodeAt(0) === 0xfeff) { text = text.slice(1); } + return YAML.parse(text); } catch (e) { let message: string; @@ -125,11 +135,11 @@ export function parseJSON(text: string, description: string, address = " nn.typeRef).add(builder.getPrimitiveType("null"))); @@ -104,24 +109,26 @@ function makeNullable( // union if the type is modified to be non-nullable. That means that the union // (and the null) might be left unreachable in the graph. Provenance checking // won't work in this case, which is why it's disabled in testing for GraphQL. -function removeNull(builder: TypeBuilder, tref: TypeRef): TypeRef { +function removeNull (builder: TypeBuilder, tref: TypeRef): TypeRef { const t = derefTypeRef(tref, builder.typeGraph); if (!(t instanceof UnionType)) { return tref; } + const nonNulls = removeNullFromUnion(t)[1]; const first = iterableFirst(nonNulls); if (first) { if (nonNulls.size === 1) return first.typeRef; return builder.getUnionType( t.getAttributes(), - setMap(nonNulls, nn => nn.typeRef) + setMap(nonNulls, nn => nn.typeRef), ); } + return panic("Trying to remove null results in empty union."); } -function makeScalar(builder: TypeBuilder, ft: GQLType): TypeRef { +function makeScalar (builder: TypeBuilder, ft: GQLType): TypeRef { switch (ft.name) { case "Boolean": return builder.getPrimitiveType("bool"); @@ -135,40 +142,42 @@ function makeScalar(builder: TypeBuilder, ft: GQLType): TypeRef { } } -function hasOptionalDirectives(directives?: DirectiveNode[]): boolean { +function hasOptionalDirectives (directives?: DirectiveNode[]): boolean { if (!directives) return false; for (const d of directives) { const name = d.name.value; if (name === "include" || name === "skip") return true; } + return false; } interface Selection { - selection: SelectionNode; inType: GQLType; optional: boolean; + selection: SelectionNode; } -function expandSelectionSet(selectionSet: SelectionSetNode, inType: GQLType, optional: boolean): Selection[] { +function expandSelectionSet (selectionSet: SelectionSetNode, inType: GQLType, optional: boolean): Selection[] { return selectionSet.selections .reverse() .map(s => ({ selection: s, inType, optional: optional || hasOptionalDirectives(s.directives) })); } interface GQLSchema { - readonly types: { [name: string]: GQLType }; - readonly queryType: GQLType; readonly mutationType?: GQLType; + readonly queryType: GQLType; + readonly types: { [name: string]: GQLType, }; } class GQLQuery { private readonly _schema: GQLSchema; - private readonly _fragments: { [name: string]: FragmentDefinitionNode }; - readonly queries: ReadonlyArray; + private readonly _fragments: { [name: string]: FragmentDefinitionNode, }; + + readonly queries: readonly OperationDefinitionNode[]; - constructor(schema: GQLSchema, queryString: string) { + constructor (schema: GQLSchema, queryString: string) { this._schema = schema; this._fragments = {}; @@ -183,15 +192,16 @@ class GQLQuery { this._fragments[def.name.value] = def; } } + messageAssert(queries.length >= 1, "GraphQLNoQueriesDefined", {}); this.queries = queries; } - private makeIRTypeFromFieldNode = ( + private readonly makeIRTypeFromFieldNode = ( builder: TypeBuilder, fieldNode: FieldNode, fieldType: GQLType, - containingTypeName: string + containingTypeName: string, ): TypeRef => { let optional = hasOptionalDirectives(fieldNode.directives); let result: TypeRef; @@ -206,6 +216,7 @@ class GQLQuery { if (!fieldNode.selectionSet) { return panic("No selection set on object or interface"); } + return makeNullable( builder, this.makeIRTypeFromSelectionSet( @@ -213,16 +224,17 @@ class GQLQuery { fieldNode.selectionSet, fieldType, fieldNode.name.value, - containingTypeName + containingTypeName, ), fieldNode.name.value, null, - containingTypeName + containingTypeName, ); case TypeKind.ENUM: if (!fieldType.enumValues) { return panic("Enum type doesn't have values"); } + const values = fieldType.enumValues.map(ev => ev.name); let name: string; let fieldName: string | null; @@ -233,6 +245,7 @@ class GQLQuery { name = fieldNode.name.value; fieldName = null; } + optional = true; result = builder.getEnumType(makeNames(name, fieldName, containingTypeName), new Set(values)); break; @@ -243,43 +256,47 @@ class GQLQuery { if (!fieldType.ofType) { return panic("No type for list"); } + optional = true; result = builder.getArrayType( emptyTypeAttributes, - this.makeIRTypeFromFieldNode(builder, fieldNode, fieldType.ofType, containingTypeName) + this.makeIRTypeFromFieldNode(builder, fieldNode, fieldType.ofType, containingTypeName), ); break; case TypeKind.NON_NULL: if (!fieldType.ofType) { return panic("No type for non-null"); } + result = removeNull( builder, - this.makeIRTypeFromFieldNode(builder, fieldNode, fieldType.ofType, containingTypeName) + this.makeIRTypeFromFieldNode(builder, fieldNode, fieldType.ofType, containingTypeName), ); break; default: return assertNever(fieldType.kind); } + if (optional) { result = makeNullable(builder, result, fieldNode.name.value, null, containingTypeName); } + return result; }; - private getFragment = (name: string): FragmentDefinitionNode => { + private readonly getFragment = (name: string): FragmentDefinitionNode => { const fragment = this._fragments[name]; if (!fragment) return panic(`Fragment ${name} is not defined.`); return fragment; }; - private makeIRTypeFromSelectionSet = ( + private readonly makeIRTypeFromSelectionSet = ( builder: TypeBuilder, selectionSet: SelectionSetNode, gqlType: GQLType, containingFieldName: string | null, containingTypeName: string | null, - overrideName?: string + overrideName?: string, ): TypeRef => { if ( gqlType.kind !== TypeKind.OBJECT && @@ -288,9 +305,11 @@ class GQLQuery { ) { return panic("Type for selection set is not object, interface, or union."); } + if (!gqlType.name) { return panic("Object, interface, or union type doesn't have a name."); } + const nameOrOverride = overrideName || gqlType.name; const properties = new Map(); let selections = expandSelectionSet(selectionSet, gqlType, false); @@ -314,6 +333,7 @@ class GQLQuery { selections = selections.concat(expanded); break; } + case "InlineFragment": { // FIXME: support type conditions with discriminated unions const fragmentType = selection.typeCondition @@ -325,14 +345,16 @@ class GQLQuery { selections = selections.concat(expanded); break; } + default: assertNever(selection); } } + return builder.getClassType(makeNames(nameOrOverride, containingFieldName, containingTypeName), properties); }; - makeType(builder: TypeBuilder, query: OperationDefinitionNode, queryName: string): TypeRef { + makeType (builder: TypeBuilder, query: OperationDefinitionNode, queryName: string): TypeRef { if (query.operation === "query") { return this.makeIRTypeFromSelectionSet( builder, @@ -340,7 +362,7 @@ class GQLQuery { this._schema.queryType, null, queryName, - "data" + "data", ); } @@ -355,7 +377,7 @@ class GQLQuery { this._schema.mutationType, null, queryName, - "data" + "data", ); } @@ -364,13 +386,15 @@ class GQLQuery { } class GQLSchemaFromJSON implements GQLSchema { - readonly types: { [name: string]: GQLType } = {}; - // @ts-ignore: The constructor can return early, but only by throwing. + readonly types: { [name: string]: GQLType, } = {}; + + // @ts-expect-error: The constructor can return early, but only by throwing. readonly queryType: GQLType; - // @ts-ignore: The constructor can return early, but only by throwing. + + // @ts-expect-error: The constructor can return early, but only by throwing. readonly mutationType?: GQLType; - constructor(json: any) { + constructor (json: any) { const schema: GraphQLSchema = json.data; if (schema.__schema.queryType.name === null) { @@ -381,6 +405,7 @@ class GQLSchemaFromJSON implements GQLSchema { if (!t.name) return panic("No top-level type name given"); this.types[t.name] = { kind: t.kind, name: t.name, description: t.description }; } + for (const t of schema.__schema.types) { if (!t.name) return panic("This cannot happen"); const type = this.types[t.name]; @@ -392,6 +417,7 @@ class GQLSchemaFromJSON implements GQLSchema { if (queryType === undefined) { return panic("Query type not found."); } + // console.log(`query type ${queryType.name} is ${queryType.kind}`); this.queryType = queryType; @@ -411,30 +437,34 @@ class GQLSchemaFromJSON implements GQLSchema { this.mutationType = mutationType; } - private addTypeFields = (target: GQLType, source: GQLType): void => { + private readonly addTypeFields = (target: GQLType, source: GQLType): void => { if (source.fields) { target.fields = source.fields.map(f => { return { name: f.name, description: f.description, type: this.makeType(f.type), - args: f.args.map(this.makeInputValue) + args: f.args.map(this.makeInputValue), }; }); // console.log(`${target.name} has ${target.fields.length} fields`); } + if (source.interfaces) { target.interfaces = source.interfaces.map(this.makeType); // console.log(`${target.name} has ${target.interfaces.length} interfaces`); } + if (source.possibleTypes) { target.possibleTypes = source.possibleTypes.map(this.makeType); // console.log(`${target.name} has ${target.possibleTypes.length} possibleTypes`); } + if (source.inputFields) { target.inputFields = source.inputFields.map(this.makeInputValue); // console.log(`${target.name} has ${target.inputFields.length} inputFields`); } + if (source.enumValues) { target.enumValues = source.enumValues.map(ev => { return { name: ev.name, description: ev.description }; @@ -443,37 +473,38 @@ class GQLSchemaFromJSON implements GQLSchema { } }; - private makeInputValue = (iv: InputValue): InputValue => { + private readonly makeInputValue = (iv: InputValue): InputValue => { return { name: iv.name, description: iv.description, type: this.makeType(iv.type), - defaultValue: iv.defaultValue + defaultValue: iv.defaultValue, }; }; - private makeType = (t: GQLType): GQLType => { + private readonly makeType = (t: GQLType): GQLType => { if (t.name) { const namedType = this.types[t.name]; if (!namedType) return panic(`Type ${t.name} not found`); return namedType; } + if (!t.ofType) return panic(`Type of kind ${t.kind} has neither name nor ofType`); const type: GQLType = { kind: t.kind, description: t.description, - ofType: this.makeType(t.ofType) + ofType: this.makeType(t.ofType), }; this.addTypeFields(type, t); return type; }; } -function makeGraphQLQueryTypes( +function makeGraphQLQueryTypes ( topLevelName: string, builder: TypeBuilder, json: any, - queryString: string + queryString: string, ): Map { const schema = new GQLSchemaFromJSON(json); const query = new GQLQuery(schema, queryString); @@ -483,69 +514,77 @@ function makeGraphQLQueryTypes( if (types.has(queryName)) { return panic(`Duplicate query name ${queryName}`); } + const dataType = query.makeType(builder, odn, queryName); const dataOrNullType = builder.getUnionType( emptyTypeAttributes, - new Set([dataType, builder.getPrimitiveType("null")]) + new Set([dataType, builder.getPrimitiveType("null")]), ); const errorType = builder.getClassType( namesTypeAttributeKind.makeAttributes(TypeNames.make(new Set(["error"]), new Set(["graphQLError"]), false)), mapFromObject({ message: builder.makeClassProperty( builder.getStringType(emptyTypeAttributes, StringTypes.unrestricted), - false - ) - }) + false, + ), + }), ); const errorArray = builder.getArrayType( namesTypeAttributeKind.makeAttributes( - TypeNames.make(new Set(["errors"]), new Set(["graphQLErrors"]), false) + TypeNames.make(new Set(["errors"]), new Set(["graphQLErrors"]), false), ), - errorType + errorType, ); const t = builder.getClassType( makeNamesTypeAttributes(queryName, false), mapFromObject({ data: builder.makeClassProperty(dataOrNullType, false), - errors: builder.makeClassProperty(errorArray, true) - }) + errors: builder.makeClassProperty(errorArray, true), + }), ); types.set(queryName, t); } + return types; } -export type GraphQLSourceData = { name: string; schema: any; query: string }; +export interface GraphQLSourceData { + name: string; query: string; schema: any; +} -type GraphQLTopLevel = { schema: any; query: string }; +interface GraphQLTopLevel { + query: string; schema: any; +} export class GraphQLInput implements Input { readonly kind: string = "graphql"; + readonly needIR: boolean = true; + readonly needSchemaProcessing: boolean = false; private readonly _topLevels: Map = new Map(); - async addSource(source: GraphQLSourceData): Promise { + async addSource (source: GraphQLSourceData): Promise { this.addSourceSync(source); } - addSourceSync(source: GraphQLSourceData): void { + addSourceSync (source: GraphQLSourceData): void { this._topLevels.set(source.name, { schema: source.schema, - query: source.query + query: source.query, }); } - singleStringSchemaSource(): undefined { + singleStringSchemaSource (): undefined { return undefined; } - async addTypes(ctx: RunContext, typeBuilder: TypeBuilder): Promise { - return this.addTypesSync(ctx, typeBuilder); + async addTypes (ctx: RunContext, typeBuilder: TypeBuilder): Promise { + this.addTypesSync(ctx, typeBuilder); } - addTypesSync(_ctx: RunContext, typeBuilder: TypeBuilder): void { + addTypesSync (_ctx: RunContext, typeBuilder: TypeBuilder): void { for (const [name, { schema, query }] of this._topLevels) { const newTopLevels = makeGraphQLQueryTypes(name, typeBuilder, schema, query); for (const [actualName, t] of newTopLevels) { diff --git a/packages/quicktype-typescript-input/src/index.ts b/packages/quicktype-typescript-input/src/index.ts index 145cc50e1..47696ce83 100644 --- a/packages/quicktype-typescript-input/src/index.ts +++ b/packages/quicktype-typescript-input/src/index.ts @@ -1,13 +1,15 @@ import * as ts from "typescript"; -import { PartialArgs, generateSchema } from "@mark.probst/typescript-json-schema"; +import { type PartialArgs} from "@mark.probst/typescript-json-schema"; +import { generateSchema } from "@mark.probst/typescript-json-schema"; -import { defined, JSONSchemaSourceData, messageError } from "quicktype-core"; +import { type JSONSchemaSourceData} from "quicktype-core"; +import { defined, messageError } from "quicktype-core"; const settings: PartialArgs = { required: true, titles: true, topRef: true, - noExtraProps: true + noExtraProps: true, }; const compilerOptions: ts.CompilerOptions = { @@ -18,18 +20,18 @@ const compilerOptions: ts.CompilerOptions = { module: ts.ModuleKind.CommonJS, strictNullChecks: true, typeRoots: [], - rootDir: "." + rootDir: ".", }; // FIXME: We're stringifying and then parsing this schema again. Just pass around // the schema directly. -export function schemaForTypeScriptSources(sourceFileNames: string[]): JSONSchemaSourceData { +export function schemaForTypeScriptSources (sourceFileNames: string[]): JSONSchemaSourceData { const program = ts.createProgram(sourceFileNames, compilerOptions); const diagnostics = ts.getPreEmitDiagnostics(program); const error = diagnostics.find(d => d.category === ts.DiagnosticCategory.Error); if (error !== undefined) { return messageError("TypeScriptCompilerError", { - message: ts.flattenDiagnosticMessageText(error.messageText, "\n") + message: ts.flattenDiagnosticMessageText(error.messageText, "\n"), }); } @@ -49,7 +51,7 @@ export function schemaForTypeScriptSources(sourceFileNames: string[]): JSONSchem } const description = definition.description as string; - const matches = description.match(/#TopLevel/); + const matches = /#TopLevel/.exec(description); if (matches === null) { continue; } @@ -70,11 +72,14 @@ export function schemaForTypeScriptSources(sourceFileNames: string[]): JSONSchem } } } + if (uris.length === 0) { uris.push("#/definitions/"); } + if (topLevelName === undefined) { topLevelName = ""; } + return { schema: JSON.stringify(schema), name: topLevelName, uris, isConverted: true }; } diff --git a/src/CompressedJSONFromStream.ts b/src/CompressedJSONFromStream.ts index 84c6ffe6f..850da2fc1 100644 --- a/src/CompressedJSONFromStream.ts +++ b/src/CompressedJSONFromStream.ts @@ -1,8 +1,9 @@ -import { Readable } from "readable-stream"; -import { CompressedJSON, Value } from "quicktype-core"; +import { type Readable } from "readable-stream"; +import { type Value } from "quicktype-core"; +import { CompressedJSON } from "quicktype-core"; import { Parser } from "stream-json"; -const methodMap: { [name: string]: string } = { +const methodMap: { [name: string]: string, } = { startObject: "pushObjectContext", endObject: "finishObject", startArray: "pushArrayContext", @@ -14,13 +15,13 @@ const methodMap: { [name: string]: string } = { stringValue: "commitString", nullValue: "commitNull", trueValue: "handleTrueValue", - falseValue: "handleFalseValue" + falseValue: "handleFalseValue", }; export class CompressedJSONFromStream extends CompressedJSON { - async parse(readStream: Readable): Promise { + async parse (readStream: Readable): Promise { const combo = new Parser({ packKeys: true, packStrings: true }); - combo.on("data", (item: { name: string; value: string | undefined }) => { + combo.on("data", (item: { name: string, value: string | undefined, }) => { if (typeof methodMap[item.name] === "string") { (this as any)[methodMap[item.name]](item.value); } @@ -36,7 +37,7 @@ export class CompressedJSONFromStream extends CompressedJSON { readStream.setEncoding("utf8"); readStream.pipe(combo); readStream.resume(); - return promise; + return await promise; } protected handleStartNumber = (): void => { @@ -51,17 +52,17 @@ export class CompressedJSONFromStream extends CompressedJSON { } }; - protected handleEndNumber(): void { + protected handleEndNumber (): void { const isDouble = this.context.currentNumberIsDouble; this.popContext(); this.commitNumber(isDouble); } - protected handleTrueValue(): void { + protected handleTrueValue (): void { this.commitBoolean(true); } - protected handleFalseValue(): void { + protected handleFalseValue (): void { this.commitBoolean(false); } } diff --git a/src/GraphQLIntrospection.ts b/src/GraphQLIntrospection.ts index 71106b1df..b62122ec5 100644 --- a/src/GraphQLIntrospection.ts +++ b/src/GraphQLIntrospection.ts @@ -5,24 +5,26 @@ import { exceptionToString } from "@glideapps/ts-necessities"; import fetch from "cross-fetch"; // https://github.com/apollographql/apollo-codegen/blob/master/src/downloadSchema.ts -const defaultHeaders: { [name: string]: string } = { +const defaultHeaders: { [name: string]: string, } = { Accept: "application/json", - "Content-Type": "application/json" + "Content-Type": "application/json", }; const headerRegExp = /^([^:]+):\s*(.*)$/; -export async function introspectServer(url: string, method: string, headerStrings: string[]): Promise { - const headers: { [name: string]: string } = {}; +export async function introspectServer (url: string, method: string, headerStrings: string[]): Promise { + const headers: { [name: string]: string, } = {}; for (const name of Object.getOwnPropertyNames(defaultHeaders)) { headers[name] = defaultHeaders[name]; } + for (const str of headerStrings) { - const matches = str.match(headerRegExp); + const matches = headerRegExp.exec(str); if (matches === null) { return panic(`Not a valid HTTP header: "${str}"`); } + headers[matches[1]] = matches[2]; } @@ -31,7 +33,7 @@ export async function introspectServer(url: string, method: string, headerString const response = await fetch(url, { method, headers: headers, - body: JSON.stringify({ query: introspectionQuery }) + body: JSON.stringify({ query: introspectionQuery }), }); result = await response.json(); diff --git a/src/TypeSource.ts b/src/TypeSource.ts index cc693c4c9..ab0580889 100644 --- a/src/TypeSource.ts +++ b/src/TypeSource.ts @@ -1,7 +1,7 @@ -import { Readable } from "readable-stream"; +import { type Readable } from "readable-stream"; -import { JSONSourceData, JSONSchemaSourceData } from "quicktype-core"; -import { GraphQLSourceData } from "quicktype-graphql-input"; +import { type JSONSourceData, type JSONSchemaSourceData } from "quicktype-core"; +import { type GraphQLSourceData } from "quicktype-graphql-input"; export interface JSONTypeSource extends JSONSourceData { kind: "json"; diff --git a/src/URLGrammar.ts b/src/URLGrammar.ts index 5280846f0..25ac55c5c 100644 --- a/src/URLGrammar.ts +++ b/src/URLGrammar.ts @@ -1,9 +1,10 @@ import { panic, checkStringMap, checkArray } from "quicktype-core"; -function expand(json: any): string[] { +function expand (json: any): string[] { if (typeof json === "string") { return [json]; } + if (Array.isArray(json)) { let result: string[] = [""]; for (const j of json) { @@ -14,10 +15,13 @@ function expand(json: any): string[] { appended.push(a + b); } } + result = appended; } + return result; } + if (Object.prototype.hasOwnProperty.call(json, "oneOf")) { const options = checkArray(json.oneOf); const result: string[] = []; @@ -26,14 +30,16 @@ function expand(json: any): string[] { result.push(x); } } + return result; } + return panic(`Value is not a valid URL grammar: ${json}`); } -export function urlsFromURLGrammar(json: any): { [name: string]: string[] } { +export function urlsFromURLGrammar (json: any): { [name: string]: string[], } { const topLevelMap = checkStringMap(json); - const results: { [name: string]: string[] } = {}; + const results: { [name: string]: string[], } = {}; for (const name of Object.getOwnPropertyNames(topLevelMap)) { results[name] = expand(topLevelMap[name]); diff --git a/src/index.ts b/src/index.ts index 109161c79..710b5cc9e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,21 +2,23 @@ import * as fs from "fs"; import * as path from "path"; import * as _ from "lodash"; -import { Readable } from "readable-stream"; +import { type Readable } from "readable-stream"; import { hasOwnProperty, definedMap, withDefault, mapFromObject, mapMap } from "collection-utils"; import { exceptionToString } from "@glideapps/ts-necessities"; import { - Options, - RendererOptions, + type Options, + type RendererOptions, + type SerializedRenderResult, + type TargetLanguage, + type OptionDefinition, + type JSONSourceData} from "quicktype-core"; +import { getTargetLanguage, quicktypeMultiFile, - SerializedRenderResult, - TargetLanguage, languageNamed, InputData, JSONSchemaInput, - OptionDefinition, defaultTargetLanguages, IssueAnnotationData, panic, @@ -32,19 +34,18 @@ import { inferenceFlagNames, splitIntoWords, capitalize, - JSONSourceData, JSONInput, getStream, readableFromFileOrURL, readFromFileOrURL, - FetchingJSONSchemaStore + FetchingJSONSchemaStore, } from "quicktype-core"; import { schemaForTypeScriptSources } from "quicktype-typescript-input"; import { GraphQLInput } from "quicktype-graphql-input"; import { urlsFromURLGrammar } from "./URLGrammar"; import { introspectServer } from "./GraphQLIntrospection"; -import { JSONTypeSource, TypeSource, GraphQLTypeSource, SchemaTypeSource } from "./TypeSource"; +import { type JSONTypeSource, type TypeSource, type GraphQLTypeSource, type SchemaTypeSource } from "./TypeSource"; import { CompressedJSONFromStream } from "./CompressedJSONFromStream"; const stringToStream = require("string-to-stream"); @@ -57,53 +58,53 @@ const wordWrap: (s: string) => string = require("wordwrap")(90); const packageJSON = require("../package.json"); export interface CLIOptions { - lang: string; - topLevel: string; - src: string[]; - srcUrls?: string; - srcLang: string; + // We use this to access the inference flags + [option: string]: any; additionalSchema: string[]; - graphqlSchema?: string; + allPropertiesOptional: boolean; + alphabetizeProperties: boolean; + buildMarkovChain?: string; + debug?: string; graphqlIntrospect?: string; + graphqlSchema?: string; + help: boolean; httpHeader?: string[]; httpMethod?: string; - out?: string; - buildMarkovChain?: string; + lang: string; - alphabetizeProperties: boolean; - allPropertiesOptional: boolean; noRender: boolean; + out?: string; + quiet: boolean; rendererOptions: RendererOptions; - help: boolean; - quiet: boolean; - version: boolean; - debug?: string; + src: string[]; + srcLang: string; + srcUrls?: string; telemetry?: string; + topLevel: string; - // We use this to access the inference flags - [option: string]: any; + version: boolean; } const defaultDefaultTargetLanguageName = "go"; -async function sourceFromFileOrUrlArray( +async function sourceFromFileOrUrlArray ( name: string, filesOrUrls: string[], - httpHeaders?: string[] + httpHeaders?: string[], ): Promise { - const samples = await Promise.all(filesOrUrls.map(file => readableFromFileOrURL(file, httpHeaders))); + const samples = await Promise.all(filesOrUrls.map(async file => await readableFromFileOrURL(file, httpHeaders))); return { kind: "json", name, samples }; } -function typeNameFromFilename(filename: string): string { +function typeNameFromFilename (filename: string): string { const name = path.basename(filename); return name.substring(0, name.lastIndexOf(".")); } -async function samplesFromDirectory(dataDir: string, httpHeaders?: string[]): Promise { - async function readFilesOrURLsInDirectory(d: string): Promise { +async function samplesFromDirectory (dataDir: string, httpHeaders?: string[]): Promise { + async function readFilesOrURLsInDirectory (d: string): Promise { const files = fs .readdirSync(d) .map(x => path.join(d, x)) @@ -128,17 +129,17 @@ async function samplesFromDirectory(dataDir: string, httpHeaders?: string[]): Pr sourcesInDir.push({ kind: "json", name, - samples: [await readableFromFileOrURL(fileOrUrl, httpHeaders)] + samples: [await readableFromFileOrURL(fileOrUrl, httpHeaders)], }); } else if (file.endsWith(".schema")) { sourcesInDir.push({ kind: "schema", name, - uris: [fileOrUrl] + uris: [fileOrUrl], }); } else if (file.endsWith(".gqlschema")) { messageAssert(graphQLSchema === undefined, "DriverMoreThanOneGraphQLSchemaInDir", { - dir: dataDir + dir: dataDir, }); graphQLSchema = await readableFromFileOrURL(fileOrUrl, httpHeaders); graphQLSchemaFileName = fileOrUrl; @@ -147,7 +148,7 @@ async function samplesFromDirectory(dataDir: string, httpHeaders?: string[]): Pr kind: "graphql", name, schema: undefined, - query: await getStream(await readableFromFileOrURL(fileOrUrl, httpHeaders)) + query: await getStream(await readableFromFileOrURL(fileOrUrl, httpHeaders)), }); } } @@ -156,6 +157,7 @@ async function samplesFromDirectory(dataDir: string, httpHeaders?: string[]): Pr if (graphQLSchema === undefined) { return messageError("DriverNoGraphQLSchemaInDir", { dir: dataDir }); } + const schema = parseJSON(await getStream(graphQLSchema), "GraphQL schema", graphQLSchemaFileName); for (const source of graphQLSources) { source.schema = schema; @@ -205,9 +207,10 @@ async function samplesFromDirectory(dataDir: string, httpHeaders?: string[]): Pr sources.push({ kind: "json", name: path.basename(dir), - samples: jsonSamples + samples: jsonSamples, }); } + sources = sources.concat(schemaSources); sources = sources.concat(graphQLSources); } @@ -215,20 +218,21 @@ async function samplesFromDirectory(dataDir: string, httpHeaders?: string[]): Pr return sources; } -function inferLang(options: Partial, defaultLanguage: string): string { +function inferLang (options: Partial, defaultLanguage: string): string { // Output file extension determines the language if language is undefined if (options.out !== undefined) { let extension = path.extname(options.out); if (extension === "") { return messageError("DriverNoLanguageOrExtension", {}); } + return extension.slice(1); } return defaultLanguage; } -function inferTopLevel(options: Partial): string { +function inferTopLevel (options: Partial): string { // Output file name determines the top-level if undefined if (options.out !== undefined) { let extension = path.extname(options.out); @@ -247,7 +251,7 @@ function inferTopLevel(options: Partial): string { return "TopLevel"; } -function inferCLIOptions(opts: Partial, targetLanguage: TargetLanguage | undefined): CLIOptions { +function inferCLIOptions (opts: Partial, targetLanguage: TargetLanguage | undefined): CLIOptions { let srcLang = opts.srcLang; if (opts.graphqlSchema !== undefined || opts.graphqlIntrospect !== undefined) { messageAssert(srcLang === undefined || srcLang === "graphql", "DriverSourceLangMustBeGraphQL", {}); @@ -268,6 +272,7 @@ function inferCLIOptions(opts: Partial, targetLanguage: TargetLangua if (maybeLanguage === undefined) { return messageError("DriverUnknownOutputLanguage", { lang: languageName }); } + language = maybeLanguage; } @@ -292,63 +297,65 @@ function inferCLIOptions(opts: Partial, targetLanguage: TargetLangua httpMethod: opts.httpMethod, httpHeader: opts.httpHeader, debug: opts.debug, - telemetry: opts.telemetry + telemetry: opts.telemetry, }; for (const flagName of inferenceFlagNames) { const cliName = negatedInferenceFlagName(flagName); options[cliName] = !!opts[cliName]; } + return options; } -function makeLangTypeLabel(targetLanguages: TargetLanguage[]): string { +function makeLangTypeLabel (targetLanguages: TargetLanguage[]): string { assert(targetLanguages.length > 0, "Must have at least one target language"); return targetLanguages.map(r => _.minBy(r.names, s => s.length)).join("|"); } -function negatedInferenceFlagName(name: string): string { +function negatedInferenceFlagName (name: string): string { const prefix = "infer"; if (name.startsWith(prefix)) { name = name.slice(prefix.length); } + return "no" + capitalize(name); } -function dashedFromCamelCase(name: string): string { +function dashedFromCamelCase (name: string): string { return splitIntoWords(name) .map(w => w.word.toLowerCase()) .join("-"); } -function makeOptionDefinitions(targetLanguages: TargetLanguage[]): OptionDefinition[] { +function makeOptionDefinitions (targetLanguages: TargetLanguage[]): OptionDefinition[] { const beforeLang: OptionDefinition[] = [ { name: "out", alias: "o", type: String, - typeLabel: `FILE`, - description: "The output file. Determines --lang and --top-level." + typeLabel: "FILE", + description: "The output file. Determines --lang and --top-level.", }, { name: "top-level", alias: "t", type: String, typeLabel: "NAME", - description: "The name for the top level type." - } + description: "The name for the top level type.", + }, ]; const lang: OptionDefinition[] = targetLanguages.length < 2 ? [] : [ - { - name: "lang", - alias: "l", - type: String, - typeLabel: "LANG", - description: "The target language." - } - ]; + { + name: "lang", + alias: "l", + type: String, + typeLabel: "LANG", + description: "The target language.", + }, + ]; const afterLang: OptionDefinition[] = [ { name: "src-lang", @@ -356,7 +363,7 @@ function makeOptionDefinitions(targetLanguages: TargetLanguage[]): OptionDefinit type: String, defaultValue: undefined, typeLabel: "SRC_LANG", - description: "The source language (default is json)." + description: "The source language (default is json).", }, { name: "src", @@ -364,49 +371,49 @@ function makeOptionDefinitions(targetLanguages: TargetLanguage[]): OptionDefinit multiple: true, defaultOption: true, typeLabel: "FILE|URL|DIRECTORY", - description: "The file, url, or data directory to type." + description: "The file, url, or data directory to type.", }, { name: "src-urls", type: String, typeLabel: "FILE", - description: "Tracery grammar describing URLs to crawl." - } + description: "Tracery grammar describing URLs to crawl.", + }, ]; const inference: OptionDefinition[] = Array.from( mapMap(mapFromObject(inferenceFlags), (flag, name) => { return { name: dashedFromCamelCase(negatedInferenceFlagName(name)), type: Boolean, - description: flag.negationDescription + "." + description: flag.negationDescription + ".", }; - }).values() + }).values(), ); const afterInference: OptionDefinition[] = [ { name: "graphql-schema", type: String, typeLabel: "FILE", - description: "GraphQL introspection file." + description: "GraphQL introspection file.", }, { name: "graphql-introspect", type: String, typeLabel: "URL", - description: "Introspect GraphQL schema from a server." + description: "Introspect GraphQL schema from a server.", }, { name: "http-method", type: String, typeLabel: "METHOD", - description: "HTTP method to use for the GraphQL introspection query." + description: "HTTP method to use for the GraphQL introspection query.", }, { name: "http-header", type: String, multiple: true, typeLabel: "HEADER", - description: "Header(s) to attach to all HTTP requests, including the GraphQL introspection query." + description: "Header(s) to attach to all HTTP requests, including the GraphQL introspection query.", }, { name: "additional-schema", @@ -414,67 +421,67 @@ function makeOptionDefinitions(targetLanguages: TargetLanguage[]): OptionDefinit type: String, multiple: true, typeLabel: "FILE", - description: "Register the $id's of additional JSON Schema files." + description: "Register the $id's of additional JSON Schema files.", }, { name: "no-render", type: Boolean, - description: "Don't render output." + description: "Don't render output.", }, { name: "alphabetize-properties", type: Boolean, - description: "Alphabetize order of class properties." + description: "Alphabetize order of class properties.", }, { name: "all-properties-optional", type: Boolean, - description: "Make all class properties optional." + description: "Make all class properties optional.", }, { name: "build-markov-chain", type: String, typeLabel: "FILE", - description: "Markov chain corpus filename." + description: "Markov chain corpus filename.", }, { name: "quiet", type: Boolean, - description: "Don't show issues in the generated code." + description: "Don't show issues in the generated code.", }, { name: "debug", type: String, typeLabel: "OPTIONS or all", description: - "Comma separated debug options: print-graph, print-reconstitution, print-gather-names, print-transformations, print-schema-resolving, print-times, provenance" + "Comma separated debug options: print-graph, print-reconstitution, print-gather-names, print-transformations, print-schema-resolving, print-times, provenance", }, { name: "telemetry", type: String, typeLabel: "enable|disable", - description: "Enable anonymous telemetry to help improve quicktype" + description: "Enable anonymous telemetry to help improve quicktype", }, { name: "help", alias: "h", type: Boolean, - description: "Get some help." + description: "Get some help.", }, { name: "version", alias: "v", type: Boolean, - description: "Display the version of quicktype" - } + description: "Display the version of quicktype", + }, ]; return beforeLang.concat(lang, afterLang, inference, afterInference); } interface ColumnDefinition { name: string; + padding?: { left: string, right: string, }; width?: number; - padding?: { left: string; right: string }; } interface TableOptions { @@ -482,27 +489,27 @@ interface TableOptions { } interface UsageSection { - header?: string; content?: string | string[]; + header?: string; + hide?: string[]; optionList?: OptionDefinition[]; tableOptions?: TableOptions; - hide?: string[]; } const tableOptionsForOptions: TableOptions = { columns: [ { name: "option", - width: 60 + width: 60, }, { name: "description", - width: 60 - } - ] + width: 60, + }, + ], }; -function makeSectionsBeforeRenderers(targetLanguages: TargetLanguage[]): UsageSection[] { +function makeSectionsBeforeRenderers (targetLanguages: TargetLanguage[]): UsageSection[] { const langDisplayNames = targetLanguages.map(r => r.displayName).join(", "); return [ @@ -510,24 +517,24 @@ function makeSectionsBeforeRenderers(targetLanguages: TargetLanguage[]): UsageSe header: "Synopsis", content: [ `$ quicktype [${chalk.bold("--lang")} LANG] [${chalk.bold("--src-lang")} SRC_LANG] [${chalk.bold( - "--out" + "--out", )} FILE] FILE|URL ...`, "", ` LANG ... ${makeLangTypeLabel(targetLanguages)}`, "", - "SRC_LANG ... json|schema|graphql|postman|typescript" - ] + "SRC_LANG ... json|schema|graphql|postman|typescript", + ], }, { header: "Description", - content: `Given JSON sample data, quicktype outputs code for working with that data in ${langDisplayNames}.` + content: `Given JSON sample data, quicktype outputs code for working with that data in ${langDisplayNames}.`, }, { header: "Options", optionList: makeOptionDefinitions(targetLanguages), hide: ["no-render", "build-markov-chain"], - tableOptions: tableOptionsForOptions - } + tableOptions: tableOptionsForOptions, + }, ]; } @@ -544,21 +551,21 @@ const sectionsAfterRenderers: UsageSection[] = [ + Bar - bar-sample-1.json - bar-sample-2.json - - Baz.url` + - Baz.url`, ), "$ quicktype -l go samples", "", chalk.dim("Generate JSON Schema, then TypeScript"), "$ quicktype -o schema.json https://blockchain.info/latestblock", - "$ quicktype -o bitcoin.ts --src-lang schema schema.json" - ] + "$ quicktype -o bitcoin.ts --src-lang schema schema.json", + ], }, { - content: `Learn more at ${chalk.bold("quicktype.io")}` - } + content: `Learn more at ${chalk.bold("quicktype.io")}`, + }, ]; -export function parseCLIOptions(argv: string[], targetLanguage?: TargetLanguage): CLIOptions { +export function parseCLIOptions (argv: string[], targetLanguage?: TargetLanguage): CLIOptions { if (argv.length === 0) { return inferCLIOptions({ help: true }, targetLanguage); } @@ -574,6 +581,7 @@ export function parseCLIOptions(argv: string[], targetLanguage?: TargetLanguage) if (targetLanguage === undefined) { targetLanguage = getTargetLanguage(incompleteOptions.lang); } + const rendererOptionDefinitions = targetLanguage.cliOptionDefinitions.actual; // Use the global options as well as the renderer options from now on: const allOptionDefinitions = _.concat(optionDefinitions, rendererOptionDefinitions); @@ -584,23 +592,24 @@ export function parseCLIOptions(argv: string[], targetLanguage?: TargetLanguage) // Parse the options in argv and split them into global options and renderer options, // according to each option definition's `renderer` field. If `partial` is false this // will throw if it encounters an unknown option. -function parseOptions(definitions: OptionDefinition[], argv: string[], partial: boolean): Partial { - let opts: { [key: string]: any }; +function parseOptions (definitions: OptionDefinition[], argv: string[], partial: boolean): Partial { + let opts: { [key: string]: any, }; try { opts = commandLineArgs(definitions, { argv, partial }); } catch (e) { assert(!partial, "Partial option parsing should not have failed"); return messageError("DriverCLIOptionParsingFailed", { message: exceptionToString(e) }); } + for (const k of Object.keys(opts)) { if (opts[k] === null) { return messageError("DriverCLIOptionParsingFailed", { - message: `Missing value for command line option "${k}"` + message: `Missing value for command line option "${k}"`, }); } } - const options: { rendererOptions: RendererOptions; [key: string]: any } = { rendererOptions: {} }; + const options: { [key: string]: any, rendererOptions: RendererOptions, } = { rendererOptions: {} }; for (const o of definitions) { if (!hasOwnProperty(opts, o.name)) continue; const v = opts[o.name] as string; @@ -610,10 +619,11 @@ function parseOptions(definitions: OptionDefinition[], argv: string[], partial: options[k] = v; } } + return options; } -function usage(targetLanguages: TargetLanguage[]) { +function usage (targetLanguages: TargetLanguage[]) { const rendererSections: UsageSection[] = []; for (const language of targetLanguages) { @@ -623,7 +633,7 @@ function usage(targetLanguages: TargetLanguage[]) { rendererSections.push({ header: `Options for ${language.displayName}`, optionList: definitions, - tableOptions: tableOptionsForOptions + tableOptions: tableOptionsForOptions, }); } @@ -633,12 +643,12 @@ function usage(targetLanguages: TargetLanguage[]) { } // Returns an array of [name, sourceURIs] pairs. -async function getSourceURIs(options: CLIOptions): Promise<[string, string[]][]> { +async function getSourceURIs (options: CLIOptions): Promise> { if (options.srcUrls !== undefined) { const json = parseJSON( await readFromFileOrURL(options.srcUrls, options.httpHeader), "URL grammar", - options.srcUrls + options.srcUrls, ); const jsonMap = urlsFromURLGrammar(json); const topLevels = Object.getOwnPropertyNames(jsonMap); @@ -650,7 +660,7 @@ async function getSourceURIs(options: CLIOptions): Promise<[string, string[]][]> } } -async function typeSourcesForURIs(name: string, uris: string[], options: CLIOptions): Promise { +async function typeSourcesForURIs (name: string, uris: string[], options: CLIOptions): Promise { switch (options.srcLang) { case "json": return [await sourceFromFileOrUrlArray(name, uris, options.httpHeader)]; @@ -661,10 +671,10 @@ async function typeSourcesForURIs(name: string, uris: string[], options: CLIOpti } } -async function getSources(options: CLIOptions): Promise { +async function getSources (options: CLIOptions): Promise { const sourceURIs = await getSourceURIs(options); const sourceArrays = await Promise.all( - sourceURIs.map(async ([name, uris]) => await typeSourcesForURIs(name, uris, options)) + sourceURIs.map(async ([name, uris]) => await typeSourcesForURIs(name, uris, options)), ); let sources: TypeSource[] = ([] as TypeSource[]).concat(...sourceArrays); @@ -678,34 +688,35 @@ async function getSources(options: CLIOptions): Promise { // Every src that's not a directory is assumed to be a file or URL const filesOrUrls = options.src.filter(x => !_.includes(directories, x)); if (!_.isEmpty(filesOrUrls)) { - sources.push(...(await typeSourcesForURIs(options.topLevel, filesOrUrls, options))); + sources.push(...await typeSourcesForURIs(options.topLevel, filesOrUrls, options)); } return sources; } -function makeTypeScriptSource(fileNames: string[]): SchemaTypeSource { +function makeTypeScriptSource (fileNames: string[]): SchemaTypeSource { return Object.assign({ kind: "schema" }, schemaForTypeScriptSources(fileNames)) as SchemaTypeSource; } -export function jsonInputForTargetLanguage( +export function jsonInputForTargetLanguage ( targetLanguage: string | TargetLanguage, languages?: TargetLanguage[], - handleJSONRefs = false + handleJSONRefs = false, ): JSONInput { if (typeof targetLanguage === "string") { targetLanguage = defined(languageNamed(targetLanguage, languages)); } + const compressedJSON = new CompressedJSONFromStream(targetLanguage.dateTimeRecognizer, handleJSONRefs); return new JSONInput(compressedJSON); } -async function makeInputData( +async function makeInputData ( sources: TypeSource[], targetLanguage: TargetLanguage, - additionalSchemaAddresses: ReadonlyArray, + additionalSchemaAddresses: readonly string[], handleJSONRefs: boolean, - httpHeaders?: string[] + httpHeaders?: string[], ): Promise { const inputData = new InputData(); @@ -716,14 +727,14 @@ async function makeInputData( break; case "json": await inputData.addSource("json", source, () => - jsonInputForTargetLanguage(targetLanguage, undefined, handleJSONRefs) + jsonInputForTargetLanguage(targetLanguage, undefined, handleJSONRefs), ); break; case "schema": await inputData.addSource( "schema", source, - () => new JSONSchemaInput(new FetchingJSONSchemaStore(httpHeaders), [], additionalSchemaAddresses) + () => new JSONSchemaInput(new FetchingJSONSchemaStore(httpHeaders), [], additionalSchemaAddresses), ); break; default: @@ -734,23 +745,25 @@ async function makeInputData( return inputData; } -function stringSourceDataToStreamSourceData(src: JSONSourceData): JSONSourceData { +function stringSourceDataToStreamSourceData (src: JSONSourceData): JSONSourceData { return { name: src.name, description: src.description, samples: src.samples.map(stringToStream) }; } -export async function makeQuicktypeOptions( +export async function makeQuicktypeOptions ( options: CLIOptions, - targetLanguages?: TargetLanguage[] + targetLanguages?: TargetLanguage[], ): Promise | undefined> { if (options.help) { usage(targetLanguages === undefined ? defaultTargetLanguages : targetLanguages); return undefined; } + if (options.version) { console.log(`quicktype version ${packageJSON.version}`); console.log("Visit quicktype.io for more info."); return undefined; } + if (options.buildMarkovChain !== undefined) { const contents = fs.readFileSync(options.buildMarkovChain).toString(); const lines = contents.split("\n"); @@ -770,27 +783,31 @@ export async function makeQuicktypeOptions( schemaString = await introspectServer( options.graphqlIntrospect, withDefault(options.httpMethod, "POST"), - withDefault(options.httpHeader, []) + withDefault(options.httpHeader, []), ); if (options.graphqlSchema !== undefined) { fs.writeFileSync(options.graphqlSchema, schemaString); wroteSchemaToFile = true; } } + const numSources = options.src.length; if (numSources !== 1) { if (wroteSchemaToFile) { // We're done. return undefined; } + if (numSources === 0) { if (schemaString !== undefined) { console.log(schemaString); return undefined; } + return messageError("DriverNoGraphQLQueryGiven", {}); } } + const gqlSources: GraphQLTypeSource[] = []; for (const queryFile of options.src) { let schemaFileName: string | undefined = undefined; @@ -798,11 +815,13 @@ export async function makeQuicktypeOptions( schemaFileName = defined(options.graphqlSchema); schemaString = fs.readFileSync(schemaFileName, "utf8"); } + const schema = parseJSON(schemaString, "GraphQL schema", schemaFileName); const query = await getStream(await readableFromFileOrURL(queryFile, options.httpHeader)); const name = numSources === 1 ? options.topLevel : typeNameFromFilename(queryFile); gqlSources.push({ kind: "graphql", name, schema, query }); } + sources = gqlSources; break; case "json": @@ -817,27 +836,30 @@ export async function makeQuicktypeOptions( const collectionJSON = fs.readFileSync(collectionFile, "utf8"); const { sources: postmanSources, description } = sourcesFromPostmanCollection( collectionJSON, - collectionFile + collectionFile, ); for (const src of postmanSources) { sources.push( - Object.assign({ kind: "json" }, stringSourceDataToStreamSourceData(src)) as JSONTypeSource + Object.assign({ kind: "json" }, stringSourceDataToStreamSourceData(src)) as JSONTypeSource, ); } + if (postmanSources.length > 1) { fixedTopLevels = true; } + if (description !== undefined) { leadingComments = wordWrap(description).split("\n"); } } + break; default: return messageError("DriverUnknownSourceLanguage", { lang: options.srcLang }); } const components = definedMap(options.debug, d => d.split(",")); - const debugAll = components !== undefined && components.indexOf("all") >= 0; + const debugAll = components !== undefined && components.includes("all"); let debugPrintGraph = debugAll; let checkProvenance = debugAll; let debugPrintReconstitution = debugAll; @@ -888,7 +910,7 @@ export async function makeQuicktypeOptions( debugPrintGatherNames, debugPrintTransformations, debugPrintSchemaResolving, - debugPrintTimes + debugPrintTimes, }; for (const flagName of inferenceFlagNames) { const cliName = negatedInferenceFlagName(flagName); @@ -905,15 +927,15 @@ export async function makeQuicktypeOptions( lang, options.additionalSchema, quicktypeOptions.ignoreJsonRefs !== true, - options.httpHeader + options.httpHeader, ); return quicktypeOptions; } -export function writeOutput( +export function writeOutput ( cliOptions: CLIOptions, - resultsByFilename: ReadonlyMap + resultsByFilename: ReadonlyMap, ): void { let onFirst = true; for (const [filename, { lines, annotations }] of resultsByFilename) { @@ -925,14 +947,18 @@ export function writeOutput( if (!onFirst) { process.stdout.write("\n"); } + if (resultsByFilename.size > 1) { process.stdout.write(`// ${filename}\n\n`); } + process.stdout.write(output); } + if (cliOptions.quiet) { continue; } + for (const sa of annotations) { const annotation = sa.annotation; if (!(annotation instanceof IssueAnnotationData)) continue; @@ -946,7 +972,7 @@ export function writeOutput( } } -export async function main(args: string[] | Partial) { +export async function main (args: string[] | Partial) { let cliOptions: CLIOptions; if (Array.isArray(args)) { cliOptions = parseCLIOptions(args); @@ -964,6 +990,7 @@ export async function main(args: string[] | Partial) { console.error(chalk.red("telemetry must be 'enable' or 'disable'")); return; } + if (Array.isArray(args) && args.length === 2) { // This was merely a CLI run to set telemetry and we should not proceed return; @@ -985,6 +1012,7 @@ if (require.main === module) { } else { console.error(e); } + process.exit(1); }); } From 392838a1e8c2bf243d7b03aacaf86ff926339592 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Mon, 8 Apr 2024 07:49:22 -0700 Subject: [PATCH 21/94] update eslint rules, eslintignore --- .eslintignore | 6 ++++++ .eslintrc.json | 12 ++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 .eslintignore diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..0fd88d904 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,6 @@ +dist +node_modules +packages/*/dist +packages/*/node_modules +test/runs +test/input diff --git a/.eslintrc.json b/.eslintrc.json index 922bb451a..1f7f67937 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -12,20 +12,28 @@ }, "plugins": ["canonical"], "rules": { + "comma-dangle": "off", + "no-extra-parens": "off", "canonical/prefer-inline-type-import": "error", + "@typescript-eslint/class-literal-property-style": "off", + "@typescript-eslint/comma-dangle": "off", "@typescript-eslint/consistent-type-definitions": ["error", "interface"], "@typescript-eslint/consistent-type-imports": ["error", { "prefer": "type-imports" }], "@typescript-eslint/explicit-function-return-type": "warn", "@typescript-eslint/indent": ["error", 4], - "@typescript-eslint/quotes": ["error", "double"], - "@typescript-eslint/no-misused-promises": ["error", { "checksVoidReturn": false }], + "@typescript-eslint/quotes": ["error", "double", { "avoidEscape": true }], + "@typescript-eslint/member-delimiter-style": "off", "@typescript-eslint/naming-convention": "error", "@typescript-eslint/no-empty-interface": "warn", + "@typescript-eslint/no-extra-parens": "off", + "@typescript-eslint/no-misused-promises": ["error", { "checksVoidReturn": false }], "@typescript-eslint/no-unused-vars": ["error", { "vars": "local", "args": "none" }], "@typescript-eslint/no-use-before-define": "warn", "@typescript-eslint/no-useless-empty-export": "error", "@typescript-eslint/prefer-readonly": "warn", "@typescript-eslint/prefer-reduce-type-parameter": "off", + "@typescript-eslint/require-array-sort-compare": "off", + "@typescript-eslint/space-before-function-paren": "off", "@typescript-eslint/switch-exhaustiveness-check": "error", "@typescript-eslint/unified-signatures": "error" }, From d9baf6ea6e6582771000d1ad77705e8e7bd0df2a Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Mon, 8 Apr 2024 07:49:31 -0700 Subject: [PATCH 22/94] add lint:fix script --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index f221ca9ed..8b6d27c96 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,8 @@ "start": "script/watch", "clean": "rm -rf dist node_modules *~ packages/*/{dist,node_modules}", "debug": "node --inspect-brk --max-old-space-size=4096 ./dist/index.js", - "lint": "eslint src/** packages/*/src/**" + "lint": "eslint src/** packages/*/src/**", + "lint:fix": "eslint --fix src/** packages/*/src/**" }, "workspaces": [ "./packages/quicktype-core", From 8bbabf127ec47194450fbd09bef68fb82e813d67 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Mon, 8 Apr 2024 07:49:22 -0700 Subject: [PATCH 23/94] update eslint rules, eslintignore --- .eslintignore | 6 ++++++ .eslintrc.json | 12 ++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 .eslintignore diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..0fd88d904 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,6 @@ +dist +node_modules +packages/*/dist +packages/*/node_modules +test/runs +test/input diff --git a/.eslintrc.json b/.eslintrc.json index 922bb451a..1f7f67937 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -12,20 +12,28 @@ }, "plugins": ["canonical"], "rules": { + "comma-dangle": "off", + "no-extra-parens": "off", "canonical/prefer-inline-type-import": "error", + "@typescript-eslint/class-literal-property-style": "off", + "@typescript-eslint/comma-dangle": "off", "@typescript-eslint/consistent-type-definitions": ["error", "interface"], "@typescript-eslint/consistent-type-imports": ["error", { "prefer": "type-imports" }], "@typescript-eslint/explicit-function-return-type": "warn", "@typescript-eslint/indent": ["error", 4], - "@typescript-eslint/quotes": ["error", "double"], - "@typescript-eslint/no-misused-promises": ["error", { "checksVoidReturn": false }], + "@typescript-eslint/quotes": ["error", "double", { "avoidEscape": true }], + "@typescript-eslint/member-delimiter-style": "off", "@typescript-eslint/naming-convention": "error", "@typescript-eslint/no-empty-interface": "warn", + "@typescript-eslint/no-extra-parens": "off", + "@typescript-eslint/no-misused-promises": ["error", { "checksVoidReturn": false }], "@typescript-eslint/no-unused-vars": ["error", { "vars": "local", "args": "none" }], "@typescript-eslint/no-use-before-define": "warn", "@typescript-eslint/no-useless-empty-export": "error", "@typescript-eslint/prefer-readonly": "warn", "@typescript-eslint/prefer-reduce-type-parameter": "off", + "@typescript-eslint/require-array-sort-compare": "off", + "@typescript-eslint/space-before-function-paren": "off", "@typescript-eslint/switch-exhaustiveness-check": "error", "@typescript-eslint/unified-signatures": "error" }, From f1d19aa4bd6a697c19d047a339391dfdc7cda824 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Mon, 8 Apr 2024 07:49:31 -0700 Subject: [PATCH 24/94] add lint:fix script --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index f221ca9ed..8b6d27c96 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,8 @@ "start": "script/watch", "clean": "rm -rf dist node_modules *~ packages/*/{dist,node_modules}", "debug": "node --inspect-brk --max-old-space-size=4096 ./dist/index.js", - "lint": "eslint src/** packages/*/src/**" + "lint": "eslint src/** packages/*/src/**", + "lint:fix": "eslint --fix src/** packages/*/src/**" }, "workspaces": [ "./packages/quicktype-core", From 994567ec355c1dbfc4eb6abe9073b2a6085eb5aa Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Mon, 8 Apr 2024 08:50:01 -0700 Subject: [PATCH 25/94] add import rules --- .eslintrc.json | 17 +++++++++++++++-- package.json | 2 +- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 1f7f67937..fcf73b84b 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -5,16 +5,29 @@ "files": "*.json" }, { - "extends": ["eslint:recommended", "canonical/typescript", "canonical/typescript-type-checking"], + "extends": [ + "eslint:recommended", + "canonical/typescript", + "canonical/typescript-type-checking", + "plugin:import/recommended", + "plugin:import/typescript" + ], + "plugins": ["canonical"], "parserOptions": { "tsconfigRootDir": "./", "project": ["./tsconfig.json", "./packages/*/tsconfig.json"] }, - "plugins": ["canonical"], + "settings": { + "import/resolver": { + "typescript": true, + "node": true + } + }, "rules": { "comma-dangle": "off", "no-extra-parens": "off", "canonical/prefer-inline-type-import": "error", + "typescript-sort-keys/string-enum": "off", "@typescript-eslint/class-literal-property-style": "off", "@typescript-eslint/comma-dangle": "off", "@typescript-eslint/consistent-type-definitions": ["error", "interface"], diff --git a/package.json b/package.json index 8b6d27c96..17ee5b728 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "eslint": "^8.57.0", "eslint-config-canonical": "^41.1.7", "eslint-config-prettier": "^6.10.0", - "eslint-import-resolver-typescript": "^3.5.2", + "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-canonical": "^3.4.0", "eslint-plugin-import": "^2.26.0", "eslint-plugin-json": "^3.1.0", From d2598745687de27654bb8bfba4beb1d0cd7adb86 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Mon, 8 Apr 2024 08:50:01 -0700 Subject: [PATCH 26/94] add import rules --- .eslintrc.json | 17 +++++++++++++++-- package.json | 2 +- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 1f7f67937..fcf73b84b 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -5,16 +5,29 @@ "files": "*.json" }, { - "extends": ["eslint:recommended", "canonical/typescript", "canonical/typescript-type-checking"], + "extends": [ + "eslint:recommended", + "canonical/typescript", + "canonical/typescript-type-checking", + "plugin:import/recommended", + "plugin:import/typescript" + ], + "plugins": ["canonical"], "parserOptions": { "tsconfigRootDir": "./", "project": ["./tsconfig.json", "./packages/*/tsconfig.json"] }, - "plugins": ["canonical"], + "settings": { + "import/resolver": { + "typescript": true, + "node": true + } + }, "rules": { "comma-dangle": "off", "no-extra-parens": "off", "canonical/prefer-inline-type-import": "error", + "typescript-sort-keys/string-enum": "off", "@typescript-eslint/class-literal-property-style": "off", "@typescript-eslint/comma-dangle": "off", "@typescript-eslint/consistent-type-definitions": ["error", "interface"], diff --git a/package.json b/package.json index 8b6d27c96..17ee5b728 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "eslint": "^8.57.0", "eslint-config-canonical": "^41.1.7", "eslint-config-prettier": "^6.10.0", - "eslint-import-resolver-typescript": "^3.5.2", + "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-canonical": "^3.4.0", "eslint-plugin-import": "^2.26.0", "eslint-plugin-json": "^3.1.0", From 291f5c9ffd10de87f79d173087ef48eafd922a70 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Fri, 12 Apr 2024 00:05:51 -0700 Subject: [PATCH 27/94] update import rules --- .eslintrc.json | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/.eslintrc.json b/.eslintrc.json index fcf73b84b..c14276ec1 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -9,7 +9,8 @@ "eslint:recommended", "canonical/typescript", "canonical/typescript-type-checking", - "plugin:import/recommended", + "plugin:import/errors", + "plugin:import/warnings", "plugin:import/typescript" ], "plugins": ["canonical"], @@ -28,6 +29,41 @@ "no-extra-parens": "off", "canonical/prefer-inline-type-import": "error", "typescript-sort-keys/string-enum": "off", + + "sort-imports": [ + "error", + { + "ignoreDeclarationSort": true + } + ], + "no-duplicate-imports": "error", + "import/first": "error", + "import/order": [ + "error", + { + "newlines-between": "always", + "groups": ["builtin", "external", "internal", "parent", "sibling", "index", "object", "type"], + "pathGroups": [ + { + "pattern": "@/**", + "group": "internal", + "position": "before" + } + ], + "alphabetize": { + "order": "asc" /* sort in ascending order. Options: ['ignore', 'asc', 'desc'] */, + "caseInsensitive": true /* ignore case. Options: [true, false] */ + } + } + ], + + "import/no-absolute-path": "error", + "import/no-cycle": "error", + "import/no-duplicates": "error", + "import/no-extraneous-dependencies": "error", + "import/no-named-as-default": "off", + "import/no-useless-path-segments": "error", + "@typescript-eslint/class-literal-property-style": "off", "@typescript-eslint/comma-dangle": "off", "@typescript-eslint/consistent-type-definitions": ["error", "interface"], From 03d80012266b6eb30b2fdd25d82fc1b061afd592 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Fri, 12 Apr 2024 09:28:49 -0700 Subject: [PATCH 28/94] reduce excess style rules --- .eslintrc.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.eslintrc.json b/.eslintrc.json index c14276ec1..a5cf75933 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -69,10 +69,11 @@ "@typescript-eslint/consistent-type-definitions": ["error", "interface"], "@typescript-eslint/consistent-type-imports": ["error", { "prefer": "type-imports" }], "@typescript-eslint/explicit-function-return-type": "warn", - "@typescript-eslint/indent": ["error", 4], + "@typescript-eslint/indent": "off", "@typescript-eslint/quotes": ["error", "double", { "avoidEscape": true }], "@typescript-eslint/member-delimiter-style": "off", "@typescript-eslint/naming-convention": "error", + "@typescript-eslint/no-base-to-string": "warn", "@typescript-eslint/no-empty-interface": "warn", "@typescript-eslint/no-extra-parens": "off", "@typescript-eslint/no-misused-promises": ["error", { "checksVoidReturn": false }], From 99dd240f246f2fc9c473b06e5191e0990c02c117 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Fri, 12 Apr 2024 20:26:39 -0700 Subject: [PATCH 29/94] downgrade remaining to warnings --- .eslintignore | 2 ++ .eslintrc.json | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.eslintignore b/.eslintignore index 0fd88d904..135b09976 100644 --- a/.eslintignore +++ b/.eslintignore @@ -4,3 +4,5 @@ packages/*/dist packages/*/node_modules test/runs test/input + +license diff --git a/.eslintrc.json b/.eslintrc.json index a5cf75933..f35b5c03c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -27,6 +27,8 @@ "rules": { "comma-dangle": "off", "no-extra-parens": "off", + "no-case-declarations": "warn", + "no-duplicate-imports": "error", "canonical/prefer-inline-type-import": "error", "typescript-sort-keys/string-enum": "off", @@ -36,7 +38,6 @@ "ignoreDeclarationSort": true } ], - "no-duplicate-imports": "error", "import/first": "error", "import/order": [ "error", @@ -72,10 +73,10 @@ "@typescript-eslint/indent": "off", "@typescript-eslint/quotes": ["error", "double", { "avoidEscape": true }], "@typescript-eslint/member-delimiter-style": "off", - "@typescript-eslint/naming-convention": "error", "@typescript-eslint/no-base-to-string": "warn", "@typescript-eslint/no-empty-interface": "warn", "@typescript-eslint/no-extra-parens": "off", + "@typescript-eslint/no-loop-func": "warn", "@typescript-eslint/no-misused-promises": ["error", { "checksVoidReturn": false }], "@typescript-eslint/no-unused-vars": ["error", { "vars": "local", "args": "none" }], "@typescript-eslint/no-use-before-define": "warn", @@ -85,6 +86,7 @@ "@typescript-eslint/require-array-sort-compare": "off", "@typescript-eslint/space-before-function-paren": "off", "@typescript-eslint/switch-exhaustiveness-check": "error", + "@typescript-eslint/unbound-method": "warn", "@typescript-eslint/unified-signatures": "error" }, "overrides": [ From 7f22254f300ea60eba532c3ccc568abc6e652eed Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Mon, 8 Apr 2024 08:50:12 -0700 Subject: [PATCH 30/94] fix enum values fixup! fix enum values --- .../src/input/CompressedJSON.ts | 97 +-- .../src/input/JSONSchemaInput.ts | 252 +++--- packages/quicktype-core/src/language/CJSON.ts | 787 +++++++++--------- .../quicktype-core/src/language/CPlusPlus.ts | 775 ++++++++--------- .../quicktype-core/src/language/CSharp.ts | 492 ++++++----- .../quicktype-core/src/language/Kotlin.ts | 288 ++++--- packages/quicktype-core/src/language/Rust.ts | 140 ++-- .../quicktype-core/src/language/Scala3.ts | 170 ++-- .../quicktype-core/src/language/Smithy4s.ts | 132 +-- 9 files changed, 1553 insertions(+), 1580 deletions(-) diff --git a/packages/quicktype-core/src/input/CompressedJSON.ts b/packages/quicktype-core/src/input/CompressedJSON.ts index 7832c0675..069834913 100644 --- a/packages/quicktype-core/src/input/CompressedJSON.ts +++ b/packages/quicktype-core/src/input/CompressedJSON.ts @@ -1,23 +1,23 @@ import { addHashCode, hashCodeInit, hashString } from "collection-utils"; import { defined, panic, assert } from "../support/Support"; -import { type TransformedStringTypeKind} from "../Type"; +import { type TransformedStringTypeKind } from "../Type"; import { isPrimitiveStringTypeKind, transformedStringTypeTargetTypeKindsMap } from "../Type"; import { type DateTimeRecognizer } from "../DateTime"; import { inferTransformedStringTypeKindForString } from "../attributes/StringTypes"; export enum Tag { - Null, - False, - True, - Integer, - Double, - InternedString, - UninternedString, - Object, - Array, - StringFormat, - TransformedString + Null = 1, + False = 2, + True = 3, + Integer = 4, + Double = 5, + InternedString = 6, + UninternedString = 7, + Object = 8, + Array = 9, + StringFormat = 10, + TransformedString = 11 } export type Value = number; @@ -25,16 +25,16 @@ export type Value = number; const TAG_BITS = 4; const TAG_MASK = (1 << TAG_BITS) - 1; -export function makeValue (t: Tag, index: number): Value { - return t | index << TAG_BITS; +export function makeValue(t: Tag, index: number): Value { + return t | (index << TAG_BITS); } -function getIndex (v: Value, tag: Tag): number { +function getIndex(v: Value, tag: Tag): number { assert(valueTag(v) === tag, "Trying to get index for value with invalid tag"); return v >> TAG_BITS; } -export function valueTag (v: Value): Tag { +export function valueTag(v: Value): Tag { return v & TAG_MASK; } @@ -54,21 +54,24 @@ export abstract class CompressedJSON { private _strings: string[] = []; - private _stringIndexes: { [str: string]: number, } = {}; + private _stringIndexes: { [str: string]: number } = {}; private _objects: Value[][] = []; private _arrays: Value[][] = []; - constructor (readonly dateTimeRecognizer: DateTimeRecognizer, readonly handleRefs: boolean) {} + constructor( + readonly dateTimeRecognizer: DateTimeRecognizer, + readonly handleRefs: boolean + ) {} - abstract parse (input: T): Promise; + abstract parse(input: T): Promise; - parseSync (_input: T): Value { + parseSync(_input: T): Value { return panic("parseSync not implemented in CompressedJSON"); } - getStringForValue (v: Value): string { + getStringForValue(v: Value): string { const tag = valueTag(v); assert(tag === Tag.InternedString || tag === Tag.TransformedString); return this._strings[getIndex(v, tag)]; @@ -82,7 +85,7 @@ export abstract class CompressedJSON { return this._arrays[getIndex(v, Tag.Array)]; }; - getStringFormatTypeKind (v: Value): TransformedStringTypeKind { + getStringFormatTypeKind(v: Value): TransformedStringTypeKind { const kind = this._strings[getIndex(v, Tag.StringFormat)]; if (!isPrimitiveStringTypeKind(kind) || kind === "string") { return panic("Not a transformed string type kind"); @@ -91,11 +94,11 @@ export abstract class CompressedJSON { return kind; } - protected get context (): Context { + protected get context(): Context { return defined(this._ctx); } - protected internString (s: string): number { + protected internString(s: string): number { if (Object.prototype.hasOwnProperty.call(this._stringIndexes, s)) { return this._stringIndexes[s]; } @@ -106,13 +109,13 @@ export abstract class CompressedJSON { return index; } - protected makeString (s: string): Value { + protected makeString(s: string): Value { const value = makeValue(Tag.InternedString, this.internString(s)); assert(typeof value === "number", `Interned string value is not a number: ${value}`); return value; } - protected internObject (obj: Value[]): Value { + protected internObject(obj: Value[]): Value { const index = this._objects.length; this._objects.push(obj); return makeValue(Tag.Object, index); @@ -124,16 +127,16 @@ export abstract class CompressedJSON { return makeValue(Tag.Array, index); }; - protected get isExpectingRef (): boolean { + protected get isExpectingRef(): boolean { return this._ctx !== undefined && this._ctx.currentKey === "$ref"; } - protected commitValue (value: Value): void { + protected commitValue(value: Value): void { assert(typeof value === "number", `CompressedJSON value is not a number: ${value}`); if (this._ctx === undefined) { assert( this._rootValue === undefined, - "Committing value but nowhere to commit to - root value still there.", + "Committing value but nowhere to commit to - root value still there." ); this._rootValue = value; } else if (this._ctx.currentObject !== undefined) { @@ -150,20 +153,20 @@ export abstract class CompressedJSON { } } - protected commitNull (): void { + protected commitNull(): void { this.commitValue(makeValue(Tag.Null, 0)); } - protected commitBoolean (v: boolean): void { + protected commitBoolean(v: boolean): void { this.commitValue(makeValue(v ? Tag.True : Tag.False, 0)); } - protected commitNumber (isDouble: boolean): void { + protected commitNumber(isDouble: boolean): void { const numberTag = isDouble ? Tag.Double : Tag.Integer; this.commitValue(makeValue(numberTag, 0)); } - protected commitString (s: string): void { + protected commitString(s: string): void { let value: Value | undefined = undefined; if (this.handleRefs && this.isExpectingRef) { value = this.makeString(s); @@ -185,7 +188,7 @@ export abstract class CompressedJSON { this.commitValue(value); } - protected finish (): Value { + protected finish(): Value { const value = this._rootValue; if (value === undefined) { return panic("Finished without root document"); @@ -196,7 +199,7 @@ export abstract class CompressedJSON { return value; } - protected pushContext (): void { + protected pushContext(): void { if (this._ctx !== undefined) { this._contextStack.push(this._ctx); } @@ -205,21 +208,21 @@ export abstract class CompressedJSON { currentObject: undefined, currentArray: undefined, currentKey: undefined, - currentNumberIsDouble: false, + currentNumberIsDouble: false }; } - protected pushObjectContext (): void { + protected pushObjectContext(): void { this.pushContext(); defined(this._ctx).currentObject = []; } - protected setPropertyKey (key: string): void { + protected setPropertyKey(key: string): void { const ctx = this.context; ctx.currentKey = key; } - protected finishObject (): void { + protected finishObject(): void { const obj = this.context.currentObject; if (obj === undefined) { return panic("Object ended but not started"); @@ -229,12 +232,12 @@ export abstract class CompressedJSON { this.commitValue(this.internObject(obj)); } - protected pushArrayContext (): void { + protected pushArrayContext(): void { this.pushContext(); defined(this._ctx).currentArray = []; } - protected finishArray (): void { + protected finishArray(): void { const arr = this.context.currentArray; if (arr === undefined) { return panic("Array ended but not started"); @@ -244,16 +247,16 @@ export abstract class CompressedJSON { this.commitValue(this.internArray(arr)); } - protected popContext (): void { + protected popContext(): void { assert(this._ctx !== undefined, "Popping context when there isn't one"); this._ctx = this._contextStack.pop(); } - equals (other: any): boolean { + equals(other: any): boolean { return this === other; } - hashCode (): number { + hashCode(): number { let hashAccumulator = hashCodeInit; for (const s of this._strings) { hashAccumulator = addHashCode(hashAccumulator, hashString(s)); @@ -281,17 +284,17 @@ export abstract class CompressedJSON { } export class CompressedJSONFromString extends CompressedJSON { - async parse (input: string): Promise { + async parse(input: string): Promise { return this.parseSync(input); } - parseSync (input: string): Value { + parseSync(input: string): Value { const json = JSON.parse(input); this.process(json); return this.finish(); } - private process (json: unknown): void { + private process(json: unknown): void { if (json === null) { this.commitNull(); } else if (typeof json === "boolean") { diff --git a/packages/quicktype-core/src/input/JSONSchemaInput.ts b/packages/quicktype-core/src/input/JSONSchemaInput.ts index ae8f4b5fd..d3226c949 100644 --- a/packages/quicktype-core/src/input/JSONSchemaInput.ts +++ b/packages/quicktype-core/src/input/JSONSchemaInput.ts @@ -18,29 +18,19 @@ import { definedMap, addHashCode, iterableFirst, - hashString, + hashString } from "collection-utils"; -import { - type PrimitiveTypeKind, - type TransformedStringTypeKind} from "../Type"; -import { - transformedStringTypeTargetTypeKindsMap, - isNumberTypeKind, -} from "../Type"; -import { type StringMap} from "../support/Support"; +import { type PrimitiveTypeKind, type TransformedStringTypeKind } from "../Type"; +import { transformedStringTypeTargetTypeKindsMap, isNumberTypeKind } from "../Type"; +import { type StringMap } from "../support/Support"; import { panic, assertNever, assert, defined, parseJSON } from "../support/Support"; import { type TypeBuilder } from "../TypeBuilder"; import { TypeNames } from "../attributes/TypeNames"; import { makeNamesTypeAttributes, modifyTypeNames, singularizeTypeNames } from "../attributes/TypeNames"; -import { - type TypeAttributes} from "../attributes/TypeAttributes"; -import { - makeTypeAttributesInferred, - emptyTypeAttributes, - combineTypeAttributes, -} from "../attributes/TypeAttributes"; -import { type JSONSchema} from "./JSONSchemaStore"; +import { type TypeAttributes } from "../attributes/TypeAttributes"; +import { makeTypeAttributesInferred, emptyTypeAttributes, combineTypeAttributes } from "../attributes/TypeAttributes"; +import { type JSONSchema } from "./JSONSchemaStore"; import { JSONSchemaStore } from "./JSONSchemaStore"; import { messageAssert, messageError } from "../Messages"; import { StringTypes } from "../attributes/StringTypes"; @@ -61,24 +51,24 @@ import { patternAttributeProducer } from "../attributes/Constraints"; import { uriSchemaAttributesProducer } from "../attributes/URIAttributes"; export enum PathElementKind { - Root, - KeyOrIndex, - Type, - Object + Root = 1, + KeyOrIndex = 2, + Type = 3, + Object = 4 } export type PathElement = - | { kind: PathElementKind.Root, } - | { key: string, kind: PathElementKind.KeyOrIndex, } - | { index: number, kind: PathElementKind.Type, } - | { kind: PathElementKind.Object, }; + | { kind: PathElementKind.Root } + | { key: string; kind: PathElementKind.KeyOrIndex } + | { index: number; kind: PathElementKind.Type } + | { kind: PathElementKind.Object }; -function keyOrIndex (pe: PathElement): string | undefined { +function keyOrIndex(pe: PathElement): string | undefined { if (pe.kind !== PathElementKind.KeyOrIndex) return undefined; return pe.key; } -function pathElementEquals (a: PathElement, b: PathElement): boolean { +function pathElementEquals(a: PathElement, b: PathElement): boolean { if (a.kind !== b.kind) return false; switch (a.kind) { case PathElementKind.Type: @@ -90,15 +80,15 @@ function pathElementEquals (a: PathElement, b: PathElement): boolean { } } -function withRef (refOrLoc: Ref | (() => Ref) | Location): { ref: Ref, }; -function withRef (refOrLoc: Ref | (() => Ref) | Location, props?: T): T & { ref: Ref, }; -function withRef (refOrLoc: Ref | (() => Ref) | Location, props?: T): any { +function withRef(refOrLoc: Ref | (() => Ref) | Location): { ref: Ref }; +function withRef(refOrLoc: Ref | (() => Ref) | Location, props?: T): T & { ref: Ref }; +function withRef(refOrLoc: Ref | (() => Ref) | Location, props?: T): any { const ref = typeof refOrLoc === "function" ? refOrLoc() : refOrLoc instanceof Ref ? refOrLoc : refOrLoc.canonicalRef; return Object.assign({ ref }, props === undefined ? {} : props); } -function checkJSONSchemaObject (x: any, refOrLoc: Ref | (() => Ref)): StringMap { +function checkJSONSchemaObject(x: any, refOrLoc: Ref | (() => Ref)): StringMap { if (Array.isArray(x)) { return messageError("SchemaArrayIsInvalidSchema", withRef(refOrLoc)); } @@ -114,14 +104,14 @@ function checkJSONSchemaObject (x: any, refOrLoc: Ref | (() => Ref)): StringMap return x; } -function checkJSONSchema (x: any, refOrLoc: Ref | (() => Ref)): JSONSchema { +function checkJSONSchema(x: any, refOrLoc: Ref | (() => Ref)): JSONSchema { if (typeof x === "boolean") return x; return checkJSONSchemaObject(x, refOrLoc); } const numberRegexp = new RegExp("^[0-9]+$"); -function normalizeURI (uri: string | URI): URI { +function normalizeURI(uri: string | URI): URI { // FIXME: This is overly complicated and a bit shady. The problem is // that `normalize` will URL-escape, with the result that if we want to // open the URL as a file, escaped character will thwart us. I think the @@ -135,12 +125,12 @@ function normalizeURI (uri: string | URI): URI { } export class Ref { - static root (address: string | undefined): Ref { + static root(address: string | undefined): Ref { const uri = definedMap(address, a => new URI(a)); return new Ref(uri, []); } - private static parsePath (path: string): readonly PathElement[] { + private static parsePath(path: string): readonly PathElement[] { const elements: PathElement[] = []; if (path.startsWith("/")) { @@ -150,15 +140,13 @@ export class Ref { if (path !== "") { const parts = path.split("/"); - for (let i = 0; i < parts.length; i++) { - elements.push({ kind: PathElementKind.KeyOrIndex, key: parts[i] }); - } + parts.forEach(part => elements.push({ kind: PathElementKind.KeyOrIndex, key: part })); } return elements; } - static parseURI (uri: URI, destroyURI = false): Ref { + static parseURI(uri: URI, destroyURI = false): Ref { if (!destroyURI) { uri = uri.clone(); } @@ -173,15 +161,15 @@ export class Ref { return new Ref(uri, elements); } - static parse (ref: string): Ref { + static parse(ref: string): Ref { return Ref.parseURI(new URI(ref), true); } public addressURI: URI | undefined; - constructor ( + constructor( addressURI: URI | undefined, - readonly path: readonly PathElement[], + readonly path: readonly PathElement[] ) { if (addressURI !== undefined) { assert(addressURI.fragment() === "", `Ref URI with fragment is not allowed: ${addressURI.toString()}`); @@ -191,25 +179,25 @@ export class Ref { } } - get hasAddress (): boolean { + get hasAddress(): boolean { return this.addressURI !== undefined; } - get address (): string { + get address(): string { return defined(this.addressURI).toString(); } - get isRoot (): boolean { + get isRoot(): boolean { return this.path.length === 1 && this.path[0].kind === PathElementKind.Root; } - private pushElement (pe: PathElement): Ref { + private pushElement(pe: PathElement): Ref { const newPath = Array.from(this.path); newPath.push(pe); return new Ref(this.addressURI, newPath); } - push (...keys: string[]): Ref { + push(...keys: string[]): Ref { let ref: Ref = this; for (const key of keys) { ref = ref.pushElement({ kind: PathElementKind.KeyOrIndex, key }); @@ -218,15 +206,15 @@ export class Ref { return ref; } - pushObject (): Ref { + pushObject(): Ref { return this.pushElement({ kind: PathElementKind.Object }); } - pushType (index: number): Ref { + pushType(index: number): Ref { return this.pushElement({ kind: PathElementKind.Type, index }); } - resolveAgainst (base: Ref | undefined): Ref { + resolveAgainst(base: Ref | undefined): Ref { let addressURI = this.addressURI; if (base?.addressURI !== undefined) { addressURI = addressURI === undefined ? base.addressURI : addressURI.absoluteTo(base.addressURI); @@ -235,7 +223,7 @@ export class Ref { return new Ref(addressURI, this.path); } - get name (): string { + get name(): string { const path = Array.from(this.path); for (;;) { @@ -270,15 +258,15 @@ export class Ref { } } - get definitionName (): string | undefined { + get definitionName(): string | undefined { const pe = arrayGetFromEnd(this.path, 2); if (pe === undefined) return undefined; if (keyOrIndex(pe) === "definitions") return keyOrIndex(defined(arrayLast(this.path))); return undefined; } - toString (): string { - function elementToString (e: PathElement): string { + toString(): string { + function elementToString(e: PathElement): string { switch (e.kind) { case PathElementKind.Root: return ""; @@ -297,7 +285,7 @@ export class Ref { return address + "#" + this.path.map(elementToString).join("/"); } - private lookup (local: any, path: readonly PathElement[], root: JSONSchema): JSONSchema { + private lookup(local: any, path: readonly PathElement[], root: JSONSchema): JSONSchema { const refMaker = () => new Ref(this.addressURI, path); const first = path[0]; if (first === undefined) { @@ -330,24 +318,24 @@ export class Ref { } case PathElementKind.Type: - return panic("Cannot look up path that indexes \"type\""); + return panic('Cannot look up path that indexes "type"'); case PathElementKind.Object: - return panic("Cannot look up path that indexes \"object\""); + return panic('Cannot look up path that indexes "object"'); default: return assertNever(first); } } - lookupRef (root: JSONSchema): JSONSchema { + lookupRef(root: JSONSchema): JSONSchema { return this.lookup(root, this.path, root); } - equals (other: any): boolean { + equals(other: any): boolean { if (!(other instanceof Ref)) return false; if (this.addressURI !== undefined && other.addressURI !== undefined) { if (!this.addressURI.equals(other.addressURI)) return false; } else { - if (this.addressURI === undefined !== (other.addressURI === undefined)) return false; + if ((this.addressURI === undefined) !== (other.addressURI === undefined)) return false; } const l = this.path.length; @@ -359,7 +347,7 @@ export class Ref { return true; } - hashCode (): number { + hashCode(): number { let acc = hashCodeOf(definedMap(this.addressURI, u => u.toString())); for (const pe of this.path) { acc = addHashCode(acc, pe.kind); @@ -384,16 +372,16 @@ class Location { public readonly virtualRef: Ref; - constructor ( + constructor( canonicalRef: Ref, virtualRef?: Ref, - readonly haveID: boolean = false, + readonly haveID: boolean = false ) { this.canonicalRef = canonicalRef; this.virtualRef = virtualRef !== undefined ? virtualRef : canonicalRef; } - updateWithID (id: any) { + updateWithID(id: any) { if (typeof id !== "string") return this; const parsed = Ref.parse(id); const virtual = this.haveID ? parsed.resolveAgainst(this.virtualRef) : parsed; @@ -404,19 +392,19 @@ class Location { return new Location(this.canonicalRef, virtual, true); } - push (...keys: string[]): Location { + push(...keys: string[]): Location { return new Location(this.canonicalRef.push(...keys), this.virtualRef.push(...keys), this.haveID); } - pushObject (): Location { + pushObject(): Location { return new Location(this.canonicalRef.pushObject(), this.virtualRef.pushObject(), this.haveID); } - pushType (index: number): Location { + pushType(index: number): Location { return new Location(this.canonicalRef.pushType(index), this.virtualRef.pushType(index), this.haveID); } - toString (): string { + toString(): string { return `${this.virtualRef.toString()} (${this.canonicalRef.toString()})`; } } @@ -426,9 +414,9 @@ class Canonizer { private readonly _schemaAddressesAdded = new Set(); - constructor (private readonly _ctx: RunContext) {} + constructor(private readonly _ctx: RunContext) {} - private addIDs (schema: any, loc: Location) { + private addIDs(schema: any, loc: Location) { if (schema === null) return; if (Array.isArray(schema)) { for (let i = 0; i < schema.length; i++) { @@ -461,7 +449,7 @@ class Canonizer { } } - addSchema (schema: any, address: string): boolean { + addSchema(schema: any, address: string): boolean { if (this._schemaAddressesAdded.has(address)) return false; this.addIDs(schema, new Location(Ref.root(address), Ref.root(undefined))); @@ -470,7 +458,7 @@ class Canonizer { } // Returns: Canonical ref - canonize (base: Location, ref: Ref): Location { + canonize(base: Location, ref: Ref): Location { const virtual = ref.resolveAgainst(base.virtualRef); const loc = this._map.get(virtual); if (loc !== undefined) { @@ -483,7 +471,7 @@ class Canonizer { } } -function checkTypeList (typeOrTypes: any, loc: Location): ReadonlySet { +function checkTypeList(typeOrTypes: any, loc: Location): ReadonlySet { let set: Set; if (typeof typeOrTypes === "string") { set = new Set([typeOrTypes]); @@ -512,7 +500,7 @@ function checkTypeList (typeOrTypes: any, loc: Location): ReadonlySet { return set; } -function checkRequiredArray (arr: any, loc: Location): string[] { +function checkRequiredArray(arr: any, loc: Location): string[] { if (!Array.isArray(arr)) { return messageError("SchemaRequiredMustBeStringOrStringArray", withRef(loc, { actual: arr })); } @@ -533,7 +521,7 @@ export const schemaTypeDict = { integer: true, number: true, array: true, - object: true, + object: true }; export type JSONSchemaType = keyof typeof schemaTypeDict; @@ -554,16 +542,16 @@ export type JSONSchemaAttributeProducer = ( unionCases: JSONSchema[] | undefined ) => JSONSchemaAttributes | undefined; -function typeKindForJSONSchemaFormat (format: string): TransformedStringTypeKind | undefined { +function typeKindForJSONSchemaFormat(format: string): TransformedStringTypeKind | undefined { const target = iterableFind( transformedStringTypeTargetTypeKindsMap, - ([_, { jsonSchema }]) => jsonSchema === format, + ([_, { jsonSchema }]) => jsonSchema === format ); if (target === undefined) return undefined; return target[0] as TransformedStringTypeKind; } -function schemaFetchError (base: Location | undefined, address: string): never { +function schemaFetchError(base: Location | undefined, address: string): never { if (base === undefined) { return messageError("SchemaFetchErrorTopLevel", { address }); } else { @@ -572,16 +560,16 @@ function schemaFetchError (base: Location | undefined, address: string): never { } class Resolver { - constructor ( + constructor( private readonly _ctx: RunContext, private readonly _store: JSONSchemaStore, - private readonly _canonizer: Canonizer, + private readonly _canonizer: Canonizer ) {} - private async tryResolveVirtualRef ( + private async tryResolveVirtualRef( fetchBase: Location, lookupBase: Location, - virtualRef: Ref, + virtualRef: Ref ): Promise<[JSONSchema | undefined, Location]> { let didAdd = false; // If we are resolving into a schema file that we haven't seen yet then @@ -611,7 +599,7 @@ class Resolver { lookupLoc = new Location( new Ref(loc.canonicalRef.addressURI, lookupLoc.canonicalRef.path), lookupLoc.virtualRef, - lookupLoc.haveID, + lookupLoc.haveID ); } @@ -620,7 +608,7 @@ class Resolver { } } - async resolveVirtualRef (base: Location, virtualRef: Ref): Promise<[JSONSchema, Location]> { + async resolveVirtualRef(base: Location, virtualRef: Ref): Promise<[JSONSchema, Location]> { if (this._ctx.debugPrintSchemaResolving) { console.log(`resolving ${virtualRef.toString()} relative to ${base.toString()}`); } @@ -640,7 +628,7 @@ class Resolver { const altBase = new Location( base.canonicalRef, new Ref(base.canonicalRef.addressURI, base.virtualRef.path), - base.haveID, + base.haveID ); result = await this.tryResolveVirtualRef(altBase, base, virtualRef); schema = result[0]; @@ -655,20 +643,20 @@ class Resolver { return schemaFetchError(base, virtualRef.address); } - async resolveTopLevelRef (ref: Ref): Promise<[JSONSchema, Location]> { + async resolveTopLevelRef(ref: Ref): Promise<[JSONSchema, Location]> { return await this.resolveVirtualRef(new Location(new Ref(ref.addressURI, [])), new Ref(undefined, ref.path)); } } -async function addTypesInSchema ( +async function addTypesInSchema( resolver: Resolver, typeBuilder: TypeBuilder, references: ReadonlyMap, - attributeProducers: JSONSchemaAttributeProducer[], + attributeProducers: JSONSchemaAttributeProducer[] ): Promise { let typeForCanonicalRef = new EqualityMap(); - function setTypeForLocation (loc: Location, t: TypeRef): void { + function setTypeForLocation(loc: Location, t: TypeRef): void { const maybeRef = typeForCanonicalRef.get(loc.canonicalRef); if (maybeRef !== undefined) { assert(maybeRef === t, "Trying to set path again to different type"); @@ -677,13 +665,13 @@ async function addTypesInSchema ( typeForCanonicalRef.set(loc.canonicalRef, t); } - async function makeObject ( + async function makeObject( loc: Location, attributes: TypeAttributes, properties: StringMap, requiredArray: string[], additionalProperties: any, - sortKey: (k: string) => number | string = (k: string) => k.toLowerCase(), + sortKey: (k: string) => number | string = (k: string) => k.toLowerCase() ): Promise { const required = new Set(requiredArray); const propertiesMap = mapSortBy(mapFromObject(properties), (_, k) => sortKey(k)); @@ -692,7 +680,7 @@ async function addTypesInSchema ( const t = await toType( checkJSONSchema(propSchema, propLoc.canonicalRef), propLoc, - makeNamesTypeAttributes(propName, true), + makeNamesTypeAttributes(propName, true) ); const isOptional = !required.has(propName); return typeBuilder.makeClassProperty(t, isOptional); @@ -707,7 +695,7 @@ async function addTypesInSchema ( additionalPropertiesType = await toType( checkJSONSchema(additionalProperties, additionalLoc.canonicalRef), additionalLoc, - singularizeTypeNames(attributes), + singularizeTypeNames(attributes) ); } @@ -719,7 +707,7 @@ async function addTypesInSchema ( } const additionalProps = mapFromIterable(additionalRequired, _name => - typeBuilder.makeClassProperty(t, false), + typeBuilder.makeClassProperty(t, false) ); mapMergeInto(props, additionalProps); } @@ -727,12 +715,12 @@ async function addTypesInSchema ( return typeBuilder.getUniqueObjectType(attributes, props, additionalPropertiesType); } - async function convertToType (schema: StringMap, loc: Location, typeAttributes: TypeAttributes): Promise { + async function convertToType(schema: StringMap, loc: Location, typeAttributes: TypeAttributes): Promise { const enumArray = Array.isArray(schema.enum) ? schema.enum : undefined; const isConst = schema.const !== undefined; const typeSet = definedMap(schema.type, t => checkTypeList(t, loc)); - function isTypeIncluded (name: JSONSchemaType): boolean { + function isTypeIncluded(name: JSONSchemaType): boolean { if (typeSet !== undefined && !typeSet.has(name)) { return false; } @@ -764,9 +752,9 @@ async function addTypesInSchema ( const includedTypes = setFilter(schemaTypes, isTypeIncluded); let producedAttributesForNoCases: JSONSchemaAttributes[] | undefined = undefined; - function forEachProducedAttribute ( + function forEachProducedAttribute( cases: JSONSchema[] | undefined, - f: (attributes: JSONSchemaAttributes) => void, + f: (attributes: JSONSchemaAttributes) => void ): void { let attributes: JSONSchemaAttributes[]; if (cases === undefined && producedAttributesForNoCases !== undefined) { @@ -789,8 +777,8 @@ async function addTypesInSchema ( } } - function combineProducedAttributes ( - f: (attributes: JSONSchemaAttributes) => TypeAttributes | undefined, + function combineProducedAttributes( + f: (attributes: JSONSchemaAttributes) => TypeAttributes | undefined ): TypeAttributes { let result = emptyTypeAttributes; forEachProducedAttribute(undefined, attr => { @@ -801,7 +789,7 @@ async function addTypesInSchema ( return result; } - function makeAttributes (attributes: TypeAttributes): TypeAttributes { + function makeAttributes(attributes: TypeAttributes): TypeAttributes { if (schema.oneOf === undefined) { attributes = combineTypeAttributes( "union", @@ -809,10 +797,10 @@ async function addTypesInSchema ( combineProducedAttributes(({ forType, forUnion, forCases }) => { assert( forUnion === undefined && forCases === undefined, - "We can't have attributes for unions and cases if we don't have a union", + "We can't have attributes for unions and cases if we don't have a union" ); return forType; - }), + }) ); } @@ -838,7 +826,7 @@ async function addTypesInSchema ( typeAttributes = makeAttributes(typeAttributes); const inferredAttributes = makeTypeAttributesInferred(typeAttributes); - function makeStringType (attributes: TypeAttributes): TypeRef { + function makeStringType(attributes: TypeAttributes): TypeRef { const kind = typeKindForJSONSchemaFormat(schema.format); if (kind === undefined) { return typeBuilder.getStringType(attributes, StringTypes.unrestricted); @@ -847,7 +835,7 @@ async function addTypesInSchema ( } } - async function makeArrayType (): Promise { + async function makeArrayType(): Promise { const singularAttributes = singularizeTypeNames(typeAttributes); const items = schema.items; let itemType: TypeRef; @@ -871,7 +859,7 @@ async function addTypesInSchema ( return typeBuilder.getArrayType(emptyTypeAttributes, itemType); } - async function makeObjectType (): Promise { + async function makeObjectType(): Promise { let required: string[]; if (schema.required === undefined || typeof schema.required === "boolean") { required = []; @@ -907,7 +895,7 @@ async function addTypesInSchema ( const objectAttributes = combineTypeAttributes( "union", inferredAttributes, - combineProducedAttributes(({ forObject }) => forObject), + combineProducedAttributes(({ forObject }) => forObject) ); const order = schema.quicktypePropertyOrder ? schema.quicktypePropertyOrder : []; const orderKey = (propertyName: string) => { @@ -920,7 +908,7 @@ async function addTypesInSchema ( return await makeObject(loc, objectAttributes, properties, required, additionalProperties, orderKey); } - async function makeTypesFromCases (cases: any, kind: string): Promise { + async function makeTypesFromCases(cases: any, kind: string): Promise { const kindLoc = loc.push(kind); if (!Array.isArray(cases)) { return messageError("SchemaSetOperationCasesIsNotArray", withRef(kindLoc, { operation: kind, cases })); @@ -932,7 +920,7 @@ async function addTypesInSchema ( return await toType( checkJSONSchema(t, caseLoc.canonicalRef), caseLoc, - makeTypeAttributesInferred(typeAttributes), + makeTypeAttributesInferred(typeAttributes) ); }); } @@ -940,7 +928,7 @@ async function addTypesInSchema ( const intersectionType = typeBuilder.getUniqueIntersectionType(typeAttributes, undefined); setTypeForLocation(loc, intersectionType); - async function convertOneOrAnyOf (cases: any, kind: string): Promise { + async function convertOneOrAnyOf(cases: any, kind: string): Promise { const typeRefs = await makeTypesFromCases(cases, kind); let unionAttributes = makeTypeAttributesInferred(typeAttributes); if (kind === "oneOf") { @@ -956,7 +944,7 @@ async function addTypesInSchema ( if (forCases !== undefined) { assert( forCases.length === typeRefs.length, - "Number of case attributes doesn't match number of cases", + "Number of case attributes doesn't match number of cases" ); for (let i = 0; i < typeRefs.length; i++) { typeBuilder.addAttributes(typeRefs[i], forCases[i]); @@ -996,7 +984,7 @@ async function addTypesInSchema ( ["null", "null"], ["number", "double"], ["integer", "integer"], - ["boolean", "bool"], + ["boolean", "bool"] ] as Array<[JSONSchemaType, PrimitiveTypeKind]>) { if (!includedTypes.has(name)) continue; @@ -1007,7 +995,7 @@ async function addTypesInSchema ( const stringAttributes = combineTypeAttributes( "union", inferredAttributes, - combineProducedAttributes(({ forString }) => forString), + combineProducedAttributes(({ forString }) => forString) ); if (needStringEnum || isConst) { @@ -1045,7 +1033,7 @@ async function addTypesInSchema ( } if (schema.allOf !== undefined) { - types.push(...await makeTypesFromCases(schema.allOf, "allOf")); + types.push(...(await makeTypesFromCases(schema.allOf, "allOf"))); } if (schema.oneOf !== undefined) { @@ -1060,7 +1048,7 @@ async function addTypesInSchema ( return intersectionType; } - async function toType (schema: JSONSchema, loc: Location, typeAttributes: TypeAttributes): Promise { + async function toType(schema: JSONSchema, loc: Location, typeAttributes: TypeAttributes): Promise { const maybeType = typeForCanonicalRef.get(loc.canonicalRef); if (maybeType !== undefined) { return maybeType; @@ -1088,7 +1076,7 @@ async function addTypesInSchema ( } } -function removeExtension (fn: string): string { +function removeExtension(fn: string): string { const lower = fn.toLowerCase(); const extensions = [".json", ".schema"]; for (const ext of extensions) { @@ -1103,7 +1091,7 @@ function removeExtension (fn: string): string { return fn; } -function nameFromURI (uri: URI): string | undefined { +function nameFromURI(uri: URI): string | undefined { const fragment = uri.fragment(); if (fragment !== "") { const components = fragment.split("/"); @@ -1125,10 +1113,10 @@ function nameFromURI (uri: URI): string | undefined { return messageError("DriverCannotInferNameForSchema", { uri: uri.toString() }); } -async function refsInSchemaForURI ( +async function refsInSchemaForURI( resolver: Resolver, uri: URI, - defaultName: string, + defaultName: string ): Promise | [string, Ref]> { const fragment = uri.fragment(); let propertiesAreTypes = fragment.endsWith("/"); @@ -1163,14 +1151,14 @@ async function refsInSchemaForURI ( } class InputJSONSchemaStore extends JSONSchemaStore { - constructor ( + constructor( private readonly _inputs: Map, - private readonly _delegate?: JSONSchemaStore, + private readonly _delegate?: JSONSchemaStore ) { super(); } - async fetch (address: string): Promise { + async fetch(address: string): Promise { const maybeInput = this._inputs.get(address); if (maybeInput !== undefined) { return checkJSONSchema(parseJSON(maybeInput, "JSON Schema", address), () => Ref.root(address)); @@ -1206,10 +1194,10 @@ export class JSONSchemaInput implements Input { private _needIR = false; - constructor ( + constructor( private _schemaStore: JSONSchemaStore | undefined, additionalAttributeProducers: JSONSchemaAttributeProducer[] = [], - private readonly _additionalSchemaAddresses: readonly string[] = [], + private readonly _additionalSchemaAddresses: readonly string[] = [] ) { this._attributeProducers = [ descriptionAttributeProducer, @@ -1218,19 +1206,19 @@ export class JSONSchemaInput implements Input { uriSchemaAttributesProducer, minMaxAttributeProducer, minMaxLengthAttributeProducer, - patternAttributeProducer, + patternAttributeProducer ].concat(additionalAttributeProducers); } - get needIR (): boolean { + get needIR(): boolean { return this._needIR; } - addTopLevel (name: string, ref: Ref): void { + addTopLevel(name: string, ref: Ref): void { this._topLevels.set(name, ref); } - async addTypes (ctx: RunContext, typeBuilder: TypeBuilder): Promise { + async addTypes(ctx: RunContext, typeBuilder: TypeBuilder): Promise { if (this._schemaSources.length === 0) return; let maybeSchemaStore = this._schemaStore; @@ -1279,15 +1267,15 @@ export class JSONSchemaInput implements Input { await addTypesInSchema(resolver, typeBuilder, this._topLevels, this._attributeProducers); } - addTypesSync (): void { + addTypesSync(): void { return panic("addTypesSync not supported in JSONSchemaInput"); } - async addSource (schemaSource: JSONSchemaSourceData): Promise { + async addSource(schemaSource: JSONSchemaSourceData): Promise { this.addSourceSync(schemaSource); } - addSourceSync (schemaSource: JSONSchemaSourceData): void { + addSourceSync(schemaSource: JSONSchemaSourceData): void { const { name, uris, schema, isConverted } = schemaSource; if (isConverted !== true) { @@ -1335,7 +1323,7 @@ export class JSONSchemaInput implements Input { } } - singleStringSchemaSource (): string | undefined { + singleStringSchemaSource(): string | undefined { if (!this._schemaSources.every(([_, { schema }]) => typeof schema === "string")) { return undefined; } diff --git a/packages/quicktype-core/src/language/CJSON.ts b/packages/quicktype-core/src/language/CJSON.ts index c103d3ffe..96556fe3e 100644 --- a/packages/quicktype-core/src/language/CJSON.ts +++ b/packages/quicktype-core/src/language/CJSON.ts @@ -23,20 +23,19 @@ /* Imports */ import { TargetLanguage } from "../TargetLanguage"; -import { type Type, type TypeKind} from "../Type"; +import { type Type, type TypeKind } from "../Type"; import { ClassType, ArrayType, MapType, EnumType, UnionType } from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { type NameStyle, type Name, type Namer} from "../Naming"; +import { type NameStyle, type Name, type Namer } from "../Naming"; import { funPrefixNamer } from "../Naming"; import { type Sourcelike } from "../Source"; -import { - type NamingStyle} from "../support/Strings"; +import { type NamingStyle } from "../support/Strings"; import { allUpperWordStyle, legalizeCharacters, isAscii, isLetterOrUnderscoreOrDigit, - makeNameStyle, + makeNameStyle } from "../support/Strings"; import { defined, assertNever, panic, numberEnumValues } from "../support/Support"; import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; @@ -63,10 +62,10 @@ export const cJSONOptions = { "Source code generation type, whether to generate single or multiple source files", [ ["single-source", true], - ["multi-source", false], + ["multi-source", false] ], "single-source", - "secondary", + "secondary" ), typeIntegerSize: new EnumOption( "integer-size", @@ -75,36 +74,36 @@ export const cJSONOptions = { ["int8_t", "int8_t"], ["int16_t", "int16_t"], ["int32_t", "int32_t"], - ["int64_t", "int64_t"], + ["int64_t", "int64_t"] ], "int64_t", - "secondary", + "secondary" ), hashtableSize: new StringOption( "hashtable-size", "Hashtable size, used when maps are created (64 by default)", "SIZE", - "64", + "64" ), addTypedefAlias: new EnumOption( "typedef-alias", "Add typedef alias to unions, structs, and enums (no typedef by default)", [ ["no-typedef", false], - ["add-typedef", true], + ["add-typedef", true] ], "no-typedef", - "secondary", + "secondary" ), printStyle: new EnumOption( "print-style", "Which cJSON print should be used (formatted by default)", [ ["print-formatted", false], - ["print-unformatted", true], + ["print-unformatted", true] ], "print-formatted", - "secondary", + "secondary" ), typeNamingStyle: new EnumOption("type-style", "Naming style for types", [ pascalValue, @@ -112,7 +111,7 @@ export const cJSONOptions = { camelValue, upperUnderscoreValue, pascalUpperAcronymsValue, - camelUpperAcronymsValue, + camelUpperAcronymsValue ]), memberNamingStyle: new EnumOption("member-style", "Naming style for members", [ underscoreValue, @@ -120,7 +119,7 @@ export const cJSONOptions = { camelValue, upperUnderscoreValue, pascalUpperAcronymsValue, - camelUpperAcronymsValue, + camelUpperAcronymsValue ]), enumeratorNamingStyle: new EnumOption("enumerator-style", "Naming style for enumerators", [ upperUnderscoreValue, @@ -128,8 +127,8 @@ export const cJSONOptions = { pascalValue, camelValue, pascalUpperAcronymsValue, - camelUpperAcronymsValue, - ]), + camelUpperAcronymsValue + ]) }; /* cJSON generator target language */ @@ -140,7 +139,7 @@ export class CJSONTargetLanguage extends TargetLanguage { * @params names: names * @param extension: extension of files */ - constructor (displayName = "C (cJSON)", names: string[] = ["cjson", "cJSON"], extension = "h") { + constructor(displayName = "C (cJSON)", names: string[] = ["cjson", "cJSON"], extension = "h") { super(displayName, names, extension); } @@ -148,7 +147,7 @@ export class CJSONTargetLanguage extends TargetLanguage { * Return cJSON generator options * @return cJSON generator options array */ - protected getOptions (): Array> { + protected getOptions(): Array> { return [ cJSONOptions.typeSourceStyle, cJSONOptions.typeIntegerSize, @@ -157,7 +156,7 @@ export class CJSONTargetLanguage extends TargetLanguage { cJSONOptions.hashtableSize, cJSONOptions.typeNamingStyle, cJSONOptions.memberNamingStyle, - cJSONOptions.enumeratorNamingStyle, + cJSONOptions.enumeratorNamingStyle ]; } @@ -165,7 +164,7 @@ export class CJSONTargetLanguage extends TargetLanguage { * Indicate if language support union with both number types * @return true */ - get supportsUnionsWithBothNumberTypes (): boolean { + get supportsUnionsWithBothNumberTypes(): boolean { return true; } @@ -173,7 +172,7 @@ export class CJSONTargetLanguage extends TargetLanguage { * Indicate if language support optional class properties * @return true */ - get supportsOptionalClassProperties (): boolean { + get supportsOptionalClassProperties(): boolean { return true; } @@ -183,7 +182,7 @@ export class CJSONTargetLanguage extends TargetLanguage { * @param untypedOptionValues * @return cJSON renderer */ - protected makeRenderer (renderContext: RenderContext, untypedOptionValues: { [name: string]: any, }): CJSONRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): CJSONRenderer { return new CJSONRenderer(this, renderContext, getOptionValues(cJSONOptions, untypedOptionValues)); } } @@ -311,25 +310,25 @@ const keywords = [ "String", "StringArray", "StringReference", - "True", + "True" ]; /* Used to build forbidden global names */ export enum GlobalNames { - ClassMemberConstraints, - ClassMemberConstraintException, - ValueTooLowException, - ValueTooHighException, - ValueTooShortException, - ValueTooLongException, - InvalidPatternException, - CheckConstraint + ClassMemberConstraints = 1, + ClassMemberConstraintException = 2, + ValueTooLowException = 3, + ValueTooHighException = 4, + ValueTooShortException = 5, + ValueTooLongException = 6, + InvalidPatternException = 7, + CheckConstraint = 8 } /* To be able to support circles in multiple files - e.g. class#A using class#B using class#A (obviously not directly) we can forward declare them */ export enum IncludeKind { - ForwardDeclare, - Include + ForwardDeclare = "ForwardDeclare", + Include = "Include" } /* Used to map includes */ @@ -388,10 +387,10 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param renderContext: render context * @param _options: renderer options */ - constructor ( + constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues, + private readonly _options: OptionValues ) { super(targetLanguage, renderContext); this.typeIntegerSize = _options.typeIntegerSize; @@ -411,7 +410,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Build forbidden names for namespace * @return Forbidden names for namespace */ - protected forbiddenNamesForGlobalNamespace (): string[] { + protected forbiddenNamesForGlobalNamespace(): string[] { return [...keywords, ...this.forbiddenGlobalNames]; } @@ -419,7 +418,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Build forbidden names for enums * @return Forbidden names for enums */ - protected forbiddenForEnumCases (_enumType: EnumType, _enumName: Name): ForbiddenWordsInfo { + protected forbiddenForEnumCases(_enumType: EnumType, _enumName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } @@ -427,7 +426,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Build forbidden names for unions members * @return Forbidden names for unions members */ - protected forbiddenForUnionMembers (_u: UnionType, _unionName: Name): ForbiddenWordsInfo { + protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } @@ -435,7 +434,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Build forbidden names for objects * @return Forbidden names for objects */ - protected forbiddenForObjectProperties (_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } @@ -443,7 +442,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Build types member names * @return types member namer */ - protected makeNamedTypeNamer (): Namer { + protected makeNamedTypeNamer(): Namer { return funPrefixNamer("types", this.namedTypeNameStyle); } @@ -451,7 +450,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Build object properties member names * @return object properties member namer */ - protected namerForObjectProperty (): Namer { + protected namerForObjectProperty(): Namer { return funPrefixNamer("members", this.memberNameStyle); } @@ -459,7 +458,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Build union member names * @return union member namer */ - protected makeUnionMemberNamer (): Namer { + protected makeUnionMemberNamer(): Namer { return funPrefixNamer("members", this.memberNameStyle); } @@ -467,7 +466,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Build enum member names * @return enum member namer */ - protected makeEnumCaseNamer (): Namer { + protected makeEnumCaseNamer(): Namer { return funPrefixNamer("enumerators", makeNameStyle(this.enumeratorNamingStyle, legalizeName)); } @@ -479,11 +478,11 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param lookup: Lookup function * @return Proposed union member name */ - protected proposeUnionMemberName ( + protected proposeUnionMemberName( unionType: UnionType, unionName: Name, fieldType: Type, - lookup: (n: Name) => string, + lookup: (n: Name) => string ): string { let fieldName = super.proposeUnionMemberName(unionType, unionName, fieldType, lookup); if ("bool" === fieldName) { @@ -500,7 +499,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param fieldType: the variable type * @param fieldName: name of the variable */ - protected emitTypdefAlias (fieldType: Type, fieldName: Name) { + protected emitTypdefAlias(fieldType: Type, fieldName: Name) { if (this._options.addTypedefAlias) { this.emitLine("typedef ", this.quicktypeTypeToCJSON(fieldType, false).cType, " ", fieldName, ";"); this.ensureBlankLine(); @@ -511,7 +510,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Function called to create header file(s) * @param proposedFilename: source filename provided from stdin */ - protected emitSourceStructure (proposedFilename: string): void { + protected emitSourceStructure(proposedFilename: string): void { /* Depending of source style option, generate a unique header or multiple header files */ if (this._options.typeSourceStyle) { this.emitSingleSourceStructure(proposedFilename); @@ -524,7 +523,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Function called to create a single header file with types and generators * @param proposedFilename: source filename provided from stdin */ - protected emitSingleSourceStructure (proposedFilename: string): void { + protected emitSingleSourceStructure(proposedFilename: string): void { /* Create file */ this.startFile(proposedFilename); @@ -552,12 +551,12 @@ export class CJSONRenderer extends ConvenienceRenderer { this.forEachTopLevel( "leading", (type: Type, className: Name) => this.emitTopLevelTypedef(type, className), - type => this.namedTypeToNameForTopLevel(type) === undefined, + type => this.namedTypeToNameForTopLevel(type) === undefined ); /* Create enum prototypes */ this.forEachEnum("leading-and-interposing", (enumType: EnumType, _enumName: Name) => - this.emitEnumPrototypes(enumType), + this.emitEnumPrototypes(enumType) ); /* Create union prototypes */ @@ -565,19 +564,19 @@ export class CJSONRenderer extends ConvenienceRenderer { /* Create class prototypes */ this.forEachObject("leading-and-interposing", (classType: ClassType, _className: Name) => - this.emitClassPrototypes(classType), + this.emitClassPrototypes(classType) ); /* Create top level prototypes */ this.forEachTopLevel( "leading", (type: Type, className: Name) => this.emitTopLevelPrototypes(type, className), - type => this.namedTypeToNameForTopLevel(type) === undefined, + type => this.namedTypeToNameForTopLevel(type) === undefined ); /* Create enum functions */ this.forEachEnum("leading-and-interposing", (enumType: EnumType, _enumName: Name) => - this.emitEnumFunctions(enumType), + this.emitEnumFunctions(enumType) ); /* Create union functions */ @@ -585,14 +584,14 @@ export class CJSONRenderer extends ConvenienceRenderer { /* Create class functions */ this.forEachObject("leading-and-interposing", (classType: ClassType, _className: Name) => - this.emitClassFunctions(classType), + this.emitClassFunctions(classType) ); /* Create top level functions */ this.forEachTopLevel( "leading", (type: Type, className: Name) => this.emitTopLevelFunctions(type, className), - type => this.namedTypeToNameForTopLevel(type) === undefined, + type => this.namedTypeToNameForTopLevel(type) === undefined ); /* Close file */ @@ -602,7 +601,7 @@ export class CJSONRenderer extends ConvenienceRenderer { /** * Function called to create a multiple header files with types and generators */ - protected emitMultiSourceStructure (): void { + protected emitMultiSourceStructure(): void { /* Array of includes */ let includes: string[]; @@ -617,14 +616,14 @@ export class CJSONRenderer extends ConvenienceRenderer { }, (unionType, _name) => { this.emitUnion(unionType, includes); - }, + } ); /* Create top level file */ this.forEachTopLevel( "leading", (type: Type, className: Name) => this.emitTopLevel(type, className, includes), - type => this.namedTypeToNameForTopLevel(type) === undefined, + type => this.namedTypeToNameForTopLevel(type) === undefined ); } @@ -633,7 +632,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param enumType: enum type * @param includes: Array of includes */ - protected emitEnum (enumType: EnumType, includes: string[]): void { + protected emitEnum(enumType: EnumType, includes: string[]): void { /* Create file */ const enumName = this.nameForNamedType(enumType); const filename = this.sourcelikeToString(enumName).concat(".h"); @@ -660,7 +659,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Function called to create enum typedef * @param enumType: enum type */ - protected emitEnumTypedef (enumType: EnumType): void { + protected emitEnumTypedef(enumType: EnumType): void { /* FIXME: Now there is a language with need of global enum name, see FIXME in makeNameForEnumCase of ConvenienceRenderer.ts, should simplify here when fixed */ const enumName = this.nameForNamedType(enumType); @@ -685,7 +684,7 @@ export class CJSONRenderer extends ConvenienceRenderer { }); }, "", - true, + true ); this.ensureBlankLine(); this.emitTypdefAlias(enumType, enumName); @@ -695,7 +694,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Function called to create enum prototypes * @param enumType: enum type */ - protected emitEnumPrototypes (enumType: EnumType): void { + protected emitEnumPrototypes(enumType: EnumType): void { const enumName = this.nameForNamedType(enumType); this.emitLine("enum ", enumName, " cJSON_Get", enumName, "Value(", this.withConst("cJSON"), " * j);"); @@ -707,7 +706,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Function called to create enum functions * @param enumType: enum type */ - protected emitEnumFunctions (enumType: EnumType): void { + protected emitEnumFunctions(enumType: EnumType): void { const enumName = this.nameForNamedType(enumType); /* Create cJSON to enumName generator function */ @@ -719,13 +718,13 @@ export class CJSONRenderer extends ConvenienceRenderer { this.forEachEnumCase(enumType, "none", (name, jsonName) => { this.emitLine( onFirst ? "" : "else ", - "if (!strcmp(cJSON_GetStringValue(j), \"", + 'if (!strcmp(cJSON_GetStringValue(j), "', jsonName, - "\")) x = ", + '")) x = ', combinedName, "_", name, - ";", + ";" ); onFirst = false; }); @@ -745,9 +744,9 @@ export class CJSONRenderer extends ConvenienceRenderer { combinedName, "_", name, - ": j = cJSON_CreateString(\"", + ': j = cJSON_CreateString("', jsonName, - "\"); break;", + '"); break;' ); }); }); @@ -761,7 +760,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param unionType: union type * @param includes: Array of includes */ - protected emitUnion (unionType: UnionType, includes: string[]): void { + protected emitUnion(unionType: UnionType, includes: string[]): void { /* Create file */ const unionName = this.nameForNamedType(unionType); const filename = this.sourcelikeToString(unionName).concat(".h"); @@ -788,7 +787,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Function called to create union typedef * @param unionType: union type */ - protected emitUnionTypedef (unionType: UnionType): void { + protected emitUnionTypedef(unionType: UnionType): void { const [_hasNull, nonNulls] = removeNullFromUnion(unionType); const unionName = this.nameForNamedType(unionType); @@ -808,16 +807,16 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.optionalQualifier, " ", this.nameForUnionMember(unionType, type), - ";", + ";" ); } }, "value", - true, + true ); }, "", - true, + true ); this.ensureBlankLine(); this.emitTypdefAlias(unionType, unionName); @@ -827,7 +826,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Function called to create union prototypes * @param unionType: union type */ - protected emitUnionPrototypes (unionType: UnionType): void { + protected emitUnionPrototypes(unionType: UnionType): void { const unionName = this.nameForNamedType(unionType); this.emitLine("struct ", unionName, " * cJSON_Get", unionName, "Value(const cJSON * j);"); @@ -840,7 +839,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Function called to create union functions * @param unionType: union type */ - protected emitUnionFunctions (unionType: UnionType): void { + protected emitUnionFunctions(unionType: UnionType): void { const [hasNull, nonNulls] = removeNullFromUnion(unionType); const unionName = this.nameForNamedType(unionType); @@ -873,7 +872,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ", j", level > 0 ? level.toString() : "", - ")", + ")" ], () => { const add = (cJSON: TypeCJSON, level: number, child_level: number) => { @@ -892,7 +891,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.cType, " *)0xDEADBEEF, sizeof(", cJSON.items!.cType, - " *));", + " *));" ); } else if (cJSON.items!.cjsonType === "cJSON_String") { this.emitLine( @@ -904,7 +903,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ")), sizeof(", cJSON.items!.cType, - " *));", + " *));" ); } else if ( cJSON.items!.cjsonType === "cJSON_Object" || @@ -919,7 +918,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "), sizeof(", cJSON.items!.cType, - " *));", + " *));" ); } else { this.emitLine( @@ -928,7 +927,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", " = cJSON_malloc(sizeof(", cJSON.items!.cType, - "));", + "));" ); this.emitBlock( ["if (NULL != tmp", level > 0 ? level.toString() : "", ")"], @@ -940,7 +939,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.getValue, "(e", child_level.toString(), - ");", + ");" ); this.emitLine( "list_add_tail(x", @@ -949,9 +948,9 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", ", sizeof(", cJSON.items!.cType, - " *));", + " *));" ); - }, + } ); } }; @@ -961,26 +960,26 @@ export class CJSONRenderer extends ConvenienceRenderer { ["if (!cJSON_IsNull(e", child_level.toString(), "))"], () => { add(cJSON, level, child_level); - }, + } ); this.emitBlock(["else"], () => { this.emitLine( "list_add_tail(x", child_level.toString(), - ", (void *)0xDEADBEEF, sizeof(void *));", + ", (void *)0xDEADBEEF, sizeof(void *));" ); }); } else { add(cJSON, level, child_level); } - }, + } ); this.emitLine( "x->value.", this.nameForUnionMember(unionType, type), " = x", child_level.toString(), - ";", + ";" ); }); } else if (cJSON.cjsonType === "cJSON_Map" && cJSON.items !== undefined) { @@ -992,7 +991,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), " = hashtable_create(", this.hashtableSize, - ", false);", + ", false);" ); this.emitBlock(["if (NULL != x", child_level.toString(), ")"], () => { this.emitLine("cJSON * e", child_level.toString(), " = NULL;"); @@ -1002,7 +1001,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ", j", level > 0 ? level.toString() : "", - ")", + ")" ], () => { const add = (cJSON: TypeCJSON, level: number, child_level: number) => { @@ -1023,7 +1022,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.cType, " *)0xDEADBEEF, sizeof(", cJSON.items!.cType, - " *));", + " *));" ); } else if (cJSON.items!.cjsonType === "cJSON_String") { this.emitLine( @@ -1037,7 +1036,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ")), sizeof(", cJSON.items!.cType, - " *));", + " *));" ); } else if ( cJSON.items!.cjsonType === "cJSON_Object" || @@ -1054,7 +1053,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "), sizeof(", cJSON.items!.cType, - " *));", + " *));" ); } else { this.emitLine( @@ -1063,7 +1062,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", " = cJSON_malloc(sizeof(", cJSON.items!.cType, - "));", + "));" ); this.emitBlock( ["if (NULL != tmp", level > 0 ? level.toString() : "", ")"], @@ -1075,7 +1074,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.getValue, "(e", child_level.toString(), - ");", + ");" ); this.emitLine( "hashtable_add(x", @@ -1086,9 +1085,9 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", ", sizeof(", cJSON.items!.cType, - " *));", + " *));" ); - }, + } ); } }; @@ -1098,7 +1097,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ["if (!cJSON_IsNull(e", child_level.toString(), "))"], () => { add(cJSON, level, child_level); - }, + } ); this.emitBlock(["else"], () => { this.emitLine( @@ -1106,20 +1105,20 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ", e", child_level.toString(), - "->string, (void *)0xDEADBEEF, sizeof(void *));", + "->string, (void *)0xDEADBEEF, sizeof(void *));" ); }); } else { add(cJSON, level, child_level); } - }, + } ); this.emitLine( "x->value.", this.nameForUnionMember(unionType, type), " = x", child_level.toString(), - ";", + ";" ); }); } else if (cJSON.cjsonType === "cJSON_Invalid" || cJSON.cjsonType === "cJSON_NULL") { @@ -1128,7 +1127,7 @@ export class CJSONRenderer extends ConvenienceRenderer { this.nameForUnionMember(unionType, type), " = (", cJSON.cType, - " *)0xDEADBEEF;", + " *)0xDEADBEEF;" ); } else if (cJSON.cjsonType === "cJSON_String") { this.emitLine( @@ -1136,7 +1135,7 @@ export class CJSONRenderer extends ConvenienceRenderer { this.nameForUnionMember(unionType, type), " = strdup(", cJSON.getValue, - "(j));", + "(j));" ); } else { this.emitLine( @@ -1144,7 +1143,7 @@ export class CJSONRenderer extends ConvenienceRenderer { this.nameForUnionMember(unionType, type), " = ", cJSON.getValue, - "(j);", + "(j);" ); } }); @@ -1182,7 +1181,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), " = ", cJSON.createObject, - "();", + "();" ); this.emitBlock(["if (NULL != j", child_level.toString(), ")"], () => { this.emitLine( @@ -1193,7 +1192,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->value.", this.nameForUnionMember(unionType, type), - ");", + ");" ); this.emitBlock(["while (NULL != x", child_level.toString(), ")"], () => { const add = (cJSON: TypeCJSON, child_level: number) => { @@ -1209,7 +1208,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ", ", cJSON.items!.createObject, - "());", + "());" ); } else if ( cJSON.items!.cjsonType === "cJSON_String" || @@ -1223,7 +1222,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.createObject, "(x", child_level.toString(), - "));", + "));" ); } else { this.emitLine( @@ -1233,7 +1232,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.createObject, "(*x", child_level.toString(), - "));", + "));" ); } }; @@ -1243,13 +1242,13 @@ export class CJSONRenderer extends ConvenienceRenderer { ["if ((void *)0xDEADBEEF != x", child_level.toString(), ")"], () => { add(cJSON, child_level); - }, + } ); this.emitBlock(["else"], () => { this.emitLine( "cJSON_AddItemToArray(j", child_level.toString(), - ", cJSON_CreateNull());", + ", cJSON_CreateNull());" ); }); } else { @@ -1263,7 +1262,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->value.", this.nameForUnionMember(unionType, type), - ");", + ");" ); }); this.emitLine("j = j", child_level.toString(), ";"); @@ -1276,7 +1275,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), " = ", cJSON.createObject, - "();", + "();" ); this.emitBlock(["if (NULL != j", child_level.toString(), ")"], () => { this.emitLine("char **keys", child_level.toString(), " = NULL;"); @@ -1289,7 +1288,7 @@ export class CJSONRenderer extends ConvenienceRenderer { this.nameForUnionMember(unionType, type), ", &keys", child_level.toString(), - ");", + ");" ); this.emitBlock(["if (NULL != keys", child_level.toString(), ")"], () => { this.emitBlock( @@ -1302,7 +1301,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "; index", child_level.toString(), - "++)", + "++)" ], () => { this.emitLine( @@ -1317,7 +1316,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "[index", child_level.toString(), - "]);", + "]);" ); const add = (cJSON: TypeCJSON, child_level: number) => { if (cJSON.items!.cjsonType === "cJSON_Array") { @@ -1337,7 +1336,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "], ", cJSON.items!.createObject, - "());", + "());" ); } else if ( cJSON.items!.cjsonType === "cJSON_String" || @@ -1356,7 +1355,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.createObject, "(x", child_level.toString(), - "));", + "));" ); } else { this.emitLine( @@ -1371,7 +1370,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.createObject, "(*x", child_level.toString(), - "));", + "));" ); } }; @@ -1381,11 +1380,11 @@ export class CJSONRenderer extends ConvenienceRenderer { [ "if ((void *)0xDEADBEEF != x", child_level.toString(), - ")", + ")" ], () => { add(cJSON, child_level); - }, + } ); this.emitBlock(["else"], () => { this.emitLine( @@ -1396,13 +1395,13 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "[index", child_level.toString(), - "], cJSON_CreateNull());", + "], cJSON_CreateNull());" ); }); } else { add(cJSON, child_level); } - }, + } ); this.emitLine("cJSON_free(keys", child_level.toString(), ");"); }); @@ -1418,16 +1417,16 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.createObject, "(x->value.", this.nameForUnionMember(unionType, type), - ");", + ");" ); } - }, + } ); onFirst = false; } }); this.emitLine("return j;"); - }, + } ); this.ensureBlankLine(); @@ -1447,7 +1446,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->value.", this.nameForUnionMember(unionType, type), - ")", + ")" ], () => { this.emitLine( @@ -1458,7 +1457,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->value.", this.nameForUnionMember(unionType, type), - ");", + ");" ); this.emitBlock(["while (NULL != x", child_level.toString(), ")"], () => { if (cJSON.items!.cjsonType === "cJSON_Array") { @@ -1479,16 +1478,16 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.deleteType, "(x", child_level.toString(), - ");", + ");" ); - }, + } ); } else { this.emitLine( cJSON.items!.deleteType, "(x", child_level.toString(), - ");", + ");" ); } } @@ -1500,7 +1499,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->value.", this.nameForUnionMember(unionType, type), - ");", + ");" ); }); this.emitLine( @@ -1509,9 +1508,9 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->value.", this.nameForUnionMember(unionType, type), - ");", + ");" ); - }, + } ); } else if (cJSON.cjsonType === "cJSON_Map" && cJSON.items !== undefined) { const level = 0; @@ -1522,7 +1521,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->value.", this.nameForUnionMember(unionType, type), - ")", + ")" ], () => { this.emitLine("char **keys", child_level.toString(), " = NULL;"); @@ -1535,7 +1534,7 @@ export class CJSONRenderer extends ConvenienceRenderer { this.nameForUnionMember(unionType, type), ", &keys", child_level.toString(), - ");", + ");" ); this.emitBlock(["if (NULL != keys", child_level.toString(), ")"], () => { this.emitBlock( @@ -1548,7 +1547,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "; index", child_level.toString(), - "++)", + "++)" ], () => { this.emitLine( @@ -1563,7 +1562,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "[index", child_level.toString(), - "]);", + "]);" ); this.emitBlock(["if (NULL != x", child_level.toString(), ")"], () => { if (cJSON.items!.cjsonType === "cJSON_Array") { @@ -1581,28 +1580,28 @@ export class CJSONRenderer extends ConvenienceRenderer { [ "if ((void *)0xDEADBEEF != x", child_level.toString(), - ")", + ")" ], () => { this.emitLine( cJSON.items!.deleteType, "(x", child_level.toString(), - ");", + ");" ); - }, + } ); } else { this.emitLine( cJSON.items!.deleteType, "(x", child_level.toString(), - ");", + ");" ); } } }); - }, + } ); this.emitLine("cJSON_free(keys", child_level.toString(), ");"); }); @@ -1612,9 +1611,9 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->value.", this.nameForUnionMember(unionType, type), - ");", + ");" ); - }, + } ); } else if (cJSON.cjsonType === "cJSON_Invalid" || cJSON.cjsonType === "cJSON_NULL") { /* Nothing to do */ @@ -1627,7 +1626,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.deleteType, "(x->value.", this.nameForUnionMember(unionType, type), - ");", + ");" ); } else { /* Nothing to do */ @@ -1647,7 +1646,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param classType: class type * @param includes: Array of includes */ - protected emitClass (classType: ClassType, includes: string[]): void { + protected emitClass(classType: ClassType, includes: string[]): void { /* Create file */ const className = this.nameForNamedType(classType); const filename = this.sourcelikeToString(className).concat(".h"); @@ -1674,7 +1673,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Function called to create class typedef * @param classType: class type */ - protected emitClassTypedef (classType: ClassType): void { + protected emitClassTypedef(classType: ClassType): void { const className = this.nameForNamedType(classType); this.emitDescription(this.descriptionForType(classType)); @@ -1690,12 +1689,12 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.optionalQualifier, " ", name, - ";", + ";" ); }); }, "", - true, + true ); this.ensureBlankLine(); this.emitTypdefAlias(classType, className); @@ -1705,7 +1704,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Function called to create class prototypes * @param classType: class type */ - protected emitClassPrototypes (classType: ClassType): void { + protected emitClassPrototypes(classType: ClassType): void { const className = this.nameForNamedType(classType); this.emitLine("struct ", className, " * cJSON_Parse", className, "(", this.withConst("char"), " * s);"); @@ -1720,7 +1719,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Function called to create class functions * @param classType: class type */ - protected emitClassFunctions (classType: ClassType): void { + protected emitClassFunctions(classType: ClassType): void { const className = this.nameForNamedType(classType); /* Create string to className generator function */ @@ -1736,7 +1735,7 @@ export class CJSONRenderer extends ConvenienceRenderer { }); }); this.emitLine("return x;"); - }, + } ); this.ensureBlankLine(); @@ -1768,7 +1767,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level2.toString(), ", sizeof(", cJSON.items!.cType, - " *));", + " *));" ); } else if (cJSON.cjsonType === "cJSON_Map") { /* Not supported */ @@ -1783,7 +1782,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.cType, " *)0xDEADBEEF, sizeof(", cJSON.cType, - " *));", + " *));" ); } else if (cJSON.cjsonType === "cJSON_String") { this.emitLine( @@ -1795,7 +1794,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ")), sizeof(", cJSON.cType, - " *));", + " *));" ); } else if ( cJSON.cjsonType === "cJSON_Object" || @@ -1810,7 +1809,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "), sizeof(", cJSON.cType, - " *));", + " *));" ); } else { this.emitLine( @@ -1819,7 +1818,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", " = cJSON_malloc(sizeof(", cJSON.cType, - "));", + "));" ); this.emitBlock( ["if (NULL != tmp", level > 0 ? level.toString() : "", ")"], @@ -1831,7 +1830,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.getValue, "(e", child_level.toString(), - ");", + ");" ); this.emitLine( "list_add_tail(x", @@ -1840,12 +1839,12 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", ", sizeof(", cJSON.cType, - " *));", + " *));" ); - }, + } ); } - }, + } ); }); } else if (type instanceof ClassType) { @@ -1854,23 +1853,23 @@ export class CJSONRenderer extends ConvenienceRenderer { this.emitBlock( !cJSON.isNullable ? [ - "if (cJSON_HasObjectItem(j", - level > 0 ? level.toString() : "", - ", \"", - jsonName, - "\"))", - ] + "if (cJSON_HasObjectItem(j", + level > 0 ? level.toString() : "", + ', "', + jsonName, + '"))' + ] : [ - "if ((cJSON_HasObjectItem(j", - level > 0 ? level.toString() : "", - ", \"", - jsonName, - "\")) && (!cJSON_IsNull(cJSON_GetObjectItemCaseSensitive(j", - level > 0 ? level.toString() : "", - ", \"", - jsonName, - "\"))))", - ], + "if ((cJSON_HasObjectItem(j", + level > 0 ? level.toString() : "", + ', "', + jsonName, + '")) && (!cJSON_IsNull(cJSON_GetObjectItemCaseSensitive(j', + level > 0 ? level.toString() : "", + ', "', + jsonName, + '"))))' + ], () => { if (cJSON.cjsonType === "cJSON_Array" && cJSON.items !== undefined) { const child_level = level + 1; @@ -1878,7 +1877,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.cType, " * x", child_level.toString(), - " = list_create(false, NULL);", + " = list_create(false, NULL);" ); this.emitBlock(["if (NULL != x", child_level.toString(), ")"], () => { this.emitLine("cJSON * e", child_level.toString(), " = NULL;"); @@ -1887,9 +1886,9 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), " = cJSON_GetObjectItemCaseSensitive(j", level > 0 ? level.toString() : "", - ", \"", + ', "', jsonName, - "\");", + '");' ); this.emitBlock( [ @@ -1897,14 +1896,14 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ", j", child_level.toString(), - ")", + ")" ], () => { const add = ( type: Type, cJSON: TypeCJSON, level: number, - child_level: number, + child_level: number ) => { if (cJSON.items!.cjsonType === "cJSON_Array") { if (type instanceof ArrayType) { @@ -1917,7 +1916,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level2.toString(), ", sizeof(", cJSON.items!.cType, - " *));", + " *));" ); } else { panic("Invalid type"); @@ -1935,7 +1934,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.cType, " *)0xDEADBEEF, sizeof(", cJSON.items!.cType, - " *));", + " *));" ); } else if (cJSON.items!.cjsonType === "cJSON_String") { this.emitLine( @@ -1947,7 +1946,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ")), sizeof(", cJSON.items!.cType, - " *));", + " *));" ); } else if ( cJSON.items!.cjsonType === "cJSON_Object" || @@ -1962,7 +1961,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "), sizeof(", cJSON.items!.cType, - " *));", + " *));" ); } else { this.emitLine( @@ -1971,13 +1970,13 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", " = cJSON_malloc(sizeof(", cJSON.items!.cType, - "));", + "));" ); this.emitBlock( [ "if (NULL != tmp", level > 0 ? level.toString() : "", - ")", + ")" ], () => { this.emitLine( @@ -1987,7 +1986,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.getValue, "(e", child_level.toString(), - ");", + ");" ); this.emitLine( "list_add_tail(x", @@ -1996,9 +1995,9 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", ", sizeof(", cJSON.items!.cType, - " *));", + " *));" ); - }, + } ); } }; @@ -2008,23 +2007,23 @@ export class CJSONRenderer extends ConvenienceRenderer { [ "if (!cJSON_IsNull(e", child_level.toString(), - "))", + "))" ], () => { add(property.type, cJSON, level, child_level); - }, + } ); this.emitBlock(["else"], () => { this.emitLine( "list_add_tail(x", child_level.toString(), - ", (void *)0xDEADBEEF, sizeof(void *));", + ", (void *)0xDEADBEEF, sizeof(void *));" ); }); } else { add(property.type, cJSON, level, child_level); } - }, + } ); this.emitLine( "x", @@ -2033,7 +2032,7 @@ export class CJSONRenderer extends ConvenienceRenderer { name, " = x", child_level.toString(), - ";", + ";" ); }); } else if (cJSON.cjsonType === "cJSON_Map" && cJSON.items !== undefined) { @@ -2044,7 +2043,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), " = hashtable_create(", this.hashtableSize, - ", false);", + ", false);" ); this.emitBlock(["if (NULL != x", child_level.toString(), ")"], () => { this.emitLine("cJSON * e", child_level.toString(), " = NULL;"); @@ -2053,9 +2052,9 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), " = cJSON_GetObjectItemCaseSensitive(j", level > 0 ? level.toString() : "", - ", \"", + ', "', jsonName, - "\");", + '");' ); this.emitBlock( [ @@ -2063,14 +2062,14 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ", j", child_level.toString(), - ")", + ")" ], () => { const add = ( type: Type, cJSON: TypeCJSON, level: number, - child_level: number, + child_level: number ) => { if (cJSON.items!.cjsonType === "cJSON_Array") { if (type instanceof MapType) { @@ -2085,7 +2084,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level2.toString(), ", sizeof(", cJSON.items!.cType, - " *));", + " *));" ); } else { panic("Invalid type"); @@ -2105,7 +2104,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.cType, " *)0xDEADBEEF, sizeof(", cJSON.items!.cType, - " *));", + " *));" ); } else if (cJSON.items!.cjsonType === "cJSON_String") { this.emitLine( @@ -2119,7 +2118,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ")), sizeof(", cJSON.items!.cType, - " *));", + " *));" ); } else if ( cJSON.items!.cjsonType === "cJSON_Object" || @@ -2136,7 +2135,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "), sizeof(", cJSON.items!.cType, - " *));", + " *));" ); } else { this.emitLine( @@ -2145,13 +2144,13 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", " = cJSON_malloc(sizeof(", cJSON.items!.cType, - "));", + "));" ); this.emitBlock( [ "if (NULL != tmp", level > 0 ? level.toString() : "", - ")", + ")" ], () => { this.emitLine( @@ -2161,7 +2160,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.getValue, "(e", child_level.toString(), - ");", + ");" ); this.emitLine( "hashtable_add(x", @@ -2172,9 +2171,9 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", ", sizeof(", cJSON.items!.cType, - " *));", + " *));" ); - }, + } ); } }; @@ -2184,11 +2183,11 @@ export class CJSONRenderer extends ConvenienceRenderer { [ "if (!cJSON_IsNull(e", child_level.toString(), - "))", + "))" ], () => { add(property.type, cJSON, level, child_level); - }, + } ); this.emitBlock(["else"], () => { this.emitLine( @@ -2196,13 +2195,13 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ", e", child_level.toString(), - "->string, (void *)0xDEADBEEF, sizeof(void *));", + "->string, (void *)0xDEADBEEF, sizeof(void *));" ); }); } else { add(property.type, cJSON, level, child_level); } - }, + } ); this.emitLine( "x", @@ -2211,7 +2210,7 @@ export class CJSONRenderer extends ConvenienceRenderer { name, " = x", child_level.toString(), - ";", + ";" ); }); } else if ( @@ -2225,7 +2224,7 @@ export class CJSONRenderer extends ConvenienceRenderer { name, " = (", cJSON.cType, - " *)0xDEADBEEF;", + " *)0xDEADBEEF;" ); } else if (cJSON.cjsonType === "cJSON_String") { this.emitLine( @@ -2237,9 +2236,9 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.getValue, "(cJSON_GetObjectItemCaseSensitive(j", level > 0 ? level.toString() : "", - ", \"", + ', "', jsonName, - "\")));", + '")));' ); } else if ( cJSON.cjsonType === "cJSON_Object" || @@ -2254,9 +2253,9 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.getValue, "(cJSON_GetObjectItemCaseSensitive(j", level > 0 ? level.toString() : "", - ", \"", + ', "', jsonName, - "\"));", + '"));' ); } else { if (property.isOptional || cJSON.isNullable) { @@ -2268,7 +2267,7 @@ export class CJSONRenderer extends ConvenienceRenderer { name, " = cJSON_malloc(sizeof(", cJSON.cType, - "))))", + "))))" ], () => { this.emitLine( @@ -2280,11 +2279,11 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.getValue, "(cJSON_GetObjectItemCaseSensitive(j", level > 0 ? level.toString() : "", - ", \"", + ', "', jsonName, - "\"));", + '"));' ); - }, + } ); } else { this.emitLine( @@ -2296,13 +2295,13 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.getValue, "(cJSON_GetObjectItemCaseSensitive(j", level > 0 ? level.toString() : "", - ", \"", + ', "', jsonName, - "\"));", + '"));' ); } } - }, + } ); if (!property.isOptional && !cJSON.isNullable) { if (cJSON.cjsonType === "cJSON_Array") { @@ -2312,7 +2311,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->", name, - " = list_create(false, NULL);", + " = list_create(false, NULL);" ); }); } else if (cJSON.cjsonType === "cJSON_Map") { @@ -2324,7 +2323,7 @@ export class CJSONRenderer extends ConvenienceRenderer { name, " = hashtable_create(", this.hashtableSize, - ", false);", + ", false);" ); }); } else if ( @@ -2339,7 +2338,7 @@ export class CJSONRenderer extends ConvenienceRenderer { name, " = (", cJSON.cType, - " *)0xDEADBEEF;", + " *)0xDEADBEEF;" ); }); } else if (cJSON.cjsonType === "cJSON_String") { @@ -2352,7 +2351,7 @@ export class CJSONRenderer extends ConvenienceRenderer { name, " = cJSON_malloc(sizeof(", cJSON.cType, - "))))", + "))))" ], () => { this.emitLine( @@ -2360,9 +2359,9 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->", name, - "[0] = '\\0';", + "[0] = '\\0';" ); - }, + } ); }); } else { @@ -2377,7 +2376,7 @@ export class CJSONRenderer extends ConvenienceRenderer { }); }); this.emitLine("return x;"); - }, + } ); this.ensureBlankLine(); @@ -2400,7 +2399,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), " = list_get_head(x", level.toString(), - ");", + ");" ); this.emitBlock(["while (NULL != x", child_level.toString(), ")"], () => { if (cJSON.cjsonType === "cJSON_Array") { @@ -2411,7 +2410,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ", j", child_level2.toString(), - ");", + ");" ); } else if (cJSON.cjsonType === "cJSON_Map") { /* Not supported */ @@ -2423,7 +2422,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ", ", cJSON.createObject, - "());", + "());" ); } else if ( cJSON.cjsonType === "cJSON_String" || @@ -2437,7 +2436,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.createObject, "(x", child_level.toString(), - "));", + "));" ); } else { this.emitLine( @@ -2447,7 +2446,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.createObject, "(*x", child_level.toString(), - "));", + "));" ); } @@ -2456,7 +2455,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), " = list_get_next(x", level.toString(), - ");", + ");" ); }); }); @@ -2473,9 +2472,9 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), " = cJSON_AddArrayToObject(j", level > 0 ? level.toString() : "", - ", \"", + ', "', jsonName, - "\");", + '");' ); this.emitBlock(["if (NULL != j", child_level.toString(), ")"], () => { this.emitLine( @@ -2486,7 +2485,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->", name, - ");", + ");" ); this.emitBlock( ["while (NULL != x", child_level.toString(), ")"], @@ -2494,7 +2493,7 @@ export class CJSONRenderer extends ConvenienceRenderer { const add = ( type: Type, cJSON: TypeCJSON, - child_level: number, + child_level: number ) => { if (cJSON.items!.cjsonType === "cJSON_Array") { if (type instanceof ArrayType) { @@ -2505,7 +2504,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ", j", child_level2.toString(), - ");", + ");" ); } else { panic("Invalid type"); @@ -2520,7 +2519,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), ", ", cJSON.items!.createObject, - "());", + "());" ); } else if ( cJSON.items!.cjsonType === "cJSON_String" || @@ -2534,7 +2533,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.createObject, "(x", child_level.toString(), - "));", + "));" ); } else { this.emitLine( @@ -2544,7 +2543,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.createObject, "(*x", child_level.toString(), - "));", + "));" ); } }; @@ -2554,17 +2553,17 @@ export class CJSONRenderer extends ConvenienceRenderer { [ "if ((void *)0xDEADBEEF != x", child_level.toString(), - ")", + ")" ], () => { add(property.type, cJSON, child_level); - }, + } ); this.emitBlock(["else"], () => { this.emitLine( "cJSON_AddItemToArray(j", child_level.toString(), - ", cJSON_CreateNull());", + ", cJSON_CreateNull());" ); }); } else { @@ -2578,12 +2577,12 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->", name, - ");", + ");" ); - }, + } ); }); - }, + } ); } else if (cJSON.cjsonType === "cJSON_Map" && cJSON.items !== undefined) { const child_level = level + 1; @@ -2595,7 +2594,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), " = ", cJSON.createObject, - "();", + "();" ); this.emitBlock(["if (NULL != j", child_level.toString(), ")"], () => { this.emitLine("char **keys", child_level.toString(), " = NULL;"); @@ -2608,7 +2607,7 @@ export class CJSONRenderer extends ConvenienceRenderer { name, ", &keys", child_level.toString(), - ");", + ");" ); this.emitBlock( ["if (NULL != keys", child_level.toString(), ")"], @@ -2623,7 +2622,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "; index", child_level.toString(), - "++)", + "++)" ], () => { this.emitLine( @@ -2638,12 +2637,12 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "[index", child_level.toString(), - "]);", + "]);" ); const add = ( type: Type, cJSON: TypeCJSON, - child_level: number, + child_level: number ) => { if (cJSON.items!.cjsonType === "cJSON_Array") { if (type instanceof MapType) { @@ -2659,7 +2658,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "], j", child_level2.toString(), - ");", + ");" ); } else { panic("Invalid type"); @@ -2685,7 +2684,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "], ", cJSON.items!.createObject, - "());", + "());" ); } else if ( cJSON.items!.cjsonType === "cJSON_String" || @@ -2704,7 +2703,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.createObject, "(x", child_level.toString(), - "));", + "));" ); } else { this.emitLine( @@ -2719,7 +2718,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.createObject, "(*x", child_level.toString(), - "));", + "));" ); } }; @@ -2729,11 +2728,11 @@ export class CJSONRenderer extends ConvenienceRenderer { [ "if ((void *)0xDEADBEEF != x", child_level.toString(), - ")", + ")" ], () => { add(property.type, cJSON, child_level); - }, + } ); this.emitBlock(["else"], () => { this.emitLine( @@ -2744,33 +2743,33 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "[index", child_level.toString(), - "], cJSON_CreateNull());", + "], cJSON_CreateNull());" ); }); } else { add(property.type, cJSON, child_level); } - }, + } ); this.emitLine( "cJSON_free(keys", child_level.toString(), - ");", + ");" ); - }, + } ); this.emitLine( cJSON.addToObject, "(j", level > 0 ? level.toString() : "", - ", \"", + ', "', jsonName, - "\", j", + '", j', child_level.toString(), - ");", + ");" ); }); - }, + } ); } else if (cJSON.cjsonType === "cJSON_Invalid") { /* Nothing to do */ @@ -2783,20 +2782,20 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.addToObject, "(j", level > 0 ? level.toString() : "", - ", \"", + ', "', jsonName, - "\");", + '");' ); - }, + } ); } else { this.emitLine( cJSON.addToObject, "(j", level > 0 ? level.toString() : "", - ", \"", + ', "', jsonName, - "\");", + '");' ); } } else if (cJSON.cjsonType === "cJSON_String") { @@ -2807,15 +2806,15 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.addToObject, "(j", level > 0 ? level.toString() : "", - ", \"", + ', "', jsonName, - "\", x", + '", x', level > 0 ? level.toString() : "", "->", name, - ");", + ");" ); - }, + } ); if (!property.isOptional && !cJSON.isNullable) { this.emitBlock(["else"], () => { @@ -2823,9 +2822,9 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.addToObject, "(j", level > 0 ? level.toString() : "", - ", \"", + ', "', jsonName, - "\", \"\");", + '", "");' ); }); } @@ -2841,32 +2840,32 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.addToObject, "(j", level > 0 ? level.toString() : "", - ", \"", + ', "', jsonName, - "\", ", + '", ', cJSON.createObject, "(x", level > 0 ? level.toString() : "", "->", name, - "));", + "));" ); - }, + } ); } else { this.emitLine( cJSON.addToObject, "(j", level > 0 ? level.toString() : "", - ", \"", + ', "', jsonName, - "\", ", + '", ', cJSON.createObject, "(x", level > 0 ? level.toString() : "", "->", name, - "));", + "));" ); } } else if (cJSON.cjsonType === "cJSON_Enum") { @@ -2878,32 +2877,32 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.addToObject, "(j", level > 0 ? level.toString() : "", - ", \"", + ', "', jsonName, - "\", ", + '", ', cJSON.createObject, "(*x", level > 0 ? level.toString() : "", "->", name, - "));", + "));" ); - }, + } ); } else { this.emitLine( cJSON.addToObject, "(j", level > 0 ? level.toString() : "", - ", \"", + ', "', jsonName, - "\", ", + '", ', cJSON.createObject, "(x", level > 0 ? level.toString() : "", "->", name, - "));", + "));" ); } } else { @@ -2915,28 +2914,28 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.addToObject, "(j", level > 0 ? level.toString() : "", - ", \"", + ', "', jsonName, - "\", *x", + '", *x', level > 0 ? level.toString() : "", "->", name, - ");", + ");" ); - }, + } ); } else { this.emitLine( cJSON.addToObject, "(j", level > 0 ? level.toString() : "", - ", \"", + ', "', jsonName, - "\", x", + '", x', level > 0 ? level.toString() : "", "->", name, - ");", + ");" ); } } @@ -2946,9 +2945,9 @@ export class CJSONRenderer extends ConvenienceRenderer { this.emitLine( "cJSON_AddNullToObject(j", level > 0 ? level.toString() : "", - ", \"", + ', "', jsonName, - "\");", + '");' ); }); } @@ -2960,7 +2959,7 @@ export class CJSONRenderer extends ConvenienceRenderer { }); }); this.emitLine("return j;"); - }, + } ); this.ensureBlankLine(); @@ -2991,7 +2990,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), " = list_get_head(x", level.toString(), - ");", + ");" ); this.emitBlock(["while (NULL != x", child_level.toString(), ")"], () => { if (cJSON.cjsonType === "cJSON_Array") { @@ -3023,7 +3022,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->", name, - ");", + ");" ); this.emitBlock(["while (NULL != x", child_level.toString(), ")"], () => { if (cJSON.items!.cjsonType === "cJSON_Array") { @@ -3033,7 +3032,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.deleteType, "(x", child_level.toString(), - ");", + ");" ); } else { panic("Invalid type"); @@ -3054,16 +3053,16 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.deleteType, "(x", child_level.toString(), - ");", + ");" ); - }, + } ); } else { this.emitLine( cJSON.items!.deleteType, "(x", child_level.toString(), - ");", + ");" ); } } @@ -3075,7 +3074,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->", name, - ");", + ");" ); }); this.emitLine( @@ -3084,9 +3083,9 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->", name, - ");", + ");" ); - }, + } ); } else if (cJSON.cjsonType === "cJSON_Map" && cJSON.items !== undefined) { const child_level = level + 1; @@ -3103,7 +3102,7 @@ export class CJSONRenderer extends ConvenienceRenderer { name, ", &keys", child_level.toString(), - ");", + ");" ); this.emitBlock(["if (NULL != keys", child_level.toString(), ")"], () => { this.emitBlock( @@ -3116,7 +3115,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "; index", child_level.toString(), - "++)", + "++)" ], () => { this.emitLine( @@ -3131,7 +3130,7 @@ export class CJSONRenderer extends ConvenienceRenderer { child_level.toString(), "[index", child_level.toString(), - "]);", + "]);" ); this.emitBlock( ["if (NULL != x", child_level.toString(), ")"], @@ -3143,7 +3142,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.deleteType, "(x", child_level.toString(), - ");", + ");" ); } else { panic("Invalid type"); @@ -3161,29 +3160,29 @@ export class CJSONRenderer extends ConvenienceRenderer { [ "if ((void *)0xDEADBEEF != x", child_level.toString(), - ")", + ")" ], () => { this.emitLine( cJSON.items!.deleteType, "(x", child_level.toString(), - ");", + ");" ); - }, + } ); } else { this.emitLine( cJSON.items!.deleteType, "(x", child_level.toString(), - ");", + ");" ); } } - }, + } ); - }, + } ); this.emitLine("cJSON_free(keys", child_level.toString(), ");"); }); @@ -3193,9 +3192,9 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->", name, - ");", + ");" ); - }, + } ); } else if (cJSON.cjsonType === "cJSON_Invalid" || cJSON.cjsonType === "cJSON_NULL") { /* Nothing to do */ @@ -3213,9 +3212,9 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->", name, - ");", + ");" ); - }, + } ); } else { if (property.isOptional || cJSON.isNullable) { @@ -3228,9 +3227,9 @@ export class CJSONRenderer extends ConvenienceRenderer { level > 0 ? level.toString() : "", "->", name, - ");", + ");" ); - }, + } ); } } @@ -3251,7 +3250,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param className: top level class name * @param includes: Array of includes */ - protected emitTopLevel (type: Type, className: Name, includes: string[]): void { + protected emitTopLevel(type: Type, className: Name, includes: string[]): void { /* Create file */ const filename = this.sourcelikeToString(className).concat(".h"); this.startFile(filename); @@ -3280,7 +3279,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param type: type of the top level element * @param className: top level class name */ - protected emitTopLevelTypedef (type: Type, className: Name): void { + protected emitTopLevelTypedef(type: Type, className: Name): void { this.emitBlock( ["struct ", className], () => { @@ -3289,11 +3288,11 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.cType, cJSON.optionalQualifier !== "" ? " " : "", cJSON.optionalQualifier, - " value;", + " value;" ); }, "", - true, + true ); this.ensureBlankLine(); this.emitTypdefAlias(type, className); @@ -3304,7 +3303,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param type: type of the top level element * @param className: top level class name */ - protected emitTopLevelPrototypes (_type: Type, className: Name): void { + protected emitTopLevelPrototypes(_type: Type, className: Name): void { this.emitLine("struct ", className, " * cJSON_Parse", className, "(", this.withConst("char"), " * s);"); this.emitLine("struct ", className, " * cJSON_Get", className, "Value(", this.withConst("cJSON"), " * j);"); this.emitLine("cJSON * cJSON_Create", className, "(", this.withConst(["struct ", className]), " * x);"); @@ -3318,7 +3317,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param type: type of the top level element * @param className: top level class name */ - protected emitTopLevelFunctions (type: Type, className: Name): void { + protected emitTopLevelFunctions(type: Type, className: Name): void { /* Create string to className generator function */ this.emitBlock( ["struct ", className, " * cJSON_Parse", className, "(", this.withConst("char"), " * s)"], @@ -3332,7 +3331,7 @@ export class CJSONRenderer extends ConvenienceRenderer { }); }); this.emitLine("return x;"); - }, + } ); this.ensureBlankLine(); @@ -3364,7 +3363,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.cType, " *)0xDEADBEAF, sizeof(", cJSON.items!.cType, - " *));", + " *));" ); } else if (cJSON.items!.cjsonType === "cJSON_String") { this.emitLine( @@ -3372,7 +3371,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.getValue, "(e)), sizeof(", cJSON.items!.cType, - " *));", + " *));" ); } else { this.emitLine( @@ -3380,7 +3379,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.getValue, "(e), sizeof(", cJSON.items!.cType, - " *));", + " *));" ); } }; @@ -3391,7 +3390,7 @@ export class CJSONRenderer extends ConvenienceRenderer { }); this.emitBlock(["else"], () => { this.emitLine( - "list_add_tail(x->value, (void *)0xDEADBEEF, sizeof(void *));", + "list_add_tail(x->value, (void *)0xDEADBEEF, sizeof(void *));" ); }); } else { @@ -3418,7 +3417,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.cType, " *)0xDEADBEEF, sizeof(", cJSON.items!.cType, - " *));", + " *));" ); } else if (cJSON.items!.cjsonType === "cJSON_String") { this.emitLine( @@ -3426,7 +3425,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.getValue, "(e)), sizeof(", cJSON.items!.cType, - " *));", + " *));" ); } else { this.emitLine( @@ -3434,7 +3433,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.items!.getValue, "(e), sizeof(", cJSON.items!.cType, - " *));", + " *));" ); } }; @@ -3445,7 +3444,7 @@ export class CJSONRenderer extends ConvenienceRenderer { }); this.emitBlock(["else"], () => { this.emitLine( - "hashtable_add(x->value, e->string, (void *)0xDEADBEEF, sizeof(void *));", + "hashtable_add(x->value, e->string, (void *)0xDEADBEEF, sizeof(void *));" ); }); } else { @@ -3465,7 +3464,7 @@ export class CJSONRenderer extends ConvenienceRenderer { }); }); this.emitLine("return x;"); - }, + } ); this.ensureBlankLine(); @@ -3493,7 +3492,7 @@ export class CJSONRenderer extends ConvenienceRenderer { this.emitLine( "cJSON_AddItemToArray(j, ", cJSON.items!.createObject, - "());", + "());" ); } else if ( cJSON.items!.cjsonType === "cJSON_String" || @@ -3503,13 +3502,13 @@ export class CJSONRenderer extends ConvenienceRenderer { this.emitLine( "cJSON_AddItemToArray(j, ", cJSON.items!.createObject, - "(x1));", + "(x1));" ); } else { this.emitLine( "cJSON_AddItemToArray(j, ", cJSON.items!.createObject, - "(*x1));", + "(*x1));" ); } }; @@ -3539,7 +3538,7 @@ export class CJSONRenderer extends ConvenienceRenderer { this.emitBlock(["for (size_t index = 0; index < count; index++)"], () => { this.emitLine( cJSON.items!.cType, - " *x2 = hashtable_lookup(x->value, keys[index]);", + " *x2 = hashtable_lookup(x->value, keys[index]);" ); const add = (cJSON: TypeCJSON) => { if (cJSON.items!.cjsonType === "cJSON_Array") { @@ -3553,7 +3552,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.addToObject, "(j, keys[index], ", cJSON.items!.createObject, - "());", + "());" ); } else if ( cJSON.items!.cjsonType === "cJSON_String" || @@ -3564,14 +3563,14 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON.addToObject, "(j, keys[index], ", cJSON.items!.createObject, - "(x2));", + "(x2));" ); } else { this.emitLine( cJSON.addToObject, "(j, keys[index], ", cJSON.items!.createObject, - "(*x2));", + "(*x2));" ); } }; @@ -3583,7 +3582,7 @@ export class CJSONRenderer extends ConvenienceRenderer { this.emitBlock(["else"], () => { this.emitLine( cJSON.addToObject, - "(j, keys[index], cJSON_CreateNull());", + "(j, keys[index], cJSON_CreateNull());" ); }); } else { @@ -3603,7 +3602,7 @@ export class CJSONRenderer extends ConvenienceRenderer { } }); this.emitLine("return j;"); - }, + } ); this.ensureBlankLine(); @@ -3687,7 +3686,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param isNullable: true if the field is nullable * @return cJSON type */ - protected quicktypeTypeToCJSON (t: Type, isOptional: boolean, isNullable = false): TypeCJSON { + protected quicktypeTypeToCJSON(t: Type, isOptional: boolean, isNullable = false): TypeCJSON { /* Compute cJSON type */ return matchType( t, @@ -3702,7 +3701,7 @@ export class CJSONRenderer extends ConvenienceRenderer { createObject: "", deleteType: "", items: undefined, - isNullable, + isNullable }; }, _nullType => { @@ -3716,7 +3715,7 @@ export class CJSONRenderer extends ConvenienceRenderer { createObject: "cJSON_CreateNull", deleteType: "cJSON_free", items: undefined, - isNullable, + isNullable }; }, _boolType => { @@ -3730,7 +3729,7 @@ export class CJSONRenderer extends ConvenienceRenderer { createObject: "cJSON_CreateBool", deleteType: "cJSON_free", items: undefined, - isNullable, + isNullable }; }, _integerType => { @@ -3744,7 +3743,7 @@ export class CJSONRenderer extends ConvenienceRenderer { createObject: "cJSON_CreateNumber", deleteType: "cJSON_free", items: undefined, - isNullable, + isNullable }; }, _doubleType => { @@ -3758,7 +3757,7 @@ export class CJSONRenderer extends ConvenienceRenderer { createObject: "cJSON_CreateNumber", deleteType: "cJSON_free", items: undefined, - isNullable, + isNullable }; }, _stringType => { @@ -3772,7 +3771,7 @@ export class CJSONRenderer extends ConvenienceRenderer { createObject: "cJSON_CreateString", deleteType: "cJSON_free", items: undefined, - isNullable, + isNullable }; }, arrayType => { @@ -3787,7 +3786,7 @@ export class CJSONRenderer extends ConvenienceRenderer { createObject: "cJSON_CreateArray", deleteType: "list_release", items, - isNullable, + isNullable }; }, classType => { @@ -3801,7 +3800,7 @@ export class CJSONRenderer extends ConvenienceRenderer { createObject: ["cJSON_Create", this.nameForNamedType(classType)], deleteType: ["cJSON_Delete", this.nameForNamedType(classType)], items: undefined, - isNullable, + isNullable }; }, mapType => { @@ -3816,7 +3815,7 @@ export class CJSONRenderer extends ConvenienceRenderer { createObject: "cJSON_CreateObject", deleteType: "hashtable_release", items, - isNullable, + isNullable }; }, enumType => { @@ -3830,7 +3829,7 @@ export class CJSONRenderer extends ConvenienceRenderer { createObject: ["cJSON_Create", this.nameForNamedType(enumType)], deleteType: "cJSON_free", items: undefined, - isNullable, + isNullable }; }, unionType => { @@ -3848,10 +3847,10 @@ export class CJSONRenderer extends ConvenienceRenderer { createObject: ["cJSON_Create", this.nameForNamedType(unionType)], deleteType: ["cJSON_Delete", this.nameForNamedType(unionType)], items: undefined, - isNullable, + isNullable }; } - }, + } ); } @@ -3859,7 +3858,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Function called to create a file * @param proposedFilename: source filename provided from stdin */ - protected startFile (proposedFilename: Sourcelike): void { + protected startFile(proposedFilename: Sourcelike): void { /* Check if previous file is closed, create a new file */ assert(this.currentFilename === undefined, "Previous file wasn't finished"); if (proposedFilename !== undefined) { @@ -3877,7 +3876,7 @@ export class CJSONRenderer extends ConvenienceRenderer { "To get json data from cJSON object use the following: struct * data = cJSON_GetValue();", "To get cJSON object from json data use the following: cJSON * cjson = cJSON_Create();", "To print json string from json data use the following: char * string = cJSON_Print();", - "To delete json data use the following: cJSON_Delete();", + "To delete json data use the following: cJSON_Delete();" ]); this.ensureBlankLine(); @@ -3885,18 +3884,18 @@ export class CJSONRenderer extends ConvenienceRenderer { this.emitLine( "#ifndef __", allUpperWordStyle(this.currentFilename.replace(new RegExp(/[^a-zA-Z0-9]+/, "g"), "_")), - "__", + "__" ); this.emitLine( "#define __", allUpperWordStyle(this.currentFilename.replace(new RegExp(/[^a-zA-Z0-9]+/, "g"), "_")), - "__", + "__" ); this.ensureBlankLine(); /* Write C++ guard */ this.emitLine("#ifdef __cplusplus"); - this.emitLine("extern \"C\" {"); + this.emitLine('extern "C" {'); this.emitLine("#endif"); this.ensureBlankLine(); @@ -3927,7 +3926,7 @@ export class CJSONRenderer extends ConvenienceRenderer { /** * Function called to close current file */ - protected finishFile (): void { + protected finishFile(): void { /* Check if file has been created */ if (this.currentFilename !== undefined) { /* Write C++ guard */ @@ -3940,7 +3939,7 @@ export class CJSONRenderer extends ConvenienceRenderer { this.emitLine( "#endif /* __", allUpperWordStyle(this.currentFilename.replace(new RegExp(/[^a-zA-Z0-9]+/, "g"), "_")), - "__ */", + "__ */" ); this.ensureBlankLine(); @@ -3955,7 +3954,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @note If returning true, canBeForwardDeclared must be declared * @return Always returns true */ - protected get needsTypeDeclarationBeforeUse (): boolean { + protected get needsTypeDeclarationBeforeUse(): boolean { return true; } @@ -3963,7 +3962,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Check if type can be forward declared * @return true for classes, false otherwise */ - protected canBeForwardDeclared (type: Type): boolean { + protected canBeForwardDeclared(type: Type): boolean { return type.kind === "class"; } @@ -3971,7 +3970,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * Add const to wanted Sourcelike * @return Const Sourcelike */ - protected withConst (s: Sourcelike): Sourcelike { + protected withConst(s: Sourcelike): Sourcelike { return ["const ", s]; } @@ -3980,15 +3979,15 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param name: filename to include * @pram global: true if global include, false otherwise (default) */ - protected emitIncludeLine (name: Sourcelike, global = false): void { - this.emitLine("#include ", global ? "<" : "\"", name, global ? ">" : "\""); + protected emitIncludeLine(name: Sourcelike, global = false): void { + this.emitLine("#include ", global ? "<" : '"', name, global ? ">" : '"'); } /** * Emit description block * @param lines: description block lines */ - protected emitDescriptionBlock (lines: Sourcelike[]): void { + protected emitDescriptionBlock(lines: Sourcelike[]): void { this.emitCommentLines(lines, { lineStart: " * ", beforeComment: "/**", afterComment: " */" }); } @@ -4000,12 +3999,12 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param withSemicolon: true to add semicolon at the end of the block, false otherwise * @param withIndent: true to indent the block (default), false otherwise */ - protected emitBlock ( + protected emitBlock( line: Sourcelike, f: () => void, withName = "", withSemicolon = false, - withIndent = true, + withIndent = true ): void { this.emitLine(line, " {"); this.preventBlankLine(); @@ -4036,7 +4035,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param type: class, union or enum type * @param filename: current file name */ - protected emitIncludes (type: ClassType | UnionType | EnumType, filename: string): void { + protected emitIncludes(type: ClassType | UnionType | EnumType, filename: string): void { /* List required includes */ const includes: IncludeMap = new Map(); if (type instanceof UnionType) { @@ -4066,7 +4065,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param includes: include map * @param propertyType: property type */ - protected updateIncludes (isClassMember: boolean, includes: IncludeMap, propertyType: Type): void { + protected updateIncludes(isClassMember: boolean, includes: IncludeMap, propertyType: Type): void { const propTypes = this.generatedTypes(isClassMember, propertyType); for (const t of propTypes) { const typeName = this.sourcelikeToString(t.name); @@ -4116,7 +4115,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param type: type * @return Type record array */ - protected generatedTypes (isClassMember: boolean, type: Type): TypeRecord[] { + protected generatedTypes(isClassMember: boolean, type: Type): TypeRecord[] { const result: TypeRecord[] = []; const recur = (forceInclude: boolean, isVariant: boolean, l: number, t: Type) => { if (t instanceof ArrayType) { @@ -4127,7 +4126,7 @@ export class CJSONRenderer extends ConvenienceRenderer { type: t, level: l, variant: isVariant, - forceInclude, + forceInclude }); } else if (t instanceof MapType) { recur(forceInclude, isVariant, l + 1, t.values); @@ -4137,7 +4136,7 @@ export class CJSONRenderer extends ConvenienceRenderer { type: t, level: l, variant: isVariant, - forceInclude: false, + forceInclude: false }); } else if (t instanceof UnionType) { /** @@ -4161,7 +4160,7 @@ export class CJSONRenderer extends ConvenienceRenderer { type: t, level: l, variant: true, - forceInclude, + forceInclude }); /** intentional "fall-through", add all subtypes as well - but forced include */ } diff --git a/packages/quicktype-core/src/language/CPlusPlus.ts b/packages/quicktype-core/src/language/CPlusPlus.ts index c486c7827..94b60d3a4 100644 --- a/packages/quicktype-core/src/language/CPlusPlus.ts +++ b/packages/quicktype-core/src/language/CPlusPlus.ts @@ -5,26 +5,25 @@ import { iterableFirst, iterableFind, iterableSome, - withDefault, + withDefault } from "collection-utils"; import { TargetLanguage } from "../TargetLanguage"; -import { type Type, type TypeKind, type ClassProperty} from "../Type"; +import { type Type, type TypeKind, type ClassProperty } from "../Type"; import { ClassType, ArrayType, MapType, EnumType, UnionType } from "../Type"; import { nullableFromUnion, matchType, removeNullFromUnion, isNamedType, directlyReachableTypes } from "../TypeUtils"; -import { type NameStyle, type Name, type Namer} from "../Naming"; +import { type NameStyle, type Name, type Namer } from "../Naming"; import { funPrefixNamer, DependencyName } from "../Naming"; -import { type Sourcelike} from "../Source"; +import { type Sourcelike } from "../Source"; import { maybeAnnotated } from "../Source"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { - type NamingStyle} from "../support/Strings"; +import { type NamingStyle } from "../support/Strings"; import { legalizeCharacters, isAscii, isLetterOrUnderscoreOrDigit, stringEscape, - makeNameStyle, + makeNameStyle } from "../support/Strings"; import { defined, assertNever, panic, numberEnumValues } from "../support/Support"; import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; @@ -52,47 +51,47 @@ export const cPlusPlusOptions = { "Source code generation type, whether to generate single or multiple source files", [ ["single-source", true], - ["multi-source", false], + ["multi-source", false] ], "single-source", - "secondary", + "secondary" ), includeLocation: new EnumOption( "include-location", "Whether json.hpp is to be located globally or locally", [ ["local-include", true], - ["global-include", false], + ["global-include", false] ], "local-include", - "secondary", + "secondary" ), codeFormat: new EnumOption( "code-format", "Generate classes with getters/setters, instead of structs", [ ["with-struct", false], - ["with-getter-setter", true], + ["with-getter-setter", true] ], - "with-getter-setter", + "with-getter-setter" ), wstring: new EnumOption( "wstring", "Store strings using Utf-16 std::wstring, rather than Utf-8 std::string", [ ["use-string", false], - ["use-wstring", true], + ["use-wstring", true] ], - "use-string", + "use-string" ), westConst: new EnumOption( "const-style", "Put const to the left/west (const T) or right/east (T const)", [ ["west-const", true], - ["east-const", false], + ["east-const", false] ], - "west-const", + "west-const" ), justTypes: new BooleanOption("just-types", "Plain types only", false), namespace: new StringOption("namespace", "Name of the generated namespace(s)", "NAME", "quicktype"), @@ -103,7 +102,7 @@ export const cPlusPlusOptions = { camelValue, upperUnderscoreValue, pascalUpperAcronymsValue, - camelUpperAcronymsValue, + camelUpperAcronymsValue ]), memberNamingStyle: new EnumOption("member-style", "Naming style for members", [ underscoreValue, @@ -111,7 +110,7 @@ export const cPlusPlusOptions = { camelValue, upperUnderscoreValue, pascalUpperAcronymsValue, - camelUpperAcronymsValue, + camelUpperAcronymsValue ]), enumeratorNamingStyle: new EnumOption("enumerator-style", "Naming style for enumerators", [ upperUnderscoreValue, @@ -119,18 +118,18 @@ export const cPlusPlusOptions = { pascalValue, camelValue, pascalUpperAcronymsValue, - camelUpperAcronymsValue, + camelUpperAcronymsValue ]), boost: new BooleanOption("boost", "Require a dependency on boost. Without boost, C++17 is required", true), - hideNullOptional: new BooleanOption("hide-null-optional", "Hide null value for optional field", false), + hideNullOptional: new BooleanOption("hide-null-optional", "Hide null value for optional field", false) }; export class CPlusPlusTargetLanguage extends TargetLanguage { - constructor (displayName = "C++", names: string[] = ["c++", "cpp", "cplusplus"], extension = "cpp") { + constructor(displayName = "C++", names: string[] = ["c++", "cpp", "cplusplus"], extension = "cpp") { super(displayName, names, extension); } - protected getOptions (): Array> { + protected getOptions(): Array> { return [ cPlusPlusOptions.justTypes, cPlusPlusOptions.namespace, @@ -144,33 +143,33 @@ export class CPlusPlusTargetLanguage extends TargetLanguage { cPlusPlusOptions.enumeratorNamingStyle, cPlusPlusOptions.enumType, cPlusPlusOptions.boost, - cPlusPlusOptions.hideNullOptional, + cPlusPlusOptions.hideNullOptional ]; } - get supportsUnionsWithBothNumberTypes (): boolean { + get supportsUnionsWithBothNumberTypes(): boolean { return true; } - get supportsOptionalClassProperties (): boolean { + get supportsOptionalClassProperties(): boolean { return true; } - protected makeRenderer ( + protected makeRenderer( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any, }, + untypedOptionValues: { [name: string]: any } ): CPlusPlusRenderer { return new CPlusPlusRenderer(this, renderContext, getOptionValues(cPlusPlusOptions, untypedOptionValues)); } } -function constraintsForType (t: Type): -| { - minMax?: MinMaxConstraint, - minMaxLength?: MinMaxConstraint, - pattern?: string, -} -| undefined { +function constraintsForType(t: Type): + | { + minMax?: MinMaxConstraint; + minMaxLength?: MinMaxConstraint; + pattern?: string; + } + | undefined { const minMax = minMaxValueForType(t); const minMaxLength = minMaxLengthForType(t); const pattern = patternForType(t); @@ -280,7 +279,7 @@ const keywords = [ "final", "transaction_safe", "transaction_safe_dynamic", - "NULL", + "NULL" ]; /// Type to use as an optional if cycle breaking is required @@ -294,43 +293,45 @@ const optionalFactoryAsSharedType = "std::make_shared"; * but in vector or in variant) we can forward declare them; */ export enum IncludeKind { - ForwardDeclare, - Include + ForwardDeclare = "ForwardDeclare", + Include = "Include" } +// FIXME: make these string enums eventually export enum GlobalNames { - ClassMemberConstraints, - ClassMemberConstraintException, - ValueTooLowException, - ValueTooHighException, - ValueTooShortException, - ValueTooLongException, - InvalidPatternException, - CheckConstraint + ClassMemberConstraints = 1, + ClassMemberConstraintException = 2, + ValueTooLowException = 3, + ValueTooHighException = 4, + ValueTooShortException = 5, + ValueTooLongException = 6, + InvalidPatternException = 7, + CheckConstraint = 8 } +// FIXME: make these string enums eventually export enum MemberNames { - MinIntValue, - GetMinIntValue, - SetMinIntValue, - MaxIntValue, - GetMaxIntValue, - SetMaxIntValue, - MinDoubleValue, - GetMinDoubleValue, - SetMinDoubleValue, - MaxDoubleValue, - GetMaxDoubleValue, - SetMaxDoubleValue, - MinLength, - GetMinLength, - SetMinLength, - MaxLength, - GetMaxLength, - SetMaxLength, - Pattern, - GetPattern, - SetPattern + MinIntValue = 1, + GetMinIntValue = 2, + SetMinIntValue = 3, + MaxIntValue = 4, + GetMaxIntValue = 5, + SetMaxIntValue = 6, + MinDoubleValue = 7, + GetMinDoubleValue = 8, + SetMinDoubleValue = 9, + MaxDoubleValue = 10, + GetMaxDoubleValue = 11, + SetMaxDoubleValue = 12, + MinLength = 13, + GetMinLength = 14, + SetMinLength = 15, + MaxLength = 16, + GetMaxLength = 17, + SetMaxLength = 18, + Pattern = 19, + GetPattern = 20, + SetPattern = 21 } interface ConstraintMember { @@ -382,7 +383,7 @@ interface StringType { wrapToString: (inner: Sourcelike) => Sourcelike; } -function addQualifier (qualifier: Sourcelike, qualified: Sourcelike[]): Sourcelike[] { +function addQualifier(qualifier: Sourcelike, qualified: Sourcelike[]): Sourcelike[] { if (qualified.length === 0) { return []; } @@ -391,12 +392,12 @@ function addQualifier (qualifier: Sourcelike, qualified: Sourcelike[]): Sourceli } class WrappingCode { - constructor ( + constructor( private readonly start: Sourcelike[], - private readonly end: Sourcelike[], + private readonly end: Sourcelike[] ) {} - wrap (qualifier: Sourcelike, inner: Sourcelike): Sourcelike { + wrap(qualifier: Sourcelike, inner: Sourcelike): Sourcelike { return [addQualifier(qualifier, this.start), inner, this.end]; } } @@ -418,7 +419,7 @@ class BaseString { public _encodingFunction: Sourcelike; - constructor ( + constructor( stringType: string, constStringType: string, smatch: string, @@ -426,7 +427,7 @@ class BaseString { stringLiteralPrefix: string, toString: WrappingCode, encodingClass: string, - encodingFunction: string, + encodingFunction: string ) { this._stringType = stringType; this._constStringType = constStringType; @@ -438,27 +439,27 @@ class BaseString { this._encodingFunction = encodingFunction; } - public getType (): string { + public getType(): string { return this._stringType; } - public getConstType (): string { + public getConstType(): string { return this._constStringType; } - public getSMatch (): string { + public getSMatch(): string { return this._smatch; } - public getRegex (): string { + public getRegex(): string { return this._regex; } - public createStringLiteral (inner: Sourcelike): Sourcelike { - return [this._stringLiteralPrefix, "\"", inner, "\""]; + public createStringLiteral(inner: Sourcelike): Sourcelike { + return [this._stringLiteralPrefix, '"', inner, '"']; } - public wrapToString (inner: Sourcelike): Sourcelike { + public wrapToString(inner: Sourcelike): Sourcelike { return this._toString.wrap([], inner); } } @@ -508,10 +509,10 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { protected readonly enumeratorNamingStyle: NamingStyle; - constructor ( + constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues, + private readonly _options: OptionValues ) { super(targetLanguage, renderContext); @@ -556,14 +557,14 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } // union typeguard - isUnion (t: Type | UnionType): t is UnionType { + isUnion(t: Type | UnionType): t is UnionType { return t.kind === "union"; } // Returns true if the type can be stored in // a stack based optional type. This requires // that the type does not require forward declaration. - isOptionalAsValuePossible (t: Type): boolean { + isOptionalAsValuePossible(t: Type): boolean { if (this.isForwardDeclaredType(t)) return false; if (this.isUnion(t)) { @@ -625,113 +626,113 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { return !this.isCycleBreakerType(t); } - isImplicitCycleBreaker (t: Type): boolean { + isImplicitCycleBreaker(t: Type): boolean { const kind = t.kind; return kind === "array" || kind === "map"; } // Is likely to return std::optional or boost::optional - optionalTypeStack (): string { + optionalTypeStack(): string { return this._optionalType; } // Is likely to return std::make_optional or boost::optional - optionalFactoryStack (): string { + optionalFactoryStack(): string { return this._optionalFactory; } // Is likely to return std::shared_ptr - optionalTypeHeap (): string { + optionalTypeHeap(): string { return optionalAsSharedType; } // Is likely to return std::make_shared - optionalFactoryHeap (): string { + optionalFactoryHeap(): string { return optionalFactoryAsSharedType; } // Returns the optional type most suitable for the given type. // Classes that don't require forward declarations can be stored // in std::optional ( or boost::optional ) - optionalType (t: Type): string { + optionalType(t: Type): string { if (this.isOptionalAsValuePossible(t)) return this.optionalTypeStack(); else return this.optionalTypeHeap(); } // Returns a label that can be used to distinguish between // heap and stack based optional handling methods - optionalTypeLabel (t: Type): string { + optionalTypeLabel(t: Type): string { if (this.isOptionalAsValuePossible(t)) return "stack"; else return "heap"; } - protected getConstraintMembers (): ConstraintMember[] { + protected getConstraintMembers(): ConstraintMember[] { return [ { name: MemberNames.MinIntValue, getter: MemberNames.GetMinIntValue, setter: MemberNames.SetMinIntValue, - cppType: "int64_t", + cppType: "int64_t" }, { name: MemberNames.MaxIntValue, getter: MemberNames.GetMaxIntValue, setter: MemberNames.SetMaxIntValue, - cppType: "int64_t", + cppType: "int64_t" }, { name: MemberNames.MinDoubleValue, getter: MemberNames.GetMinDoubleValue, setter: MemberNames.SetMinDoubleValue, - cppType: "double", + cppType: "double" }, { name: MemberNames.MaxDoubleValue, getter: MemberNames.GetMaxDoubleValue, setter: MemberNames.SetMaxDoubleValue, - cppType: "double", + cppType: "double" }, { name: MemberNames.MinLength, getter: MemberNames.GetMinLength, setter: MemberNames.SetMinLength, - cppType: "size_t", + cppType: "size_t" }, { name: MemberNames.MaxLength, getter: MemberNames.GetMaxLength, setter: MemberNames.SetMaxLength, - cppType: "size_t", + cppType: "size_t" }, { name: MemberNames.Pattern, getter: MemberNames.GetPattern, setter: MemberNames.SetPattern, cppType: this._stringType.getType(), - cppConstType: this._stringType.getConstType(), - }, + cppConstType: this._stringType.getConstType() + } ]; } - protected lookupGlobalName (type: GlobalNames): string { + protected lookupGlobalName(type: GlobalNames): string { return defined(this._generatedGlobalNames.get(type)); } - protected lookupMemberName (type: MemberNames): string { + protected lookupMemberName(type: MemberNames): string { return defined(this._generatedMemberNames.get(type)); } - protected addGlobalName (type: GlobalNames): void { + protected addGlobalName(type: GlobalNames): void { const genName = this._namedTypeNameStyle(GlobalNames[type]); this._generatedGlobalNames.set(type, genName); this._forbiddenGlobalNames.push(genName); } - protected addMemberName (type: MemberNames): void { + protected addMemberName(type: MemberNames): void { this._generatedMemberNames.set(type, this._memberNameStyle(MemberNames[type])); } - protected setupGlobalNames (): void { + protected setupGlobalNames(): void { for (const v of numberEnumValues(GlobalNames)) { this.addGlobalName(v); } @@ -741,64 +742,64 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } - protected forbiddenNamesForGlobalNamespace (): string[] { + protected forbiddenNamesForGlobalNamespace(): string[] { return [...keywords, ...this._forbiddenGlobalNames]; } - protected forbiddenForObjectProperties (_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForEnumCases (_e: EnumType, _enumName: Name): ForbiddenWordsInfo { + protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected makeNamedTypeNamer (): Namer { + protected makeNamedTypeNamer(): Namer { return funPrefixNamer("types", this._namedTypeNameStyle); } - protected namerForObjectProperty (): Namer { + protected namerForObjectProperty(): Namer { return this._memberNamingFunction; } - protected makeUnionMemberNamer (): null { + protected makeUnionMemberNamer(): null { return null; } - protected makeEnumCaseNamer (): Namer { + protected makeEnumCaseNamer(): Namer { return funPrefixNamer("enumerators", makeNameStyle(this.enumeratorNamingStyle, legalizeName)); } - protected makeNamesForPropertyGetterAndSetter ( + protected makeNamesForPropertyGetterAndSetter( _c: ClassType, _className: Name, _p: ClassProperty, _jsonName: string, - name: Name, + name: Name ): [Name, Name, Name] { const getterName = new DependencyName(this._memberNamingFunction, name.order, lookup => `get_${lookup(name)}`); const mutableGetterName = new DependencyName( this._memberNamingFunction, name.order, - lookup => `getMutable_${lookup(name)}`, + lookup => `getMutable_${lookup(name)}` ); const setterName = new DependencyName(this._memberNamingFunction, name.order, lookup => `set_${lookup(name)}`); return [getterName, mutableGetterName, setterName]; } - protected makePropertyDependencyNames ( + protected makePropertyDependencyNames( c: ClassType, className: Name, p: ClassProperty, jsonName: string, - name: Name, + name: Name ): Name[] { const getterAndSetterNames = this.makeNamesForPropertyGetterAndSetter(c, className, p, jsonName, name); this._gettersAndSettersForPropertyName.set(name, getterAndSetterNames); return getterAndSetterNames; } - protected withConst (s: Sourcelike): Sourcelike { + protected withConst(s: Sourcelike): Sourcelike { if (this._options.westConst) { return ["const ", s]; } else { @@ -806,11 +807,11 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } - protected emitInclude (global: boolean, name: Sourcelike): void { - this.emitLine("#include ", global ? "<" : "\"", name, global ? ">" : "\""); + protected emitInclude(global: boolean, name: Sourcelike): void { + this.emitLine("#include ", global ? "<" : '"', name, global ? ">" : '"'); } - protected startFile (basename: Sourcelike, includeHelper = true): void { + protected startFile(basename: Sourcelike, includeHelper = true): void { assert(this._currentFilename === undefined, "Previous file wasn't finished"); if (basename !== undefined) { this._currentFilename = this.sourcelikeToString(basename); @@ -828,7 +829,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { " json.hpp https://github.com/nlohmann/json", "", " Then include this file, and then do", - "", + "" ]); if (this._options.typeSourceStyle) { @@ -885,25 +886,25 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.ensureBlankLine(); } - protected finishFile (): void { + protected finishFile(): void { super.finishFile(defined(this._currentFilename)); this._currentFilename = undefined; } - protected get needsTypeDeclarationBeforeUse (): boolean { + protected get needsTypeDeclarationBeforeUse(): boolean { return true; } - protected canBeForwardDeclared (t: Type): boolean { + protected canBeForwardDeclared(t: Type): boolean { const kind = t.kind; return kind === "class"; } - protected emitDescriptionBlock (lines: Sourcelike[]): void { + protected emitDescriptionBlock(lines: Sourcelike[]): void { this.emitCommentLines(lines, { lineStart: " * ", beforeComment: "/**", afterComment: " */" }); } - protected emitBlock (line: Sourcelike, withSemicolon: boolean, f: () => void, withIndent = true): void { + protected emitBlock(line: Sourcelike, withSemicolon: boolean, f: () => void, withIndent = true): void { this.emitLine(line, " {"); this.preventBlankLine(); if (withIndent) { @@ -920,7 +921,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } - protected emitNamespaces (namespaceNames: Iterable, f: () => void): void { + protected emitNamespaces(namespaceNames: Iterable, f: () => void): void { const namesArray = toReadonlyArray(namespaceNames); const first = namesArray[0]; if (first === undefined) { @@ -930,16 +931,16 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { ["namespace ", first], false, () => this.emitNamespaces(namesArray.slice(1), f), - namesArray.length === 1, + namesArray.length === 1 ); } } - protected cppTypeInOptional ( + protected cppTypeInOptional( nonNulls: ReadonlySet, ctx: TypeContext, withIssues: boolean, - forceNarrowString: boolean, + forceNarrowString: boolean ): Sourcelike { if (nonNulls.size === 1) { return this.cppType(defined(iterableFirst(nonNulls)), ctx, withIssues, forceNarrowString, false); @@ -957,19 +958,19 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: false, - inJsonNamespace: ctx.inJsonNamespace, + inJsonNamespace: ctx.inJsonNamespace }, withIssues, false, - false, - ), + false + ) ); } return [this._variantType, "<", typeList, ">"]; } - protected variantType (u: UnionType, inJsonNamespace: boolean): Sourcelike { + protected variantType(u: UnionType, inJsonNamespace: boolean): Sourcelike { const [maybeNull, nonNulls] = removeNullFromUnion(u, true); assert(nonNulls.size >= 2, "Variant not needed for less than two types."); const indirection = maybeNull !== null; @@ -978,10 +979,10 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: !indirection, needsOptionalIndirection: !indirection, - inJsonNamespace, + inJsonNamespace }, true, - false, + false ); if (!indirection) { return variant; @@ -990,25 +991,25 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { return [this.optionalType(u), "<", variant, ">"]; } - protected ourQualifier (inJsonNamespace: boolean): Sourcelike { + protected ourQualifier(inJsonNamespace: boolean): Sourcelike { return inJsonNamespace ? [arrayIntercalate("::", this._namespaceNames), "::"] : []; } - protected jsonQualifier (inJsonNamespace: boolean): Sourcelike { + protected jsonQualifier(inJsonNamespace: boolean): Sourcelike { return inJsonNamespace ? [] : "nlohmann::"; } - protected variantIndirection (type: Type, needIndirection: boolean, typeSrc: Sourcelike): Sourcelike { + protected variantIndirection(type: Type, needIndirection: boolean, typeSrc: Sourcelike): Sourcelike { if (!needIndirection) return typeSrc; return [this.optionalType(type), "<", typeSrc, ">"]; } - protected cppType ( + protected cppType( t: Type, ctx: TypeContext, withIssues: boolean, forceNarrowString: boolean, - isOptional: boolean, + isOptional: boolean ): Sourcelike { const inJsonNamespace = ctx.inJsonNamespace; if (isOptional && t instanceof UnionType) { @@ -1027,14 +1028,14 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { isOptional = false; return maybeAnnotated(withIssues, anyTypeIssueAnnotation, [ this.jsonQualifier(inJsonNamespace), - "json", + "json" ]); }, _nullType => { isOptional = false; return maybeAnnotated(withIssues, nullTypeIssueAnnotation, [ this.jsonQualifier(inJsonNamespace), - "json", + "json" ]); }, _boolType => "bool", @@ -1054,19 +1055,19 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: false, needsOptionalIndirection: true, - inJsonNamespace, + inJsonNamespace }, withIssues, forceNarrowString, - false, + false ), - ">", + ">" ], classType => this.variantIndirection( classType, ctx.needsForwardIndirection && this.isForwardDeclaredType(classType) && !isOptional, - [this.ourQualifier(inJsonNamespace), this.nameForNamedType(classType)], + [this.ourQualifier(inJsonNamespace), this.nameForNamedType(classType)] ), mapType => { let keyType = this._stringType.getType(); @@ -1083,13 +1084,13 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: false, needsOptionalIndirection: true, - inJsonNamespace, + inJsonNamespace }, withIssues, forceNarrowString, - false, + false ), - ">", + ">" ]; }, enumType => [this.ourQualifier(inJsonNamespace), this.nameForNamedType(enumType)], @@ -1102,16 +1103,16 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: false, needsOptionalIndirection: false, - inJsonNamespace, + inJsonNamespace }, withIssues, forceNarrowString, - false, + false ); } else { return [this.ourQualifier(inJsonNamespace), this.nameForNamedType(unionType)]; } - }, + } ); if (!isOptional) return typeSource; return [this.optionalType(t), "<", typeSource, ">"]; @@ -1121,7 +1122,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { * similar to cppType, it practically gathers all the generated types within * 't'. It also records, whether a given sub-type is part of a variant or not. */ - protected generatedTypes (isClassMember: boolean, theType: Type): TypeRecord[] { + protected generatedTypes(isClassMember: boolean, theType: Type): TypeRecord[] { const result: TypeRecord[] = []; const recur = (forceInclude: boolean, isVariant: boolean, l: number, t: Type) => { if (t instanceof ArrayType) { @@ -1132,7 +1133,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { type: t, level: l, variant: isVariant, - forceInclude, + forceInclude }); } else if (t instanceof MapType) { recur(true, isVariant, l + 1, t.values); @@ -1142,7 +1143,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { type: t, level: l, variant: isVariant, - forceInclude: false, + forceInclude: false }); } else if (t instanceof UnionType) { /** @@ -1166,7 +1167,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { type: t, level: l, variant: true, - forceInclude, + forceInclude }); /** intentional "fall-through", add all subtypes as well - but forced include */ } @@ -1184,15 +1185,15 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { return result; } - protected constraintMember (jsonName: string): string { + protected constraintMember(jsonName: string): string { return this._memberNameStyle(`${jsonName}Constraint`); } - protected emitMember (cppType: Sourcelike, name: Sourcelike): void { + protected emitMember(cppType: Sourcelike, name: Sourcelike): void { this.emitLine(cppType, " ", name, ";"); } - protected emitClassMembers (c: ClassType, constraints: Map | undefined): void { + protected emitClassMembers(c: ClassType, constraints: Map | undefined): void { if (this._options.codeFormat) { this.emitLine("private:"); @@ -1203,13 +1204,13 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false, + inJsonNamespace: false }, true, false, - property.isOptional, + property.isOptional ), - name, + name ); if (constraints?.has(jsonName)) { /** FIXME!!! NameStyle will/can collide with other Names */ @@ -1231,28 +1232,28 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false, + inJsonNamespace: false }, true, false, - property.isOptional, + property.isOptional ), - name, + name ); } else { const [getterName, mutableGetterName, setterName] = defined( - this._gettersAndSettersForPropertyName.get(name), + this._gettersAndSettersForPropertyName.get(name) ); const rendered = this.cppType( property.type, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false, + inJsonNamespace: false }, true, false, - property.isOptional, + property.isOptional ); /** @@ -1262,8 +1263,8 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { */ const checkConst = this.lookupGlobalName(GlobalNames.CheckConstraint); if ( - property.type instanceof UnionType && property.type.findMember("null") !== undefined || - property.isOptional && property.type.kind !== "null" && property.type.kind !== "any" + (property.type instanceof UnionType && property.type.findMember("null") !== undefined) || + (property.isOptional && property.type.kind !== "null" && property.type.kind !== "any") ) { this.emitLine(rendered, " ", getterName, "() const { return ", name, "; }"); if (constraints?.has(jsonName)) { @@ -1280,7 +1281,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.constraintMember(jsonName), ", *value); this->", name, - " = value; }", + " = value; }" ); } else { this.emitLine("void ", setterName, "(", rendered, " value) { this->", name, " = value; }"); @@ -1302,7 +1303,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.constraintMember(jsonName), ", value); this->", name, - " = value; }", + " = value; }" ); } else { this.emitLine( @@ -1312,7 +1313,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.withConst(rendered), " & value) { this->", name, - " = value; }", + " = value; }" ); } } @@ -1322,7 +1323,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { }); } - protected generateClassConstraints (c: ClassType): Map | undefined { + protected generateClassConstraints(c: ClassType): Map | undefined { const res: Map = new Map(); this.forEachClassProperty(c, "none", (_name, jsonName, property) => { const constraints = constraintsForType(property.type); @@ -1335,11 +1336,11 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false, + inJsonNamespace: false }, true, false, - property.isOptional, + property.isOptional ); res.set(jsonName, [ @@ -1360,19 +1361,19 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { pattern === undefined ? this._nulloptType : [ - this._stringType.getType(), - "(", - this._stringType.createStringLiteral([stringEscape(pattern)]), - ")", - ], - ")", + this._stringType.getType(), + "(", + this._stringType.createStringLiteral([stringEscape(pattern)]), + ")" + ], + ")" ]); }); return res.size === 0 ? undefined : res; } - protected emitClass (c: ClassType, className: Name): void { + protected emitClass(c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); this.emitBlock([this._options.codeFormat ? "class " : "struct ", className], true, () => { const constraints = this.generateClassConstraints(c); @@ -1404,7 +1405,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { }); } - protected emitTopLevelHeaders (t: Type, className: Name): void { + protected emitTopLevelHeaders(t: Type, className: Name): void { // Forward declarations for std::map (need to convert UTF16 <-> UTF8) if (t instanceof MapType && this._stringType !== this.NarrowString) { const ourQualifier = this.ourQualifier(true); @@ -1417,21 +1418,21 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { " & j, ", ourQualifier, className, - " & x);", + " & x);" ); this.emitLine("static void to_json(json & j, ", this.withConst([ourQualifier, className]), " & x);"); }); } } - protected emitClassHeaders (className: Name): void { + protected emitClassHeaders(className: Name): void { const ourQualifier = this.ourQualifier(false); this.emitLine("void from_json(", this.withConst("json"), " & j, ", ourQualifier, className, " & x);"); this.emitLine("void to_json(json & j, ", this.withConst([ourQualifier, className]), " & x);"); } - protected emitTopLevelFunction (t: Type, className: Name): void { + protected emitTopLevelFunction(t: Type, className: Name): void { // Function definitions for std::map (need to convert UTF16 <-> UTF8) if (t instanceof MapType && this._stringType !== this.NarrowString) { const ourQualifier = this.ourQualifier(true); @@ -1448,7 +1449,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { " & j, ", ourQualifier, className, - "& x)", + "& x)" ], false, () => { @@ -1457,22 +1458,22 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true, + inJsonNamespace: true }, false, true, - false, + false ); toType = this.cppType( t, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true, + inJsonNamespace: true }, false, false, - false, + false ); this.emitLine([ @@ -1480,11 +1481,11 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, [ "j.get<", cppType, - ">()", + ">()" ]), - ";", + ";" ]); - }, + } ); this.emitBlock( @@ -1494,7 +1495,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { className, ">::to_json(json & j, ", this.withConst([ourQualifier, className]), - " & x)", + " & x)" ], false, () => { @@ -1503,35 +1504,35 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true, + inJsonNamespace: true }, false, false, - false, + false ); toType = this.cppType( t, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true, + inJsonNamespace: true }, false, true, - false, + false ); this.emitLine([ "j = ", this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, "x"), - ";", + ";" ]); - }, + } ); } } - protected emitClassFunctions (c: ClassType, className: Name): void { + protected emitClassFunctions(c: ClassType, className: Name): void { const ourQualifier = this.ourQualifier(false); let cppType: Sourcelike; let toType: Sourcelike; @@ -1562,12 +1563,12 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { [ourQualifier], this._stringType.getType(), this.NarrowString.getType(), - [this._stringType.createStringLiteral([stringEscape(json)])], + [this._stringType.createStringLiteral([stringEscape(json)])] ), - ")", - ], + ")" + ] ), - ";", + ";" ); return; } @@ -1589,20 +1590,20 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: false, needsOptionalIndirection: false, - inJsonNamespace: false, + inJsonNamespace: false }, false, - true, + true ); toType = this.cppTypeInOptional( typeSet, { needsForwardIndirection: false, needsOptionalIndirection: false, - inJsonNamespace: false, + inJsonNamespace: false }, false, - false, + false ); this.emitLine( assignment.wrap( @@ -1621,14 +1622,14 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { [ourQualifier], this._stringType.getType(), this.NarrowString.getType(), - [this._stringType.createStringLiteral([stringEscape(json)])], + [this._stringType.createStringLiteral([stringEscape(json)])] ), - ")", - ], - ), - ], + ")" + ] + ) + ] ), - ";", + ";" ); return; } @@ -1639,22 +1640,22 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false, + inJsonNamespace: false }, false, true, - p.isOptional, + p.isOptional ); toType = this.cppType( propType, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false, + inJsonNamespace: false }, false, false, - p.isOptional, + p.isOptional ); this.emitLine( assignment.wrap( @@ -1665,17 +1666,17 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { [ourQualifier], this._stringType.getType(), this.NarrowString.getType(), - this._stringType.createStringLiteral([stringEscape(json)]), + this._stringType.createStringLiteral([stringEscape(json)]) ), ").get<", cppType, - ">()", - ]), + ">()" + ]) ), - ";", + ";" ); }); - }, + } ); this.ensureBlankLine(); @@ -1691,22 +1692,22 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false, + inJsonNamespace: false }, false, false, - p.isOptional, + p.isOptional ); toType = this.cppType( propType, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false, + inJsonNamespace: false }, false, true, - p.isOptional, + p.isOptional ); const [getterName, ,] = defined(this._gettersAndSettersForPropertyName.get(name)); let getter: Sourcelike[]; @@ -1722,33 +1723,33 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { [ourQualifier], this._stringType.getType(), this.NarrowString.getType(), - this._stringType.createStringLiteral([stringEscape(json)]), + this._stringType.createStringLiteral([stringEscape(json)]) ), "] = ", this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, ["x.", getter]), - ";", + ";" ]; if (p.isOptional && this._options.hideNullOptional) { this.emitBlock( [ "if (", this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, ["x.", getter]), - ")", + ")" ], false, () => { this.emitLine(assignment); - }, + } ); } else { this.emitLine(assignment); } }); - }, + } ); } - protected emitEnum (e: EnumType, enumName: Name): void { + protected emitEnum(e: EnumType, enumName: Name): void { const caseNames: Sourcelike[] = []; const enumValues = enumCaseValues(e, this.targetLanguage.name); @@ -1767,11 +1768,11 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.emitLine("enum class ", enumName, " : ", this._enumType, " { ", caseNames, " };"); } - protected emitUnionTypedefs (u: UnionType, unionName: Name): void { + protected emitUnionTypedefs(u: UnionType, unionName: Name): void { this.emitLine("using ", unionName, " = ", this.variantType(u, false), ";"); } - protected emitUnionHeaders (u: UnionType): void { + protected emitUnionHeaders(u: UnionType): void { // Forward declarations for boost::variant. If none of the Ts were defined by us (e.g. if we have // boost::variant) then we need to specialize nlohmann::adl_serializer for our // variant type. If at least one of the Ts is our type then we could get away with regular adl definitions, @@ -1784,10 +1785,10 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: false, needsOptionalIndirection: false, - inJsonNamespace: true, + inJsonNamespace: true }, false, - false, + false ); this.emitLine("template <>"); @@ -1797,7 +1798,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { }); } - protected emitUnionFunctions (u: UnionType): void { + protected emitUnionFunctions(u: UnionType): void { // Function definitions for boost::variant. const ourQualifier = this.ourQualifier(true) as string; @@ -1810,7 +1811,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { ["class", "is_object"], ["map", "is_object"], ["array", "is_array"], - ["enum", "is_string"], + ["enum", "is_string"] ]; const nonNulls = removeNullFromUnion(u, true)[1]; const variantType = this.cppTypeInOptional( @@ -1818,10 +1819,10 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: false, needsOptionalIndirection: false, - inJsonNamespace: true, + inJsonNamespace: true }, false, - false, + false ); this.emitBlock( @@ -1832,7 +1833,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.withConst("json"), " & j, ", variantType, - " & x)", + " & x)" ], false, () => { @@ -1847,38 +1848,38 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true, + inJsonNamespace: true }, false, true, - false, + false ); const toType = this.cppType( typeForKind, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true, + inJsonNamespace: true }, false, false, - false, + false ); this.emitLine( "x = ", this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, [ "j.get<", cppType, - ">()", + ">()" ]), - ";", + ";" ); }); onFirst = false; } - this.emitLine("else throw std::runtime_error(\"Could not deserialise!\");"); - }, + this.emitLine('else throw std::runtime_error("Could not deserialise!");'); + } ); this.ensureBlankLine(); @@ -1896,57 +1897,57 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true, + inJsonNamespace: true }, false, false, - false, + false ); const toType = this.cppType( t, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true, + inJsonNamespace: true }, false, true, - false, + false ); this.emitLine( "j = ", this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, [ this._options.boost ? "boost::get<" : "std::get<", cppType, - ">(x)", + ">(x)" ]), - ";", + ";" ); this.emitLine("break;"); }); i++; } - this.emitLine("default: throw std::runtime_error(\"Input JSON does not conform to schema!\");"); + this.emitLine('default: throw std::runtime_error("Input JSON does not conform to schema!");'); }); - }, + } ); } - protected emitEnumHeaders (enumName: Name): void { + protected emitEnumHeaders(enumName: Name): void { const ourQualifier = this.ourQualifier(false); this.emitLine("void from_json(", this.withConst("json"), " & j, ", ourQualifier, enumName, " & x);"); this.emitLine("void to_json(json & j, ", this.withConst([ourQualifier, enumName]), " & x);"); } - private isLargeEnum (e: EnumType) { + private isLargeEnum(e: EnumType) { // This is just an estimation. Someone might want to do some // benchmarks to find the optimum value here return e.cases.size > 15; } - protected emitEnumFunctions (e: EnumType, enumName: Name): void { + protected emitEnumFunctions(e: EnumType, enumName: Name): void { const ourQualifier = this.ourQualifier(false); this.emitBlock( @@ -1961,7 +1962,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { ", ", ourQualifier, enumName, - "> enumValues", + "> enumValues" ], true, () => { @@ -1972,17 +1973,17 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { [ourQualifier], this._stringType.getType(), this.NarrowString.getType(), - [this._stringType.createStringLiteral([stringEscape(jsonName)])], + [this._stringType.createStringLiteral([stringEscape(jsonName)])] ), ", ", ourQualifier, enumName, "::", name, - "},", + "}," ); }); - }, + } ); this.emitLine(`auto iter = enumValues.find(j.get<${this._stringType.getType()}>());`); @@ -2000,20 +2001,20 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { [ourQualifier], this._stringType.getType(), this.NarrowString.getType(), - [this._stringType.createStringLiteral([stringEscape(jsonName)])], + [this._stringType.createStringLiteral([stringEscape(jsonName)])] ), ") x = ", ourQualifier, enumName, "::", name, - ";", + ";" ); onFirst = false; }); - this.emitLine("else { throw std::runtime_error(\"Input JSON does not conform to schema!\"); }"); + this.emitLine('else { throw std::runtime_error("Input JSON does not conform to schema!"); }'); } - }, + } ); this.ensureBlankLine(); @@ -2034,20 +2035,20 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { [ourQualifier], this._stringType.getType(), this.NarrowString.getType(), - [this._stringType.createStringLiteral([stringEscape(jsonName)])], + [this._stringType.createStringLiteral([stringEscape(jsonName)])] ), - "; break;", + "; break;" ); }); this.emitLine( - `default: throw std::runtime_error("Unexpected value in enumeration \\"${enumName}\\": " + std::to_string(static_cast(x)));`, + `default: throw std::runtime_error("Unexpected value in enumeration \\"${enumName}\\": " + std::to_string(static_cast(x)));` ); }); - }, + } ); } - protected emitTopLevelTypedef (t: Type, name: Name): void { + protected emitTopLevelTypedef(t: Type, name: Name): void { this.emitLine( "using ", name, @@ -2057,17 +2058,17 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false, + inJsonNamespace: false }, true, false, - false, + false ), - ";", + ";" ); } - protected emitAllUnionFunctions (): void { + protected emitAllUnionFunctions(): void { this.forEachUniqueUnion( "leading-and-interposing", u => @@ -2077,17 +2078,17 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: false, needsOptionalIndirection: false, - inJsonNamespace: true, + inJsonNamespace: true }, false, - false, - ), + false + ) ), - (u: UnionType) => this.emitUnionFunctions(u), + (u: UnionType) => this.emitUnionFunctions(u) ); } - protected emitAllUnionHeaders (): void { + protected emitAllUnionHeaders(): void { this.forEachUniqueUnion( "interposing", u => @@ -2097,17 +2098,17 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: false, needsOptionalIndirection: false, - inJsonNamespace: true, + inJsonNamespace: true }, false, - false, - ), + false + ) ), - (u: UnionType) => this.emitUnionHeaders(u), + (u: UnionType) => this.emitUnionHeaders(u) ); } - protected emitOptionalHelpers (): void { + protected emitOptionalHelpers(): void { this.emitLine("#ifndef NLOHMANN_OPT_HELPER"); this.emitLine("#define NLOHMANN_OPT_HELPER"); @@ -2120,7 +2121,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { false, () => { this.emitLine("if (!opt) j = nullptr; else j = *opt;"); - }, + } ); this.ensureBlankLine(); @@ -2130,9 +2131,9 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { false, () => { this.emitLine( - `if (j.is_null()) return ${factory}(); else return ${factory}(j.get());`, + `if (j.is_null()) return ${factory}(); else return ${factory}(j.get());` ); - }, + } ); }); }; @@ -2144,7 +2145,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.emitLine("#endif"); } - protected emitDeclaration (decl: Declaration): void { + protected emitDeclaration(decl: Declaration): void { if (decl.kind === "forward") { if (this._options.codeFormat) { this.emitLine("class ", this.nameForNamedType(decl.type), ";"); @@ -2168,17 +2169,17 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } - protected emitGetterSetter (t: string, getterName: string, setterName: string, memberName: string): void { + protected emitGetterSetter(t: string, getterName: string, setterName: string, memberName: string): void { this.emitLine("void ", setterName, "(", t, " ", memberName, ") { this->", memberName, " = ", memberName, "; }"); this.emitLine("auto ", getterName, "() const { return ", memberName, "; }"); } - protected emitNumericCheckConstraints ( + protected emitNumericCheckConstraints( checkConst: string, classConstraint: string, getterMinValue: string, getterMaxValue: string, - cppType: string, + cppType: string ): void { this.emitBlock( [ @@ -2190,7 +2191,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.withConst(classConstraint), " & c, ", cppType, - " value)", + " value)" ], false, () => { @@ -2213,9 +2214,9 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this._stringType.wrapToString(["*c.", getterMinValue, "()"]), " + ", this._stringType.createStringLiteral([")"]), - ");", + ");" ); - }, + } ); this.ensureBlankLine(); @@ -2238,17 +2239,17 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this._stringType.wrapToString(["*c.", getterMaxValue, "()"]), " + ", this._stringType.createStringLiteral([")"]), - ");", + ");" ); - }, + } ); this.ensureBlankLine(); - }, + } ); this.ensureBlankLine(); } - protected emitConstraintClasses (): void { + protected emitConstraintClasses(): void { const ourQualifier = this.ourQualifier(false) as string; const getterMinIntValue = this.lookupMemberName(MemberNames.GetMinIntValue); @@ -2291,7 +2292,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { withDefault(member.cppConstType, member.cppType), this.lookupMemberName(member.getter), this.lookupMemberName(member.setter), - this.lookupMemberName(member.name), + this.lookupMemberName(member.name) ); } }); @@ -2309,9 +2310,9 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { [ourQualifier], this._stringType.getType(), this.NarrowString.getType(), - ["msg"], + ["msg"] ), - ") {}", + ") {}" ); }); this.ensureBlankLine(); @@ -2321,7 +2322,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { GlobalNames.ValueTooHighException, GlobalNames.ValueTooShortException, GlobalNames.ValueTooLongException, - GlobalNames.InvalidPatternException, + GlobalNames.InvalidPatternException ]; for (const ex of exceptions) { @@ -2340,7 +2341,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { classConstraint, getterMinDoubleValue, getterMaxDoubleValue, - "double", + "double" ); this.emitBlock( @@ -2353,7 +2354,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.withConst(classConstraint), " & c, ", this._stringType.getConstType(), - " value)", + " value)" ], false, () => { @@ -2365,7 +2366,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this._nulloptType, " && value.length() < *c.", getterMinLength, - "())", + "())" ], false, () => { @@ -2384,9 +2385,9 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this._stringType.wrapToString(["*c.", getterMinLength, "()"]), " + ", this._stringType.createStringLiteral([")"]), - ");", + ");" ); - }, + } ); this.ensureBlankLine(); @@ -2398,7 +2399,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this._nulloptType, " && value.length() > *c.", getterMaxLength, - "())", + "())" ], false, () => { @@ -2417,9 +2418,9 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this._stringType.wrapToString(["*c.", getterMaxLength, "()"]), " + ", this._stringType.createStringLiteral([")"]), - ");", + ");" ); - }, + } ); this.ensureBlankLine(); @@ -2430,7 +2431,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this._stringType.getRegex(), "( *c.", getterPattern, - "() ));", + "() ));" ); this.emitBlock(["if (result.empty())"], false, () => { this.emitLine( @@ -2446,16 +2447,16 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { getterPattern, "() + ", this._stringType.createStringLiteral([")"]), - ");", + ");" ); }); }); this.ensureBlankLine(); - }, + } ); } - protected emitHelperFunctions (): void { + protected emitHelperFunctions(): void { this._stringType.emitHelperFunctions(); if ( @@ -2493,7 +2494,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.emitLine("return j.at(property).get();"); }); this.emitLine("return json();"); - }, + } ); this.ensureBlankLine(); @@ -2503,7 +2504,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { false, () => { this.emitLine("return get_untyped(j, property.data());"); - }, + } ); this.emitLine("#endif"); @@ -2526,7 +2527,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.withConst("json"), " & j, ", this.withConst("char"), - " * property)", + " * property)" ], false, () => { @@ -2535,7 +2536,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.emitLine("return j.at(property).get<", optionalType, ">();"); }); this.emitLine("return ", optionalType, "();"); - }, + } ); this.ensureBlankLine(); @@ -2547,12 +2548,12 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { optionalType, ` get_${label}_optional(`, this.withConst("json"), - " & j, std::string property)", + " & j, std::string property)" ], false, () => { this.emitLine(`return get_${label}_optional(j, property.data());`); - }, + } ); }; @@ -2565,7 +2566,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } - protected emitExtraIncludes (): void { + protected emitExtraIncludes(): void { this.ensureBlankLine(); if (this._options.codeFormat) { @@ -2592,7 +2593,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.ensureBlankLine(); } - protected emitHelper (): void { + protected emitHelper(): void { this.startFile("helper.hpp", false); this.emitExtraIncludes(); @@ -2613,7 +2614,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.finishFile(); } - protected emitTypes (): void { + protected emitTypes(): void { if (!this._options.justTypes) { this.emitLine("using nlohmann::json;"); this.ensureBlankLine(); @@ -2625,24 +2626,24 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.forEachTopLevel( "leading", (t: Type, name: Name) => this.emitTopLevelTypedef(t, name), - t => this.namedTypeToNameForTopLevel(t) === undefined, + t => this.namedTypeToNameForTopLevel(t) === undefined ); } - protected gatherUserNamespaceForwardDecls (): Sourcelike[] { + protected gatherUserNamespaceForwardDecls(): Sourcelike[] { return this.gatherSource(() => { this.forEachObject("leading-and-interposing", (_: any, className: Name) => - this.emitClassHeaders(className), + this.emitClassHeaders(className) ); this.forEachEnum("leading-and-interposing", (_: any, enumName: Name) => this.emitEnumHeaders(enumName)); }); } - protected gatherNlohmannNamespaceForwardDecls (): Sourcelike[] { + protected gatherNlohmannNamespaceForwardDecls(): Sourcelike[] { return this.gatherSource(() => { this.forEachTopLevel("leading-and-interposing", (t: Type, className: Name) => - this.emitTopLevelHeaders(t, className), + this.emitTopLevelHeaders(t, className) ); this.ensureBlankLine(); @@ -2651,21 +2652,21 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { }); } - protected emitUserNamespaceImpls (): void { + protected emitUserNamespaceImpls(): void { this.forEachObject("leading-and-interposing", (c: ClassType, className: Name) => - this.emitClassFunctions(c, className), + this.emitClassFunctions(c, className) ); this.forEachEnum("leading-and-interposing", (e: EnumType, enumName: Name) => - this.emitEnumFunctions(e, enumName), + this.emitEnumFunctions(e, enumName) ); } - protected emitNlohmannNamespaceImpls (): void { + protected emitNlohmannNamespaceImpls(): void { this.forEachTopLevel( "leading-and-interposing", (t: Type, name: Name) => this.emitTopLevelFunction(t, name), - t => this.namedTypeToNameForTopLevel(t) === undefined, + t => this.namedTypeToNameForTopLevel(t) === undefined ); this.ensureBlankLine(); @@ -2673,7 +2674,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.emitAllUnionFunctions(); } - protected emitGenerators (): void { + protected emitGenerators(): void { if (this._options.justTypes) { let didEmit = false; const gathered = this.gatherSource(() => @@ -2681,9 +2682,9 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { didEmit = this.forEachTopLevel( "none", (t: Type, name: Name) => this.emitTopLevelTypedef(t, name), - t => this.namedTypeToNameForTopLevel(t) === undefined, + t => this.namedTypeToNameForTopLevel(t) === undefined ); - }), + }) ); if (didEmit) { this.emitGatheredSource(gathered); @@ -2720,7 +2721,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } - protected emitSingleSourceStructure (proposedFilename: string): void { + protected emitSingleSourceStructure(proposedFilename: string): void { this.startFile(proposedFilename); this._generatedFiles.add(proposedFilename); @@ -2744,7 +2745,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.finishFile(); } - protected updateIncludes (isClassMember: boolean, includes: IncludeMap, propertyType: Type, _defName: string): void { + protected updateIncludes(isClassMember: boolean, includes: IncludeMap, propertyType: Type, _defName: string): void { const propTypes = this.generatedTypes(isClassMember, propertyType); for (const t of propTypes) { @@ -2797,7 +2798,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } - protected emitIncludes (c: ClassType | UnionType | EnumType, defName: string): void { + protected emitIncludes(c: ClassType | UnionType | EnumType, defName: string): void { /** * Need to generate "includes", in terms 'c' has members, which * are defined by others @@ -2864,7 +2865,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } - protected emitDefinition (d: ClassType | EnumType | UnionType, defName: Name): void { + protected emitDefinition(d: ClassType | EnumType | UnionType, defName: Name): void { const name = `${this.sourcelikeToString(defName)}.hpp`; this.startFile(name, true); this._generatedFiles.add(name); @@ -2888,7 +2889,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.finishFile(); } - protected emitMultiSourceStructure (proposedFilename: string): void { + protected emitMultiSourceStructure(proposedFilename: string): void { if (!this._options.justTypes && this.haveNamedTypes) { this.emitHelper(); @@ -2914,7 +2915,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { }, (u, n) => { this.emitDefinition(u, n); - }, + } ); /** @@ -2936,7 +2937,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.forEachTopLevel( "leading", (t: Type, name: Name) => this.emitTopLevelTypedef(t, name), - t => this.namedTypeToNameForTopLevel(t) === undefined, + t => this.namedTypeToNameForTopLevel(t) === undefined ); }); @@ -2944,7 +2945,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } - protected emitSourceStructure (proposedFilename: string): void { + protected emitSourceStructure(proposedFilename: string): void { this._generatedFiles.clear(); /** Gather all the unique/custom types used by the schema */ @@ -2959,13 +2960,13 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: false, needsOptionalIndirection: false, - inJsonNamespace: false, + inJsonNamespace: false }, true, false, - false, - ), - ), + false + ) + ) ]); } @@ -2982,17 +2983,17 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } - protected isConversionRequired (t: Type) { + protected isConversionRequired(t: Type) { const originalType = this.cppType( t, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true, + inJsonNamespace: true }, false, false, - false, + false ); const newType = this.cppType( @@ -3000,18 +3001,18 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true, + inJsonNamespace: true }, false, true, - false, + false ); return originalType !== newType; } - public NarrowString = new class extends BaseString implements StringType { - constructor () { + public NarrowString = new (class extends BaseString implements StringType { + constructor() { super( "std::string", "const std::string & ", @@ -3020,26 +3021,26 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { "", new WrappingCode(["std::to_string("], [")"]), "", - "", + "" ); } - public wrapEncodingChange ( + public wrapEncodingChange( _qualifier: Sourcelike[], _fromType: Sourcelike, _toType: Sourcelike, - inner: Sourcelike, + inner: Sourcelike ): Sourcelike { return inner; } - public emitHelperFunctions (): void { + public emitHelperFunctions(): void { return; } - }(); + })(); - public WideString = new class extends BaseString implements StringType { - constructor (public superThis: CPlusPlusRenderer) { + public WideString = new (class extends BaseString implements StringType { + constructor(public superThis: CPlusPlusRenderer) { super( "std::wstring", "const std::wstring & ", @@ -3048,15 +3049,15 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { "L", new WrappingCode(["std::to_wstring("], [")"]), "Utf16_Utf8", - "convert", + "convert" ); } - public wrapEncodingChange ( + public wrapEncodingChange( qualifier: Sourcelike[], fromType: Sourcelike, toType: Sourcelike, - inner: Sourcelike, + inner: Sourcelike ): Sourcelike { if (this.superThis.sourcelikeToString(fromType) === this.superThis.sourcelikeToString(toType)) { return inner; @@ -3072,11 +3073,11 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this._encodingFunction, "(", inner, - ")", + ")" ]; } - public emitHelperFunctions (): void { + public emitHelperFunctions(): void { this.superThis.emitLine("template"); this.superThis.emitLine("struct tag {};"); this.superThis.ensureBlankLine(); @@ -3090,9 +3091,9 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { false, () => { this.superThis.emitLine( - "if (ptr == nullptr) return std::unique_ptr(); else return std::unique_ptr(new TT(Utf16_Utf8::convert(*ptr)));", + "if (ptr == nullptr) return std::unique_ptr(); else return std::unique_ptr(new TT(Utf16_Utf8::convert(*ptr)));" ); - }, + } ); this.superThis.ensureBlankLine(); @@ -3108,7 +3109,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.superThis.emitLine("it++;"); }); this.superThis.emitLine("return newVector;"); - }, + } ); this.superThis.ensureBlankLine(); @@ -3121,12 +3122,12 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.superThis.emitLine("auto newMap = std::map();"); this.superThis.emitBlock(["while (it != m.end())"], false, () => { this.superThis.emitLine( - "newMap.insert(std::pair(Utf16_Utf8::convert(it->first), Utf16_Utf8::convert(it->second)));", + "newMap.insert(std::pair(Utf16_Utf8::convert(it->first), Utf16_Utf8::convert(it->second)));" ); this.superThis.emitLine("it++;"); }); this.superThis.emitLine("return newMap;"); - }, + } ); this.superThis.ensureBlankLine(); @@ -3141,9 +3142,9 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { false, () => { this.superThis.emitLine( - "return std::wstring_convert, wchar_t>{}.from_bytes(str.data());", + "return std::wstring_convert, wchar_t>{}.from_bytes(str.data());" ); - }, + } ); this.superThis.ensureBlankLine(); @@ -3152,9 +3153,9 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { false, () => { this.superThis.emitLine( - "return std::wstring_convert, wchar_t>{}.to_bytes(str.data());", + "return std::wstring_convert, wchar_t>{}.to_bytes(str.data());" ); - }, + } ); this.superThis.ensureBlankLine(); @@ -3172,10 +3173,10 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.superThis.emitLine( "return ", this.superThis.ourQualifier(false), - "Utf16_Utf8::convert(s.str()); ", + "Utf16_Utf8::convert(s.str()); " ); }); this.superThis.ensureBlankLine(); } - }(this); + })(this); } diff --git a/packages/quicktype-core/src/language/CSharp.ts b/packages/quicktype-core/src/language/CSharp.ts index 9ffc68669..e9ee7be51 100644 --- a/packages/quicktype-core/src/language/CSharp.ts +++ b/packages/quicktype-core/src/language/CSharp.ts @@ -5,41 +5,32 @@ import { type ClassProperty, type TransformedStringTypeKind, type PrimitiveStringTypeKind, - type PrimitiveType, -} from "../Type"; -import { - EnumType, - UnionType, - ClassType, - ArrayType, + type PrimitiveType } from "../Type"; +import { EnumType, UnionType, ClassType, ArrayType } from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion, directlyReachableSingleNamedType } from "../TypeUtils"; -import { type Sourcelike} from "../Source"; +import { type Sourcelike } from "../Source"; import { maybeAnnotated, modifySource } from "../Source"; -import { - type WordInName, -} from "../support/Strings"; +import { type WordInName } from "../support/Strings"; import { utf16LegalizeCharacters, utf16StringEscape, splitIntoWords, combineWords, firstUpperWordStyle, - camelCase, + camelCase } from "../support/Strings"; import { defined, assert, panic, assertNever } from "../support/Support"; -import { type Name, type Namer} from "../Naming"; +import { type Name, type Namer } from "../Naming"; import { DependencyName, funPrefixNamer, SimpleName } from "../Naming"; -import { type ForbiddenWordsInfo} from "../ConvenienceRenderer"; +import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; import { ConvenienceRenderer, inferredNameOrder } from "../ConvenienceRenderer"; import { TargetLanguage } from "../TargetLanguage"; -import { type Option, type OptionValues} from "../RendererOptions"; +import { type Option, type OptionValues } from "../RendererOptions"; import { StringOption, EnumOption, BooleanOption, getOptionValues } from "../RendererOptions"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; import { type StringTypeMapping } from "../TypeBuilder"; -import { - type Transformer, - type Transformation} from "../Transformers"; +import { type Transformer, type Transformation } from "../Transformers"; import { followTargetType, transformationForType, @@ -56,35 +47,36 @@ import { ArrayDecodingTransformer, ArrayEncodingTransformer, MinMaxLengthCheckTransformer, - MinMaxValueTransformer, + MinMaxValueTransformer } from "../Transformers"; import { type RenderContext } from "../Renderer"; import { minMaxLengthForType, minMaxValueForType } from "../attributes/Constraints"; import unicode from "unicode-properties"; export enum Framework { - Newtonsoft, - SystemTextJson + Newtonsoft = "Newtonsoft", + SystemTextJson = "SystemTextJson" } export type Version = 5 | 6; export interface OutputFeatures { - attributes: boolean; helpers: boolean; + attributes: boolean; + helpers: boolean; } export enum AccessModifier { - None, - Public, - Internal + None = "None", + Public = "Public", + Internal = "Internal" } export type CSharpTypeForAny = "object" | "dynamic"; -function noFollow (t: Type): Type { +function noFollow(t: Type): Type { return t; } -function needTransformerForType (t: Type): "automatic" | "manual" | "nullable" | "none" { +function needTransformerForType(t: Type): "automatic" | "manual" | "nullable" | "none" { if (t instanceof UnionType) { const maybeNullable = nullableFromUnion(t); if (maybeNullable === null) return "automatic"; @@ -108,7 +100,7 @@ function needTransformerForType (t: Type): "automatic" | "manual" | "nullable" | return "none"; } -function alwaysApplyTransformation (xf: Transformation): boolean { +function alwaysApplyTransformation(xf: Transformation): boolean { const t = xf.targetType; if (t instanceof EnumType) return true; if (t instanceof UnionType) return nullableFromUnion(t) === null; @@ -118,7 +110,7 @@ function alwaysApplyTransformation (xf: Transformation): boolean { /** * The C# type for a given transformed string type. */ -function csTypeForTransformedStringType (t: PrimitiveType): Sourcelike { +function csTypeForTransformedStringType(t: PrimitiveType): Sourcelike { switch (t.kind) { case "date-time": return "DateTimeOffset"; @@ -137,23 +129,23 @@ export const cSharpOptions = { "Serialization framework", [ ["NewtonSoft", Framework.Newtonsoft], - ["SystemTextJson", Framework.SystemTextJson], + ["SystemTextJson", Framework.SystemTextJson] ], - "NewtonSoft", + "NewtonSoft" ), useList: new EnumOption("array-type", "Use T[] or List", [ ["array", false], - ["list", true], + ["list", true] ]), dense: new EnumOption( "density", "Property density", [ ["normal", false], - ["dense", true], + ["dense", true] ], "normal", - "secondary", + "secondary" ), // FIXME: Do this via a configurable named eventually. namespace: new StringOption("namespace", "Generated namespace", "NAME", "QuickType"), @@ -162,58 +154,58 @@ export const cSharpOptions = { "C# version", [ ["5", 5], - ["6", 6], + ["6", 6] ], "6", - "secondary", + "secondary" ), virtual: new BooleanOption("virtual", "Generate virtual properties", false), typeForAny: new EnumOption( "any-type", - "Type to use for \"any\"", + 'Type to use for "any"', [ ["object", "object"], - ["dynamic", "dynamic"], + ["dynamic", "dynamic"] ], "object", - "secondary", + "secondary" ), useDecimal: new EnumOption( "number-type", "Type to use for numbers", [ ["double", false], - ["decimal", true], + ["decimal", true] ], "double", - "secondary", + "secondary" ), features: new EnumOption("features", "Output features", [ ["complete", { namespaces: true, helpers: true, attributes: true }], ["attributes-only", { namespaces: true, helpers: false, attributes: true }], ["just-types-and-namespace", { namespaces: true, helpers: false, attributes: false }], - ["just-types", { namespaces: true, helpers: false, attributes: false }], + ["just-types", { namespaces: true, helpers: false, attributes: false }] ]), baseclass: new EnumOption( "base-class", "Base class", [ ["EntityData", "EntityData"], - ["Object", undefined], + ["Object", undefined] ], "Object", - "secondary", + "secondary" ), checkRequired: new BooleanOption("check-required", "Fail if required properties are missing", false), - keepPropertyName: new BooleanOption("keep-property-name", "Keep original field name generate", false), + keepPropertyName: new BooleanOption("keep-property-name", "Keep original field name generate", false) }; export class CSharpTargetLanguage extends TargetLanguage { - constructor () { + constructor() { super("C#", ["cs", "csharp"], "cs"); } - protected getOptions (): Array> { + protected getOptions(): Array> { return [ cSharpOptions.framework, cSharpOptions.namespace, @@ -226,11 +218,11 @@ export class CSharpTargetLanguage extends TargetLanguage { cSharpOptions.features, cSharpOptions.baseclass, cSharpOptions.checkRequired, - cSharpOptions.keepPropertyName, + cSharpOptions.keepPropertyName ]; } - get stringTypeMapping (): StringTypeMapping { + get stringTypeMapping(): StringTypeMapping { const mapping: Map = new Map(); mapping.set("date", "date-time"); mapping.set("time", "date-time"); @@ -242,22 +234,22 @@ export class CSharpTargetLanguage extends TargetLanguage { return mapping; } - get supportsUnionsWithBothNumberTypes (): boolean { + get supportsUnionsWithBothNumberTypes(): boolean { return true; } - get supportsOptionalClassProperties (): boolean { + get supportsOptionalClassProperties(): boolean { return true; } - needsTransformerForType (t: Type): boolean { + needsTransformerForType(t: Type): boolean { const need = needTransformerForType(t); return need !== "none" && need !== "nullable"; } - protected makeRenderer ( + protected makeRenderer( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any, }, + untypedOptionValues: { [name: string]: any } ): ConvenienceRenderer { const options = getOptionValues(cSharpOptions, untypedOptionValues); @@ -266,13 +258,13 @@ export class CSharpTargetLanguage extends TargetLanguage { return new NewtonsoftCSharpRenderer( this, renderContext, - getOptionValues(newtonsoftCSharpOptions, untypedOptionValues), + getOptionValues(newtonsoftCSharpOptions, untypedOptionValues) ); case Framework.SystemTextJson: return new SystemTextJsonCSharpRenderer( this, renderContext, - getOptionValues(systemTextJsonCSharpOptions, untypedOptionValues), + getOptionValues(systemTextJsonCSharpOptions, untypedOptionValues) ); default: return assertNever(options.framework); @@ -288,7 +280,7 @@ const denseJsonPropertyName = "J"; const denseRequiredEnumName = "R"; const denseNullValueHandlingEnumName = "N"; -function isStartCharacter (utf16Unit: number): boolean { +function isStartCharacter(utf16Unit: number): boolean { if (unicode.isAlphabetic(utf16Unit)) { return true; } @@ -296,7 +288,7 @@ function isStartCharacter (utf16Unit: number): boolean { return utf16Unit === 0x5f; // underscore } -function isPartCharacter (utf16Unit: number): boolean { +function isPartCharacter(utf16Unit: number): boolean { const category: string = unicode.getCategory(utf16Unit); if (["Nd", "Pc", "Mn", "Mc"].includes(category)) { return true; @@ -307,7 +299,7 @@ function isPartCharacter (utf16Unit: number): boolean { const legalizeName = utf16LegalizeCharacters(isPartCharacter); -function csNameStyle (original: string): string { +function csNameStyle(original: string): string { const words = splitIntoWords(original); return combineWords( words, @@ -317,11 +309,11 @@ function csNameStyle (original: string): string { firstUpperWordStyle, firstUpperWordStyle, "", - isStartCharacter, + isStartCharacter ); } -function csNameStyleKeep (original: string): string { +function csNameStyleKeep(original: string): string { const keywords = [ "abstract", "as", @@ -399,14 +391,14 @@ function csNameStyleKeep (original: string): string { "virtual", "void", "volatile", - "while", + "while" ]; const words: WordInName[] = [ { word: original, - isAcronym: false, - }, + isAcronym: false + } ]; const result = combineWords( @@ -417,13 +409,13 @@ function csNameStyleKeep (original: string): string { x => x, x => x, "", - isStartCharacter, + isStartCharacter ); return keywords.includes(result) ? "@" + result : result; } -function isValueType (t: Type): boolean { +function isValueType(t: Type): boolean { if (t instanceof UnionType) { return nullableFromUnion(t) === null; } @@ -432,19 +424,19 @@ function isValueType (t: Type): boolean { } export class CSharpRenderer extends ConvenienceRenderer { - constructor ( + constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _csOptions: OptionValues, + private readonly _csOptions: OptionValues ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace (): string[] { + protected forbiddenNamesForGlobalNamespace(): string[] { return ["QuickType", "Type", "System", "Console", "Exception", "DateTimeOffset", "Guid", "Uri"]; } - protected forbiddenForObjectProperties (_: ClassType, classNamed: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties(_: ClassType, classNamed: Name): ForbiddenWordsInfo { return { names: [ classNamed, @@ -454,54 +446,54 @@ export class CSharpRenderer extends ConvenienceRenderer { "Equals", "GetType", "MemberwiseClone", - "ReferenceEquals", + "ReferenceEquals" ], - includeGlobalForbidden: false, + includeGlobalForbidden: false }; } - protected forbiddenForUnionMembers (_: UnionType, unionNamed: Name): ForbiddenWordsInfo { + protected forbiddenForUnionMembers(_: UnionType, unionNamed: Name): ForbiddenWordsInfo { return { names: [unionNamed], includeGlobalForbidden: true }; } - protected makeNamedTypeNamer (): Namer { + protected makeNamedTypeNamer(): Namer { return namingFunction; } - protected namerForObjectProperty (): Namer { + protected namerForObjectProperty(): Namer { return this._csOptions.keepPropertyName ? namingFunctionKeep : namingFunction; } - protected makeUnionMemberNamer (): Namer { + protected makeUnionMemberNamer(): Namer { return namingFunction; } - protected makeEnumCaseNamer (): Namer { + protected makeEnumCaseNamer(): Namer { return namingFunction; } - protected unionNeedsName (u: UnionType): boolean { + protected unionNeedsName(u: UnionType): boolean { return nullableFromUnion(u) === null; } - protected namedTypeToNameForTopLevel (type: Type): Type | undefined { + protected namedTypeToNameForTopLevel(type: Type): Type | undefined { // If the top-level type doesn't contain any classes or unions // we have to define a class just for the `FromJson` method, in // emitFromJsonForTopLevel. return directlyReachableSingleNamedType(type); } - protected emitBlock (f: () => void, semicolon = false): void { + protected emitBlock(f: () => void, semicolon = false): void { this.emitLine("{"); this.indent(f); this.emitLine("}", semicolon ? ";" : ""); } - protected get doubleType (): string { + protected get doubleType(): string { return this._csOptions.useDecimal ? "decimal" : "double"; } - protected csType (t: Type, follow: (t: Type) => Type = followTargetType, withIssues = false): Sourcelike { + protected csType(t: Type, follow: (t: Type) => Type = followTargetType, withIssues = false): Sourcelike { const actualType = follow(t); return matchType( actualType, @@ -527,11 +519,11 @@ export class CSharpRenderer extends ConvenienceRenderer { if (nullable !== null) return this.nullableCSType(nullable, noFollow); return this.nameForNamedType(unionType); }, - transformedStringType => csTypeForTransformedStringType(transformedStringType), + transformedStringType => csTypeForTransformedStringType(transformedStringType) ); } - protected nullableCSType (t: Type, follow: (t: Type) => Type = followTargetType, withIssues = false): Sourcelike { + protected nullableCSType(t: Type, follow: (t: Type) => Type = followTargetType, withIssues = false): Sourcelike { t = followTargetType(t); const csType = this.csType(t, follow, withIssues); if (isValueType(t)) { @@ -541,17 +533,17 @@ export class CSharpRenderer extends ConvenienceRenderer { } } - protected baseclassForType (_t: Type): Sourcelike | undefined { + protected baseclassForType(_t: Type): Sourcelike | undefined { return undefined; } - protected emitType ( + protected emitType( description: string[] | undefined, accessModifier: AccessModifier, declaration: Sourcelike, name: Sourcelike, baseclass: Sourcelike | undefined, - emitter: () => void, + emitter: () => void ): void { switch (accessModifier) { case AccessModifier.Public: @@ -574,16 +566,16 @@ export class CSharpRenderer extends ConvenienceRenderer { this.emitBlock(emitter); } - protected attributesForProperty ( + protected attributesForProperty( _property: ClassProperty, _name: Name, _c: ClassType, - _jsonName: string, + _jsonName: string ): Sourcelike[] | undefined { return undefined; } - protected propertyDefinition (property: ClassProperty, name: Name, _c: ClassType, _jsonName: string): Sourcelike { + protected propertyDefinition(property: ClassProperty, name: Name, _c: ClassType, _jsonName: string): Sourcelike { const t = property.type; const csType = property.isOptional ? this.nullableCSType(t, followTargetType, true) @@ -596,7 +588,7 @@ export class CSharpRenderer extends ConvenienceRenderer { return [...propertyArray, csType, " ", name, " { get; set; }"]; } - protected emitDescriptionBlock (lines: Sourcelike[]): void { + protected emitDescriptionBlock(lines: Sourcelike[]): void { const start = "/// "; if (this._csOptions.dense) { this.emitLine(start, lines.join("; "), ""); @@ -605,11 +597,11 @@ export class CSharpRenderer extends ConvenienceRenderer { } } - protected blankLinesBetweenAttributes (): boolean { + protected blankLinesBetweenAttributes(): boolean { return false; } - private emitClassDefinition (c: ClassType, className: Name): void { + private emitClassDefinition(c: ClassType, className: Name): void { this.emitType( this.descriptionForType(c), AccessModifier.Public, @@ -629,7 +621,7 @@ export class CSharpRenderer extends ConvenienceRenderer { if (attributes === undefined) { if ( // Descriptions should be preceded by an empty line - !isFirstProperty && description !== undefined || + (!isFirstProperty && description !== undefined) || // If the previous property has a description, leave an empty line previousDescription !== undefined ) { @@ -656,11 +648,11 @@ export class CSharpRenderer extends ConvenienceRenderer { if (columns.length > 0) { this.emitTable(columns); } - }, + } ); } - private emitUnionDefinition (u: UnionType, unionName: Name): void { + private emitUnionDefinition(u: UnionType, unionName: Name): void { const nonNulls = removeNullFromUnion(u, true)[1]; this.emitType( this.descriptionForType(u), @@ -676,23 +668,23 @@ export class CSharpRenderer extends ConvenienceRenderer { this.ensureBlankLine(); const nullTests: Sourcelike[] = Array.from(nonNulls).map(t => [ this.nameForUnionMember(u, t), - " == null", + " == null" ]); this.ensureBlankLine(); this.forEachUnionMember(u, nonNulls, "none", null, (fieldName, t) => { const csType = this.csType(t); this.emitExpressionMember( ["public static implicit operator ", unionName, "(", csType, " ", fieldName, ")"], - ["new ", unionName, " { ", fieldName, " = ", fieldName, " }"], + ["new ", unionName, " { ", fieldName, " = ", fieldName, " }"] ); }); if (u.findMember("null") === undefined) return; this.emitExpressionMember("public bool IsNull", arrayIntercalate(" && ", nullTests), true); - }, + } ); } - private emitEnumDefinition (e: EnumType, enumName: Name): void { + private emitEnumDefinition(e: EnumType, enumName: Name): void { const caseNames: Sourcelike[] = []; this.forEachEnumCase(e, "none", name => { if (caseNames.length > 0) caseNames.push(", "); @@ -702,7 +694,7 @@ export class CSharpRenderer extends ConvenienceRenderer { this.emitLine("public enum ", enumName, " { ", caseNames, " };"); } - protected emitExpressionMember (declare: Sourcelike, define: Sourcelike, isProperty = false): void { + protected emitExpressionMember(declare: Sourcelike, define: Sourcelike, isProperty = false): void { if (this._csOptions.version === 5) { this.emitLine(declare); this.emitBlock(() => { @@ -724,7 +716,7 @@ export class CSharpRenderer extends ConvenienceRenderer { condition: (t: T) => Sourcelike, withBlock: boolean, withReturn: boolean, - f: (t: T) => void, + f: (t: T) => void ): void { assert(!withReturn || withBlock, "Can only have return with block"); for (const t of types) { @@ -742,40 +734,40 @@ export class CSharpRenderer extends ConvenienceRenderer { } } - protected emitUsing (ns: Sourcelike): void { + protected emitUsing(ns: Sourcelike): void { this.emitLine("using ", ns, ";"); } - protected emitUsings (): void { + protected emitUsings(): void { for (const ns of ["System", "System.Collections.Generic"]) { this.emitUsing(ns); } } - protected emitRequiredHelpers (): void { + protected emitRequiredHelpers(): void { return; } - private emitTypesAndSupport (): void { + private emitTypesAndSupport(): void { this.forEachObject("leading-and-interposing", (c: ClassType, name: Name) => this.emitClassDefinition(c, name)); this.forEachEnum("leading-and-interposing", (e, name) => this.emitEnumDefinition(e, name)); this.forEachUnion("leading-and-interposing", (u, name) => this.emitUnionDefinition(u, name)); this.emitRequiredHelpers(); } - protected emitDefaultLeadingComments (): void { + protected emitDefaultLeadingComments(): void { return; } - protected emitDefaultFollowingComments (): void { + protected emitDefaultFollowingComments(): void { return; } - protected needNamespace (): boolean { + protected needNamespace(): boolean { return true; } - protected emitSourceStructure (): void { + protected emitSourceStructure(): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } else { @@ -809,10 +801,10 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { private readonly _needNamespaces: boolean; - constructor ( + constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues, + private readonly _options: OptionValues ) { super(targetLanguage, renderContext, _options); this._needHelpers = _options.features.helpers; @@ -820,7 +812,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { this._needNamespaces = _options.features.namespaces; } - protected forbiddenNamesForGlobalNamespace (): string[] { + protected forbiddenNamesForGlobalNamespace(): string[] { const forbidden = [ "Converter", "JsonConverter", @@ -832,7 +824,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { "MetadataPropertyHandling", "DateParseHandling", "FromJson", - "Required", + "Required" ]; if (this._options.dense) { forbidden.push("J", "R", "N"); @@ -845,13 +837,13 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { return super.forbiddenNamesForGlobalNamespace().concat(forbidden); } - protected forbiddenForObjectProperties (c: ClassType, className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties(c: ClassType, className: Name): ForbiddenWordsInfo { const result = super.forbiddenForObjectProperties(c, className); result.names = result.names.concat(["ToJson", "FromJson", "Required"]); return result; } - protected makeNameForTransformation (xf: Transformation, typeName: Name | undefined): Name { + protected makeNameForTransformation(xf: Transformation, typeName: Name | undefined): Name { if (typeName === undefined) { let xfer = xf.transformer; if (xfer instanceof DecodingTransformer && xfer.consumer !== undefined) { @@ -864,19 +856,19 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { return new DependencyName(namingFunction, typeName.order + 30, lookup => `${lookup(typeName)}_converter`); } - protected makeNamedTypeDependencyNames (t: Type, name: Name): DependencyName[] { + protected makeNamedTypeDependencyNames(t: Type, name: Name): DependencyName[] { if (!(t instanceof EnumType)) return []; const extensionsName = new DependencyName( namingFunction, name.order + 30, - lookup => `${lookup(name)}_extensions`, + lookup => `${lookup(name)}_extensions` ); this._enumExtensionsNames.set(name, extensionsName); return [extensionsName]; } - protected emitUsings (): void { + protected emitUsings(): void { // FIXME: We need System.Collections.Generic whenever we have maps or use List. if (!this._needAttributes && !this._needHelpers) return; @@ -898,11 +890,11 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { } } - protected baseclassForType (_t: Type): Sourcelike | undefined { + protected baseclassForType(_t: Type): Sourcelike | undefined { return this._options.baseclass; } - protected emitDefaultLeadingComments (): void { + protected emitDefaultLeadingComments(): void { if (!this._needHelpers) return; this.emitLine("// "); @@ -910,7 +902,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { this.emitLine( "// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do", this.topLevels.size === 1 ? "" : " one of these", - ":", + ":" ); this.emitLine("//"); this.emitLine("// using ", this._options.namespace, ";"); @@ -927,7 +919,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { }); } - private converterForType (t: Type): Name | undefined { + private converterForType(t: Type): Name | undefined { let xf = transformationForType(t); if (xf === undefined && t instanceof UnionType) { @@ -945,11 +937,11 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { return defined(this.nameForTransformation(t)); } - protected attributesForProperty ( + protected attributesForProperty( property: ClassProperty, _name: Name, _c: ClassType, - jsonName: string, + jsonName: string ): Sourcelike[] | undefined { if (!this._needAttributes) return undefined; @@ -964,7 +956,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { const nullValueHandling = isOptional && !isNullable ? [", NullValueHandling = ", nullValueHandlingClass, ".Ignore"] : []; let required: Sourcelike; - if (!this._options.checkRequired || isOptional && isNullable) { + if (!this._options.checkRequired || (isOptional && isNullable)) { required = [nullValueHandling]; } else if (isOptional && !isNullable) { required = [", Required = ", requiredClass, ".DisallowNull", nullValueHandling]; @@ -974,7 +966,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { required = [", Required = ", requiredClass, ".Always", nullValueHandling]; } - attributes.push(["[", jsonProperty, "(\"", escapedName, "\"", required, ")]"]); + attributes.push(["[", jsonProperty, '("', escapedName, '"', required, ")]"]); const converter = this.converterForType(property.type); if (converter !== undefined) { @@ -984,16 +976,16 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { return attributes; } - protected blankLinesBetweenAttributes (): boolean { + protected blankLinesBetweenAttributes(): boolean { return this._needAttributes && !this._options.dense; } // The "this" type can't be `dynamic`, so we have to force it to `object`. - private topLevelResultType (t: Type): Sourcelike { + private topLevelResultType(t: Type): Sourcelike { return t.kind === "any" || t.kind === "none" ? "object" : this.csType(t); } - private emitFromJsonForTopLevel (t: Type, name: Name): void { + private emitFromJsonForTopLevel(t: Type, name: Name): void { if (t instanceof EnumType) return; let partial: string; @@ -1012,33 +1004,33 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { // FIXME: Make FromJson a Named this.emitExpressionMember( ["public static ", csType, " FromJson(string json)"], - ["JsonConvert.DeserializeObject<", csType, ">(json, ", this._options.namespace, ".Converter.Settings)"], + ["JsonConvert.DeserializeObject<", csType, ">(json, ", this._options.namespace, ".Converter.Settings)"] ); }); } - private emitDecoderSwitch (emitBody: () => void): void { + private emitDecoderSwitch(emitBody: () => void): void { this.emitLine("switch (reader.TokenType)"); this.emitBlock(emitBody); } - private emitTokenCase (tokenType: string): void { + private emitTokenCase(tokenType: string): void { this.emitLine("case JsonToken.", tokenType, ":"); } - private emitThrow (message: Sourcelike): void { + private emitThrow(message: Sourcelike): void { this.emitLine("throw new Exception(", message, ");"); } - private deserializeTypeCode (typeName: Sourcelike): Sourcelike { + private deserializeTypeCode(typeName: Sourcelike): Sourcelike { return ["serializer.Deserialize<", typeName, ">(reader)"]; } - private serializeValueCode (value: Sourcelike): Sourcelike { + private serializeValueCode(value: Sourcelike): Sourcelike { return ["serializer.Serialize(writer, ", value, ")"]; } - private emitSerializeClass (): void { + private emitSerializeClass(): void { // FIXME: Make Serialize a Named this.emitType(undefined, AccessModifier.Public, "static class", "Serialize", undefined, () => { // Sometimes multiple top-levels will resolve to the same type, so we have to take care @@ -1050,39 +1042,39 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { seenTypes.add(t); this.emitExpressionMember( ["public static string ToJson(this ", this.topLevelResultType(t), " self)"], - ["JsonConvert.SerializeObject(self, ", this._options.namespace, ".Converter.Settings)"], + ["JsonConvert.SerializeObject(self, ", this._options.namespace, ".Converter.Settings)"] ); } }); }); } - private emitCanConvert (expr: Sourcelike): void { + private emitCanConvert(expr: Sourcelike): void { this.emitExpressionMember("public override bool CanConvert(Type t)", expr); } - private emitReadJson (emitBody: () => void): void { + private emitReadJson(emitBody: () => void): void { this.emitLine( - "public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)", + "public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)" ); this.emitBlock(emitBody); } - private emitWriteJson (variable: string, emitBody: () => void): void { + private emitWriteJson(variable: string, emitBody: () => void): void { this.emitLine( "public override void WriteJson(JsonWriter writer, object ", variable, - ", JsonSerializer serializer)", + ", JsonSerializer serializer)" ); this.emitBlock(emitBody); } - private converterObject (converterName: Name): Sourcelike { + private converterObject(converterName: Name): Sourcelike { // FIXME: Get a singleton return [converterName, ".Singleton"]; } - private emitConverterClass (): void { + private emitConverterClass(): void { // FIXME: Make Converter a Named const converterName: Sourcelike = ["Converter"]; this.emitType(undefined, AccessModifier.Internal, "static class", converterName, undefined, () => { @@ -1106,12 +1098,12 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { }); } - private emitDecoderTransformerCase ( + private emitDecoderTransformerCase( tokenCases: string[], variableName: string, xfer: Transformer | undefined, targetType: Type, - emitFinish: (value: Sourcelike) => void, + emitFinish: (value: Sourcelike) => void ): void { if (xfer === undefined) return; @@ -1127,11 +1119,11 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { }); } - private emitConsume ( + private emitConsume( value: Sourcelike, consumer: Transformer | undefined, targetType: Type, - emitFinish: (variableName: Sourcelike) => void, + emitFinish: (variableName: Sourcelike) => void ): boolean { if (consumer === undefined) { emitFinish(value); @@ -1141,11 +1133,11 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { } } - private emitDecodeTransformer ( + private emitDecodeTransformer( xfer: Transformer, targetType: Type, emitFinish: (value: Sourcelike) => void, - variableName = "value", + variableName = "value" ): boolean { if (xfer instanceof DecodingTransformer) { const source = xfer.sourceType; @@ -1160,7 +1152,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { typeSource, ")converter.ReadJson(reader, typeof(", typeSource, - "), null, serializer);", + "), null, serializer);" ); } else if (source.kind !== "null") { let output = targetType.kind === "double" ? targetType : source; @@ -1183,7 +1175,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { xfer.itemTransformer, xfer.itemTargetType, v => this.emitLine(variableName, ".Add(", v, ");"), - "arrayItem", + "arrayItem" ); // FIXME: handle EOF this.emitLine("reader.Read();"); @@ -1213,14 +1205,14 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { "integerValue", xfer.integerTransformer, targetType, - emitFinish, + emitFinish ); this.emitDecoderTransformerCase( xfer.integerTransformer === undefined ? ["Integer", "Float"] : ["Float"], "doubleValue", xfer.doubleTransformer, targetType, - emitFinish, + emitFinish ); this.emitDecoderTransformerCase(["Boolean"], "boolValue", xfer.boolTransformer, targetType, emitFinish); this.emitDecoderTransformerCase( @@ -1228,21 +1220,21 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { "stringValue", xfer.stringTransformer, targetType, - emitFinish, + emitFinish ); this.emitDecoderTransformerCase( ["StartObject"], "objectValue", xfer.objectTransformer, targetType, - emitFinish, + emitFinish ); this.emitDecoderTransformerCase( ["StartArray"], "arrayValue", xfer.arrayTransformer, targetType, - emitFinish, + emitFinish ); }); return false; @@ -1251,9 +1243,9 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { } } - private stringCaseValue (t: Type, stringCase: string): Sourcelike { + private stringCaseValue(t: Type, stringCase: string): Sourcelike { if (t.kind === "string") { - return ["\"", utf16StringEscape(stringCase), "\""]; + return ['"', utf16StringEscape(stringCase), '"']; } else if (t instanceof EnumType) { return [this.nameForNamedType(t), ".", this.nameForEnumCase(t, stringCase)]; } @@ -1261,13 +1253,13 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { return panic(`Type ${t.kind} does not have string cases`); } - private emitTransformer ( + private emitTransformer( variable: Sourcelike, xfer: Transformer, targetType: Type, - emitFinish: (value: Sourcelike) => void, + emitFinish: (value: Sourcelike) => void ): boolean { - function directTargetType (continuation: Transformer | undefined): Type { + function directTargetType(continuation: Transformer | undefined): Type { if (continuation === undefined) { return targetType; } @@ -1284,7 +1276,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { const matchXfer = caseXfer as StringMatchTransformer; const value = this.stringCaseValue( followTargetType(matchXfer.sourceType), - matchXfer.stringCase, + matchXfer.stringCase ); this.emitLine("case ", value, ":"); this.indent(() => { @@ -1292,7 +1284,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { variable, matchXfer.transformer, targetType, - emitFinish, + emitFinish ); if (!allDone) { this.emitLine("break;"); @@ -1400,23 +1392,23 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { switch (xfer.sourceType.kind) { case "date-time": return this.emitConsume( - [variable, ".ToString(\"o\", System.Globalization.CultureInfo.InvariantCulture)"], + [variable, '.ToString("o", System.Globalization.CultureInfo.InvariantCulture)'], xfer.consumer, targetType, - emitFinish, + emitFinish ); case "uuid": return this.emitConsume( - [variable, ".ToString(\"D\", System.Globalization.CultureInfo.InvariantCulture)"], + [variable, '.ToString("D", System.Globalization.CultureInfo.InvariantCulture)'], xfer.consumer, targetType, - emitFinish, + emitFinish ); case "integer": case "uri": return this.emitConsume([variable, ".ToString()"], xfer.consumer, targetType, emitFinish); case "bool": - this.emitLine("var boolString = ", variable, " ? \"true\" : \"false\";"); + this.emitLine("var boolString = ", variable, ' ? "true" : "false";'); return this.emitConsume("boolString", xfer.consumer, targetType, emitFinish); default: return panic(`Stringifying ${xfer.sourceType.kind} not supported`); @@ -1485,7 +1477,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { return false; } - private emitTransformation (converterName: Name, t: Type): void { + private emitTransformation(converterName: Name, t: Type): void { const xf = defined(transformationForType(t)); const reverse = xf.reverse; const targetType = xf.targetType; @@ -1513,7 +1505,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { const allHandled = this.emitDecodeTransformer(xfer, targetType, v => this.emitLine("return ", v, ";")); if (!allHandled) { - this.emitThrow(["\"Cannot unmarshal type ", csType, "\""]); + this.emitThrow(['"Cannot unmarshal type ', csType, '"']); } }); this.ensureBlankLine(); @@ -1529,10 +1521,10 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { this.emitLine("var value = (", csType, ")untypedValue;"); const allHandled = this.emitTransformer("value", reverse.transformer, reverse.targetType, () => - this.emitLine("return;"), + this.emitLine("return;") ); if (!allHandled) { - this.emitThrow(["\"Cannot marshal type ", csType, "\""]); + this.emitThrow(['"Cannot marshal type ', csType, '"']); } }); this.ensureBlankLine(); @@ -1540,21 +1532,21 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { }); } - protected emitRequiredHelpers (): void { + protected emitRequiredHelpers(): void { if (this._needHelpers) { this.forEachTopLevel("leading-and-interposing", (t, n) => this.emitFromJsonForTopLevel(t, n)); this.ensureBlankLine(); this.emitSerializeClass(); } - if (this._needHelpers || this._needAttributes && (this.haveNamedUnions || this.haveEnums)) { + if (this._needHelpers || (this._needAttributes && (this.haveNamedUnions || this.haveEnums))) { this.ensureBlankLine(); this.emitConverterClass(); this.forEachTransformation("leading-and-interposing", (n, t) => this.emitTransformation(n, t)); } } - protected needNamespace (): boolean { + protected needNamespace(): boolean { return this._needNamespaces; } } @@ -1570,10 +1562,10 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { private readonly _needNamespaces: boolean; - constructor ( + constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues, + private readonly _options: OptionValues ) { super(targetLanguage, renderContext, _options); this._needHelpers = _options.features.helpers; @@ -1581,7 +1573,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { this._needNamespaces = _options.features.namespaces; } - protected forbiddenNamesForGlobalNamespace (): string[] { + protected forbiddenNamesForGlobalNamespace(): string[] { const forbidden = [ "Converter", "JsonConverter", @@ -1594,7 +1586,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { // "MetadataPropertyHandling", // "DateParseHandling", "FromJson", - "Required", + "Required" ]; if (this._options.dense) { forbidden.push("J", "R", "N"); @@ -1607,13 +1599,13 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { return super.forbiddenNamesForGlobalNamespace().concat(forbidden); } - protected forbiddenForObjectProperties (c: ClassType, className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties(c: ClassType, className: Name): ForbiddenWordsInfo { const result = super.forbiddenForObjectProperties(c, className); result.names = result.names.concat(["ToJson", "FromJson", "Required"]); return result; } - protected makeNameForTransformation (xf: Transformation, typeName: Name | undefined): Name { + protected makeNameForTransformation(xf: Transformation, typeName: Name | undefined): Name { if (typeName === undefined) { let xfer = xf.transformer; if (xfer instanceof DecodingTransformer && xfer.consumer !== undefined) { @@ -1626,19 +1618,19 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { return new DependencyName(namingFunction, typeName.order + 30, lookup => `${lookup(typeName)}_converter`); } - protected makeNamedTypeDependencyNames (t: Type, name: Name): DependencyName[] { + protected makeNamedTypeDependencyNames(t: Type, name: Name): DependencyName[] { if (!(t instanceof EnumType)) return []; const extensionsName = new DependencyName( namingFunction, name.order + 30, - lookup => `${lookup(name)}_extensions`, + lookup => `${lookup(name)}_extensions` ); this._enumExtensionsNames.set(name, extensionsName); return [extensionsName]; } - protected emitUsings (): void { + protected emitUsings(): void { // FIXME: We need System.Collections.Generic whenever we have maps or use List. if (!this._needAttributes && !this._needHelpers) return; @@ -1660,11 +1652,11 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { } } - protected baseclassForType (_t: Type): Sourcelike | undefined { + protected baseclassForType(_t: Type): Sourcelike | undefined { return this._options.baseclass; } - protected emitDefaultFollowingComments (): void { + protected emitDefaultFollowingComments(): void { if (!this._needHelpers) return; this.emitLine("#pragma warning restore CS8618"); @@ -1672,7 +1664,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { this.emitLine("#pragma warning restore CS8603"); } - protected emitDefaultLeadingComments (): void { + protected emitDefaultLeadingComments(): void { if (!this._needHelpers) return; this.emitLine("// "); @@ -1680,7 +1672,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { this.emitLine( "// To parse this JSON data, add NuGet 'System.Text.Json' then do", this.topLevels.size === 1 ? "" : " one of these", - ":", + ":" ); this.emitLine("//"); this.emitLine("// using ", this._options.namespace, ";"); @@ -1703,7 +1695,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { this.emitLine("#pragma warning disable CS8603"); } - private converterForType (t: Type): Name | undefined { + private converterForType(t: Type): Name | undefined { let xf = transformationForType(t); if (xf === undefined && t instanceof UnionType) { @@ -1721,11 +1713,11 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { return defined(this.nameForTransformation(t)); } - protected attributesForProperty ( + protected attributesForProperty( property: ClassProperty, _name: Name, _c: ClassType, - jsonName: string, + jsonName: string ): Sourcelike[] | undefined { if (!this._needAttributes) return undefined; @@ -1754,7 +1746,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { // required = [", Required = ", requiredClass, ".Always", nullValueHandling]; // } - attributes.push(["[", jsonPropertyName, "(\"", escapedName, "\")]"]); + attributes.push(["[", jsonPropertyName, '("', escapedName, '")]']); const converter = this.converterForType(property.type); if (converter !== undefined) { @@ -1764,16 +1756,16 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { return attributes; } - protected blankLinesBetweenAttributes (): boolean { + protected blankLinesBetweenAttributes(): boolean { return this._needAttributes && !this._options.dense; } // The "this" type can't be `dynamic`, so we have to force it to `object`. - private topLevelResultType (t: Type): Sourcelike { + private topLevelResultType(t: Type): Sourcelike { return t.kind === "any" || t.kind === "none" ? "object" : this.csType(t); } - private emitFromJsonForTopLevel (t: Type, name: Name): void { + private emitFromJsonForTopLevel(t: Type, name: Name): void { if (t instanceof EnumType) return; let partial: string; @@ -1792,25 +1784,25 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { // FIXME: Make FromJson a Named this.emitExpressionMember( ["public static ", csType, " FromJson(string json)"], - ["JsonSerializer.Deserialize<", csType, ">(json, ", this._options.namespace, ".Converter.Settings)"], + ["JsonSerializer.Deserialize<", csType, ">(json, ", this._options.namespace, ".Converter.Settings)"] ); }); } - private emitDecoderSwitch (emitBody: () => void): void { + private emitDecoderSwitch(emitBody: () => void): void { this.emitLine("switch (reader.TokenType)"); this.emitBlock(emitBody); } - private emitTokenCase (tokenType: string): void { + private emitTokenCase(tokenType: string): void { this.emitLine("case JsonTokenType.", tokenType, ":"); } - private emitThrow (message: Sourcelike): void { + private emitThrow(message: Sourcelike): void { this.emitLine("throw new Exception(", message, ");"); } - private deserializeTypeCode (typeName: Sourcelike): Sourcelike { + private deserializeTypeCode(typeName: Sourcelike): Sourcelike { switch (typeName) { case "bool": return ["reader.GetBoolean()"]; @@ -1827,12 +1819,12 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { } } - private serializeValueCode (value: Sourcelike): Sourcelike { + private serializeValueCode(value: Sourcelike): Sourcelike { if (value !== "null") return ["JsonSerializer.Serialize(writer, ", value, ", options)"]; else return ["writer.WriteNullValue()"]; } - private emitSerializeClass (): void { + private emitSerializeClass(): void { // FIXME: Make Serialize a Named this.emitType(undefined, AccessModifier.Public, "static class", "Serialize", undefined, () => { // Sometimes multiple top-levels will resolve to the same type, so we have to take care @@ -1844,49 +1836,49 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { seenTypes.add(t); this.emitExpressionMember( ["public static string ToJson(this ", this.topLevelResultType(t), " self)"], - ["JsonSerializer.Serialize(self, ", this._options.namespace, ".Converter.Settings)"], + ["JsonSerializer.Serialize(self, ", this._options.namespace, ".Converter.Settings)"] ); } }); }); } - private emitCanConvert (expr: Sourcelike): void { + private emitCanConvert(expr: Sourcelike): void { this.emitExpressionMember("public override bool CanConvert(Type t)", expr); } - private emitReadJson (emitBody: () => void, csType: Sourcelike): void { + private emitReadJson(emitBody: () => void, csType: Sourcelike): void { this.emitLine( "public override ", csType, - " Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)", + " Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)" ); this.emitBlock(emitBody); } - private emitWriteJson (variable: string, emitBody: () => void, csType: Sourcelike): void { + private emitWriteJson(variable: string, emitBody: () => void, csType: Sourcelike): void { this.emitLine( "public override void Write(Utf8JsonWriter writer, ", csType, " ", variable, - ", JsonSerializerOptions options)", + ", JsonSerializerOptions options)" ); this.emitBlock(emitBody); } - private converterObject (converterName: Name): Sourcelike { + private converterObject(converterName: Name): Sourcelike { // FIXME: Get a singleton return [converterName, ".Singleton"]; } - private emitConverterClass (): void { + private emitConverterClass(): void { // FIXME: Make Converter a Named const converterName: Sourcelike = ["Converter"]; this.emitType(undefined, AccessModifier.Internal, "static class", converterName, undefined, () => { // Do not use .Web as defaults. That turns on caseInsensitive property names and will fail the keywords test. this.emitLine( - "public static readonly JsonSerializerOptions Settings = new(JsonSerializerDefaults.General)", + "public static readonly JsonSerializerOptions Settings = new(JsonSerializerDefaults.General)" ); this.emitBlock(() => { // this.emitLine("MetadataPropertyHandling = MetadataPropertyHandling.Ignore,"); @@ -1910,12 +1902,12 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { }); } - private emitDecoderTransformerCase ( + private emitDecoderTransformerCase( tokenCases: string[], variableName: string, xfer: Transformer | undefined, targetType: Type, - emitFinish: (value: Sourcelike) => void, + emitFinish: (value: Sourcelike) => void ): void { if (xfer === undefined) return; @@ -1931,11 +1923,11 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { }); } - private emitConsume ( + private emitConsume( value: Sourcelike, consumer: Transformer | undefined, targetType: Type, - emitFinish: (variableName: Sourcelike) => void, + emitFinish: (variableName: Sourcelike) => void ): boolean { if (consumer === undefined) { emitFinish(value); @@ -1945,11 +1937,11 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { } } - private emitDecodeTransformer ( + private emitDecodeTransformer( xfer: Transformer, targetType: Type, emitFinish: (value: Sourcelike) => void, - variableName = "value", + variableName = "value" ): boolean { if (xfer instanceof DecodingTransformer) { const source = xfer.sourceType; @@ -1964,7 +1956,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { typeSource, ")converter.ReadJson(reader, typeof(", typeSource, - "), null, serializer);", + "), null, serializer);" ); } else if (source.kind !== "null") { let output = targetType.kind === "double" ? targetType : source; @@ -1987,7 +1979,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { xfer.itemTransformer, xfer.itemTargetType, v => this.emitLine(variableName, ".Add(", v, ");"), - "arrayItem", + "arrayItem" ); // FIXME: handle EOF this.emitLine("reader.Read();"); @@ -2017,7 +2009,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { "integerValue", xfer.integerTransformer, targetType, - emitFinish, + emitFinish ); this.emitDecoderTransformerCase( ["Number"], @@ -2025,14 +2017,14 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { "doubleValue", xfer.doubleTransformer, targetType, - emitFinish, + emitFinish ); this.emitDecoderTransformerCase( ["True", "False"], "boolValue", xfer.boolTransformer, targetType, - emitFinish, + emitFinish ); this.emitDecoderTransformerCase( // ["String", "Date"], @@ -2040,21 +2032,21 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { "stringValue", xfer.stringTransformer, targetType, - emitFinish, + emitFinish ); this.emitDecoderTransformerCase( ["StartObject"], "objectValue", xfer.objectTransformer, targetType, - emitFinish, + emitFinish ); this.emitDecoderTransformerCase( ["StartArray"], "arrayValue", xfer.arrayTransformer, targetType, - emitFinish, + emitFinish ); }); return false; @@ -2063,9 +2055,9 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { } } - private stringCaseValue (t: Type, stringCase: string): Sourcelike { + private stringCaseValue(t: Type, stringCase: string): Sourcelike { if (t.kind === "string") { - return ["\"", utf16StringEscape(stringCase), "\""]; + return ['"', utf16StringEscape(stringCase), '"']; } else if (t instanceof EnumType) { return [this.nameForNamedType(t), ".", this.nameForEnumCase(t, stringCase)]; } @@ -2073,13 +2065,13 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { return panic(`Type ${t.kind} does not have string cases`); } - private emitTransformer ( + private emitTransformer( variable: Sourcelike, xfer: Transformer, targetType: Type, - emitFinish: (value: Sourcelike) => void, + emitFinish: (value: Sourcelike) => void ): boolean { - function directTargetType (continuation: Transformer | undefined): Type { + function directTargetType(continuation: Transformer | undefined): Type { if (continuation === undefined) { return targetType; } @@ -2096,7 +2088,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { const matchXfer = caseXfer as StringMatchTransformer; const value = this.stringCaseValue( followTargetType(matchXfer.sourceType), - matchXfer.stringCase, + matchXfer.stringCase ); this.emitLine("case ", value, ":"); this.indent(() => { @@ -2104,7 +2096,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { variable, matchXfer.transformer, targetType, - emitFinish, + emitFinish ); if (!allDone) { this.emitLine("break;"); @@ -2192,7 +2184,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { this.emitBlock(() => { // this.emitLine("var uri = new Uri(", variable, ");"); // The default value about:blank should never happen, but this way we avoid a null reference warning. - this.emitLine("var uri = new Uri(\"about:blank\");"); + this.emitLine('var uri = new Uri("about:blank");'); this.emitLine("if (!string.IsNullOrEmpty(stringValue))"); this.emitBlock(() => { this.emitLine("uri = new Uri(", variable, ");"); @@ -2218,23 +2210,23 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { switch (xfer.sourceType.kind) { case "date-time": return this.emitConsume( - [variable, ".ToString(\"o\", System.Globalization.CultureInfo.InvariantCulture)"], + [variable, '.ToString("o", System.Globalization.CultureInfo.InvariantCulture)'], xfer.consumer, targetType, - emitFinish, + emitFinish ); case "uuid": return this.emitConsume( - [variable, ".ToString(\"D\", System.Globalization.CultureInfo.InvariantCulture)"], + [variable, '.ToString("D", System.Globalization.CultureInfo.InvariantCulture)'], xfer.consumer, targetType, - emitFinish, + emitFinish ); case "integer": case "uri": return this.emitConsume([variable, ".ToString()"], xfer.consumer, targetType, emitFinish); case "bool": - this.emitLine("var boolString = ", variable, " ? \"true\" : \"false\";"); + this.emitLine("var boolString = ", variable, ' ? "true" : "false";'); return this.emitConsume("boolString", xfer.consumer, targetType, emitFinish); default: return panic(`Stringifying ${xfer.sourceType.kind} not supported`); @@ -2303,7 +2295,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { return false; } - private emitTransformation (converterName: Name, t: Type): void { + private emitTransformation(converterName: Name, t: Type): void { const xf = defined(transformationForType(t)); const reverse = xf.reverse; const targetType = xf.targetType; @@ -2337,10 +2329,10 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { // } const allHandled = this.emitDecodeTransformer(xfer, targetType, v => - this.emitLine("return ", v, ";"), + this.emitLine("return ", v, ";") ); if (!allHandled) { - this.emitThrow(["\"Cannot unmarshal type ", csType, "\""]); + this.emitThrow(['"Cannot unmarshal type ', csType, '"']); } }, csType); this.ensureBlankLine(); @@ -2357,28 +2349,28 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { // } const allHandled = this.emitTransformer("value", reverse.transformer, reverse.targetType, () => - this.emitLine("return;"), + this.emitLine("return;") ); if (!allHandled) { - this.emitThrow(["\"Cannot marshal type ", csType, "\""]); + this.emitThrow(['"Cannot marshal type ', csType, '"']); } }, - csType, + csType ); this.ensureBlankLine(); this.emitLine("public static readonly ", converterName, " Singleton = new ", converterName, "();"); - }, + } ); } - protected emitRequiredHelpers (): void { + protected emitRequiredHelpers(): void { if (this._needHelpers) { this.forEachTopLevel("leading-and-interposing", (t, n) => this.emitFromJsonForTopLevel(t, n)); this.ensureBlankLine(); this.emitSerializeClass(); } - if (this._needHelpers || this._needAttributes && (this.haveNamedUnions || this.haveEnums)) { + if (this._needHelpers || (this._needAttributes && (this.haveNamedUnions || this.haveEnums))) { this.ensureBlankLine(); this.emitConverterClass(); this.forEachTransformation("leading-and-interposing", (n, t) => this.emitTransformation(n, t)); @@ -2495,7 +2487,7 @@ internal class IsoDateTimeOffsetConverter : JsonConverter } } - protected needNamespace (): boolean { + protected needNamespace(): boolean { return this._needNamespaces; } } diff --git a/packages/quicktype-core/src/language/Kotlin.ts b/packages/quicktype-core/src/language/Kotlin.ts index 53d636499..d88b58060 100644 --- a/packages/quicktype-core/src/language/Kotlin.ts +++ b/packages/quicktype-core/src/language/Kotlin.ts @@ -3,11 +3,11 @@ import { iterableSome, arrayIntercalate } from "collection-utils"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Name, type Namer} from "../Naming"; +import { type Name, type Namer } from "../Naming"; import { funPrefixNamer } from "../Naming"; -import { type Option, type OptionValues} from "../RendererOptions"; +import { type Option, type OptionValues } from "../RendererOptions"; import { EnumOption, StringOption, getOptionValues } from "../RendererOptions"; -import { type Sourcelike} from "../Source"; +import { type Sourcelike } from "../Source"; import { maybeAnnotated, modifySource } from "../Source"; import { allLowerWordStyle, @@ -23,31 +23,21 @@ import { isPrintable, legalizeCharacters, splitIntoWords, - utf32ConcatMap, + utf32ConcatMap } from "../support/Strings"; import { assertNever, mustNotHappen } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; -import { - type ClassProperty, - type EnumType, - type ObjectType, - type PrimitiveType, - type Type} from "../Type"; -import { - ArrayType, - ClassType, - MapType, - UnionType, -} from "../Type"; +import { type ClassProperty, type EnumType, type ObjectType, type PrimitiveType, type Type } from "../Type"; +import { ArrayType, ClassType, MapType, UnionType } from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; import { type RenderContext } from "../Renderer"; import { acronymOption, acronymStyle, AcronymStyleOptions } from "../support/Acronyms"; export enum Framework { - None, - Jackson, - Klaxon, - KotlinX + None = "None", + Jackson = "Jackson", + Klaxon = "Klaxon", + KotlinX = "KotlinX" } export const kotlinOptions = { @@ -58,34 +48,34 @@ export const kotlinOptions = { ["just-types", Framework.None], ["jackson", Framework.Jackson], ["klaxon", Framework.Klaxon], - ["kotlinx", Framework.KotlinX], + ["kotlinx", Framework.KotlinX] ], - "klaxon", + "klaxon" ), acronymStyle: acronymOption(AcronymStyleOptions.Pascal), - packageName: new StringOption("package", "Package", "PACKAGE", "quicktype"), + packageName: new StringOption("package", "Package", "PACKAGE", "quicktype") }; export class KotlinTargetLanguage extends TargetLanguage { - constructor () { + constructor() { super("Kotlin", ["kotlin"], "kt"); } - protected getOptions (): Array> { + protected getOptions(): Array> { return [kotlinOptions.framework, kotlinOptions.acronymStyle, kotlinOptions.packageName]; } - get supportsOptionalClassProperties (): boolean { + get supportsOptionalClassProperties(): boolean { return true; } - get supportsUnionsWithBothNumberTypes (): boolean { + get supportsUnionsWithBothNumberTypes(): boolean { return true; } - protected makeRenderer ( + protected makeRenderer( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any, }, + untypedOptionValues: { [name: string]: any } ): ConvenienceRenderer { const options = getOptionValues(kotlinOptions, untypedOptionValues); @@ -153,23 +143,23 @@ const keywords = [ "JsonObject", "JsonValue", "Converter", - "Klaxon", + "Klaxon" ]; -function isPartCharacter (codePoint: number): boolean { +function isPartCharacter(codePoint: number): boolean { return isLetterOrUnderscore(codePoint) || isNumeric(codePoint); } -function isStartCharacter (codePoint: number): boolean { +function isStartCharacter(codePoint: number): boolean { return isPartCharacter(codePoint) && !isDigit(codePoint); } const legalizeName = legalizeCharacters(isPartCharacter); -function kotlinNameStyle ( +function kotlinNameStyle( isUpper: boolean, original: string, - acronymsStyle: (s: string) => string = allUpperWordStyle, + acronymsStyle: (s: string) => string = allUpperWordStyle ): string { const words = splitIntoWords(original); return combineWords( @@ -180,92 +170,92 @@ function kotlinNameStyle ( isUpper ? allUpperWordStyle : allLowerWordStyle, acronymsStyle, "", - isStartCharacter, + isStartCharacter ); } -function unicodeEscape (codePoint: number): string { +function unicodeEscape(codePoint: number): string { return "\\u" + intToHex(codePoint, 4); } const _stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, unicodeEscape)); -function stringEscape (s: string): string { +function stringEscape(s: string): string { // "$this" is a template string in Kotlin so we have to escape $ return _stringEscape(s).replace(/\$/g, "\\$"); } export class KotlinRenderer extends ConvenienceRenderer { - constructor ( + constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - protected readonly _kotlinOptions: OptionValues, + protected readonly _kotlinOptions: OptionValues ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace (): string[] { + protected forbiddenNamesForGlobalNamespace(): string[] { return keywords; } - protected forbiddenForObjectProperties (_o: ObjectType, _classNamed: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties(_o: ObjectType, _classNamed: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForEnumCases (_e: EnumType, _enumName: Name): ForbiddenWordsInfo { + protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForUnionMembers (_u: UnionType, _unionName: Name): ForbiddenWordsInfo { + protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: false }; } - protected topLevelNameStyle (rawName: string): string { + protected topLevelNameStyle(rawName: string): string { return kotlinNameStyle(true, rawName); } - protected makeNamedTypeNamer (): Namer { + protected makeNamedTypeNamer(): Namer { return funPrefixNamer("upper", s => kotlinNameStyle(true, s, acronymStyle(this._kotlinOptions.acronymStyle))); } - protected namerForObjectProperty (): Namer { + protected namerForObjectProperty(): Namer { return funPrefixNamer("lower", s => kotlinNameStyle(false, s, acronymStyle(this._kotlinOptions.acronymStyle))); } - protected makeUnionMemberNamer (): Namer { + protected makeUnionMemberNamer(): Namer { return funPrefixNamer("upper", s => kotlinNameStyle(true, s) + "Value"); } - protected makeEnumCaseNamer (): Namer { + protected makeEnumCaseNamer(): Namer { return funPrefixNamer("upper", s => kotlinNameStyle(true, s, acronymStyle(this._kotlinOptions.acronymStyle))); } - protected emitDescriptionBlock (lines: Sourcelike[]): void { + protected emitDescriptionBlock(lines: Sourcelike[]): void { this.emitCommentLines(lines, { lineStart: " * ", beforeComment: "/**", afterComment: " */" }); } - protected emitBlock (line: Sourcelike, f: () => void, delimiter: "curly" | "paren" | "lambda" = "curly"): void { + protected emitBlock(line: Sourcelike, f: () => void, delimiter: "curly" | "paren" | "lambda" = "curly"): void { const [open, close] = delimiter === "curly" ? ["{", "}"] : delimiter === "paren" ? ["(", ")"] : ["{", "})"]; this.emitLine(line, " ", open); this.indent(f); this.emitLine(close); } - protected anySourceType (optional: string): Sourcelike { + protected anySourceType(optional: string): Sourcelike { return ["Any", optional]; } // (asarazan): I've broken out the following two functions // because some renderers, such as kotlinx, can cope with `any`, while some get mad. - protected arrayType (arrayType: ArrayType, withIssues = false, _noOptional = false): Sourcelike { + protected arrayType(arrayType: ArrayType, withIssues = false, _noOptional = false): Sourcelike { return ["List<", this.kotlinType(arrayType.items, withIssues), ">"]; } - protected mapType (mapType: MapType, withIssues = false, _noOptional = false): Sourcelike { + protected mapType(mapType: MapType, withIssues = false, _noOptional = false): Sourcelike { return ["Map"]; } - protected kotlinType (t: Type, withIssues = false, noOptional = false): Sourcelike { + protected kotlinType(t: Type, withIssues = false, noOptional = false): Sourcelike { const optional = noOptional ? "" : "?"; return matchType( t, @@ -287,15 +277,15 @@ export class KotlinRenderer extends ConvenienceRenderer { const nullable = nullableFromUnion(unionType); if (nullable !== null) return [this.kotlinType(nullable, withIssues), optional]; return this.nameForNamedType(unionType); - }, + } ); } - protected emitUsageHeader (): void { + protected emitUsageHeader(): void { // To be overridden } - protected emitHeader (): void { + protected emitHeader(): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } else { @@ -307,23 +297,23 @@ export class KotlinRenderer extends ConvenienceRenderer { this.ensureBlankLine(); } - protected emitTopLevelArray (t: ArrayType, name: Name): void { + protected emitTopLevelArray(t: ArrayType, name: Name): void { const elementType = this.kotlinType(t.items); this.emitLine(["typealias ", name, " = ArrayList<", elementType, ">"]); } - protected emitTopLevelMap (t: MapType, name: Name): void { + protected emitTopLevelMap(t: MapType, name: Name): void { const elementType = this.kotlinType(t.values); this.emitLine(["typealias ", name, " = HashMap"]); } - protected emitEmptyClassDefinition (c: ClassType, className: Name): void { + protected emitEmptyClassDefinition(c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); this.emitClassAnnotations(c, className); this.emitLine("class ", className, "()"); } - protected emitClassDefinition (c: ClassType, className: Name): void { + protected emitClassDefinition(c: ClassType, className: Name): void { if (c.getProperties().size === 0) { this.emitEmptyClassDefinition(c, className); return; @@ -377,19 +367,19 @@ export class KotlinRenderer extends ConvenienceRenderer { this.emitClassDefinitionMethods(c, className); } - protected emitClassDefinitionMethods (_c: ClassType, _className: Name) { + protected emitClassDefinitionMethods(_c: ClassType, _className: Name) { this.emitLine(")"); } - protected emitClassAnnotations (_c: Type, _className: Name) { + protected emitClassAnnotations(_c: Type, _className: Name) { // to be overridden } - protected renameAttribute (_name: Name, _jsonName: string, _required: boolean, _meta: Array<() => void>) { + protected renameAttribute(_name: Name, _jsonName: string, _required: boolean, _meta: Array<() => void>) { // to be overridden } - protected emitEnumDefinition (e: EnumType, enumName: Name): void { + protected emitEnumDefinition(e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); this.emitBlock(["enum class ", enumName], () => { @@ -400,8 +390,8 @@ export class KotlinRenderer extends ConvenienceRenderer { }); } - protected emitUnionDefinition (u: UnionType, unionName: Name): void { - function sortBy (t: Type): string { + protected emitUnionDefinition(u: UnionType, unionName: Name): void { + function sortBy(t: Type): string { const kind = t.kind; if (kind === "class") return kind; return "_" + kind; @@ -417,13 +407,13 @@ export class KotlinRenderer extends ConvenienceRenderer { this.forEachUnionMember(u, nonNulls, "none", null, (name, t) => { table.push([ ["class ", name, "(val value: ", this.kotlinType(t), ")"], - [" : ", unionName, "()"], + [" : ", unionName, "()"] ]); }); if (maybeNull !== null) { table.push([ ["class ", this.nameForUnionMember(u, maybeNull), "()"], - [" : ", unionName, "()"], + [" : ", unionName, "()"] ]); } @@ -434,16 +424,16 @@ export class KotlinRenderer extends ConvenienceRenderer { }); } - protected emitUnionDefinitionMethods ( + protected emitUnionDefinitionMethods( _u: UnionType, _nonNulls: ReadonlySet, _maybeNull: PrimitiveType | null, - _unionName: Name, + _unionName: Name ) { // to be overridden } - protected emitSourceStructure (): void { + protected emitSourceStructure(): void { this.emitHeader(); // Top-level arrays, maps @@ -459,21 +449,21 @@ export class KotlinRenderer extends ConvenienceRenderer { "leading-and-interposing", (c: ClassType, n: Name) => this.emitClassDefinition(c, n), (e, n) => this.emitEnumDefinition(e, n), - (u, n) => this.emitUnionDefinition(u, n), + (u, n) => this.emitUnionDefinition(u, n) ); } } export class KotlinKlaxonRenderer extends KotlinRenderer { - constructor ( + constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - _kotlinOptions: OptionValues, + _kotlinOptions: OptionValues ) { super(targetLanguage, renderContext, _kotlinOptions); } - private unionMemberFromJsonValue (t: Type, e: Sourcelike): Sourcelike { + private unionMemberFromJsonValue(t: Type, e: Sourcelike): Sourcelike { return matchType( t, _anyType => [e, ".inside"], @@ -486,11 +476,11 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { _classType => [e, ".obj?.let { klaxon.parseFromJsonObject<", this.kotlinType(t), ">(it) }"], _mapType => [e, ".obj?.let { klaxon.parseFromJsonObject<", this.kotlinType(t), ">(it) }"], enumType => [e, ".string?.let { ", this.kotlinType(enumType), ".fromValue(it) }"], - _unionType => mustNotHappen(), + _unionType => mustNotHappen() ); } - private unionMemberJsonValueGuard (t: Type, _e: Sourcelike): Sourcelike { + private unionMemberJsonValueGuard(t: Type, _e: Sourcelike): Sourcelike { return matchType( t, _anyType => "is Any", @@ -507,11 +497,11 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { // This could be stricter, but for now we don't allow strings // and enums in the same union _enumType => "is String", - _unionType => mustNotHappen(), + _unionType => mustNotHappen() ); } - protected emitUsageHeader (): void { + protected emitUsageHeader(): void { this.emitLine("// To parse the JSON, install Klaxon and do:"); this.emitLine("//"); this.forEachTopLevel("none", (_, name) => { @@ -519,18 +509,18 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { }); } - protected emitHeader (): void { + protected emitHeader(): void { super.emitHeader(); this.emitLine("import com.beust.klaxon.*"); const hasUnions = iterableSome( this.typeGraph.allNamedTypes(), - t => t instanceof UnionType && nullableFromUnion(t) === null, + t => t instanceof UnionType && nullableFromUnion(t) === null ); const hasEmptyObjects = iterableSome( this.typeGraph.allNamedTypes(), - c => c instanceof ClassType && c.getProperties().size === 0, + c => c instanceof ClassType && c.getProperties().size === 0 ); if (hasUnions || this.haveEnums || hasEmptyObjects) { this.emitGenericConverter(); @@ -545,14 +535,14 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { converters.push([ [".convert(", name, "::class,"], [" { ", name, ".fromValue(it.string!!) },"], - [" { \"\\\"${it.value}\\\"\" })"], + [' { "\\"${it.value}\\"" })'] ]); }); this.forEachUnion("none", (_, name) => { converters.push([ [".convert(", name, "::class,"], [" { ", name, ".fromJson(it) },"], - [" { it.toJson() }, true)"], + [" { it.toJson() }, true)"] ]); }); @@ -563,7 +553,7 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { } } - protected emitTopLevelArray (t: ArrayType, name: Name): void { + protected emitTopLevelArray(t: ArrayType, name: Name): void { const elementType = this.kotlinType(t.items); this.emitBlock( ["class ", name, "(elements: Collection<", elementType, ">) : ArrayList<", elementType, ">(elements)"], @@ -576,14 +566,14 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { name, "(klaxon.parseArray<", elementType, - ">(json)!!)", + ">(json)!!)" ); }); - }, + } ); } - protected emitTopLevelMap (t: MapType, name: Name): void { + protected emitTopLevelMap(t: MapType, name: Name): void { const elementType = this.kotlinType(t.values); this.emitBlock( [ @@ -593,7 +583,7 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { elementType, ">) : HashMap(elements)", + ">(elements)" ], () => { this.emitLine("public fun toJson() = klaxon.toJsonString(this)"); @@ -605,22 +595,22 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { this.emitLine( "klaxon.parseJsonObject(java.io.StringReader(json)) as Map", + ">" ); }, - "paren", + "paren" ); }); - }, + } ); } - private klaxonRenameAttribute (propName: Name, jsonName: string, ignore = false): Sourcelike | undefined { + private klaxonRenameAttribute(propName: Name, jsonName: string, ignore = false): Sourcelike | undefined { const escapedName = stringEscape(jsonName); const namesDiffer = this.sourcelikeToString(propName) !== escapedName; const properties: Sourcelike[] = []; if (namesDiffer) { - properties.push(["name = \"", escapedName, "\""]); + properties.push(['name = "', escapedName, '"']); } if (ignore) { @@ -630,13 +620,13 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { return properties.length === 0 ? undefined : ["@Json(", arrayIntercalate(", ", properties), ")"]; } - protected emitEmptyClassDefinition (c: ClassType, className: Name): void { + protected emitEmptyClassDefinition(c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); this.emitLine("typealias ", className, " = JsonObject"); } - protected emitClassDefinitionMethods (c: ClassType, className: Name) { + protected emitClassDefinitionMethods(c: ClassType, className: Name) { const isTopLevel = iterableSome(this.topLevels, ([_, top]) => top === c); if (isTopLevel) { this.emitBlock(")", () => { @@ -651,14 +641,14 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { } } - protected renameAttribute (name: Name, jsonName: string, _required: boolean, meta: Array<() => void>) { + protected renameAttribute(name: Name, jsonName: string, _required: boolean, meta: Array<() => void>) { const rename = this.klaxonRenameAttribute(name, jsonName); if (rename !== undefined) { meta.push(() => this.emitLine(rename)); } } - protected emitEnumDefinition (e: EnumType, enumName: Name): void { + protected emitEnumDefinition(e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); this.emitBlock(["enum class ", enumName, "(val value: String)"], () => { @@ -680,33 +670,33 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { }); } - private emitGenericConverter (): void { + private emitGenericConverter(): void { this.ensureBlankLine(); this.emitLine( - "private fun Klaxon.convert(k: kotlin.reflect.KClass<*>, fromJson: (JsonValue) -> T, toJson: (T) -> String, isUnion: Boolean = false) =", + "private fun Klaxon.convert(k: kotlin.reflect.KClass<*>, fromJson: (JsonValue) -> T, toJson: (T) -> String, isUnion: Boolean = false) =" ); this.indent(() => { this.emitLine("this.converter(object: Converter {"); this.indent(() => { - this.emitLine("@Suppress(\"UNCHECKED_CAST\")"); + this.emitLine('@Suppress("UNCHECKED_CAST")'); this.emitTable([ ["override fun toJson(value: Any)", " = toJson(value as T)"], ["override fun fromJson(jv: JsonValue)", " = fromJson(jv) as Any"], [ "override fun canConvert(cls: Class<*>)", - " = cls == k.java || (isUnion && cls.superclass == k.java)", - ], + " = cls == k.java || (isUnion && cls.superclass == k.java)" + ] ]); }); this.emitLine("})"); }); } - protected emitUnionDefinitionMethods ( + protected emitUnionDefinitionMethods( u: UnionType, nonNulls: ReadonlySet, maybeNull: PrimitiveType | null, - unionName: Name, + unionName: Name ) { this.ensureBlankLine(); this.emitLine("public fun toJson(): String = klaxon.toJsonString(when (this) {"); @@ -717,7 +707,7 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { }); if (maybeNull !== null) { const name = this.nameForUnionMember(u, maybeNull); - toJsonTable.push([["is ", name], [" -> \"null\""]]); + toJsonTable.push([["is ", name], [' -> "null"']]); } this.emitTable(toJsonTable); @@ -731,7 +721,7 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { this.forEachUnionMember(u, nonNulls, "none", null, (name, t) => { table.push([ [this.unionMemberJsonValueGuard(t, "jv.inside")], - [" -> ", name, "(", this.unionMemberFromJsonValue(t, "jv"), "!!)"], + [" -> ", name, "(", this.unionMemberFromJsonValue(t, "jv"), "!!)"] ]); }); if (maybeNull !== null) { @@ -748,15 +738,15 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { } export class KotlinJacksonRenderer extends KotlinRenderer { - constructor ( + constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - _kotlinOptions: OptionValues, + _kotlinOptions: OptionValues ) { super(targetLanguage, renderContext, _kotlinOptions); } - private unionMemberJsonValueGuard (t: Type, _e: Sourcelike): Sourcelike { + private unionMemberJsonValueGuard(t: Type, _e: Sourcelike): Sourcelike { return matchType( t, _anyType => "is Any", @@ -773,11 +763,11 @@ export class KotlinJacksonRenderer extends KotlinRenderer { // This could be stricter, but for now we don't allow strings // and enums in the same union _enumType => "is TextNode", - _unionType => mustNotHappen(), + _unionType => mustNotHappen() ); } - protected emitUsageHeader (): void { + protected emitUsageHeader(): void { this.emitLine("// To parse the JSON, install jackson-module-kotlin and do:"); this.emitLine("//"); this.forEachTopLevel("none", (_, name) => { @@ -785,7 +775,7 @@ export class KotlinJacksonRenderer extends KotlinRenderer { }); } - protected emitHeader (): void { + protected emitHeader(): void { super.emitHeader(); this.emitMultiline(`import com.fasterxml.jackson.annotation.* @@ -799,11 +789,11 @@ import com.fasterxml.jackson.module.kotlin.*`); const hasUnions = iterableSome( this.typeGraph.allNamedTypes(), - t => t instanceof UnionType && nullableFromUnion(t) === null, + t => t instanceof UnionType && nullableFromUnion(t) === null ); const hasEmptyObjects = iterableSome( this.typeGraph.allNamedTypes(), - c => c instanceof ClassType && c.getProperties().size === 0, + c => c instanceof ClassType && c.getProperties().size === 0 ); if (hasUnions || this.haveEnums || hasEmptyObjects) { this.emitGenericConverter(); @@ -817,14 +807,14 @@ import com.fasterxml.jackson.module.kotlin.*`); converters.push([ ["convert(", name, "::class,"], [" { ", name, ".fromValue(it.asText()) },"], - [" { \"\\\"${it.value}\\\"\" })"], + [' { "\\"${it.value}\\"" })'] ]); }); this.forEachUnion("none", (_, name) => { converters.push([ ["convert(", name, "::class,"], [" { ", name, ".fromJson(it) },"], - [" { it.toJson() }, true)"], + [" { it.toJson() }, true)"] ]); }); @@ -842,7 +832,7 @@ import com.fasterxml.jackson.module.kotlin.*`); this.emitLine("}"); } - protected emitTopLevelArray (t: ArrayType, name: Name): void { + protected emitTopLevelArray(t: ArrayType, name: Name): void { const elementType = this.kotlinType(t.items); this.emitBlock( ["class ", name, "(elements: Collection<", elementType, ">) : ArrayList<", elementType, ">(elements)"], @@ -852,11 +842,11 @@ import com.fasterxml.jackson.module.kotlin.*`); this.emitBlock("companion object", () => { this.emitLine("fun fromJson(json: String) = mapper.readValue<", name, ">(json)"); }); - }, + } ); } - protected emitTopLevelMap (t: MapType, name: Name): void { + protected emitTopLevelMap(t: MapType, name: Name): void { const elementType = this.kotlinType(t.values); this.emitBlock( [ @@ -866,7 +856,7 @@ import com.fasterxml.jackson.module.kotlin.*`); elementType, ">) : HashMap(elements)", + ">(elements)" ], () => { this.emitLine("fun toJson() = mapper.writeValueAsString(this)"); @@ -874,15 +864,15 @@ import com.fasterxml.jackson.module.kotlin.*`); this.emitBlock("companion object", () => { this.emitLine("fun fromJson(json: String) = mapper.readValue<", name, ">(json)"); }); - }, + } ); } - private jacksonRenameAttribute ( + private jacksonRenameAttribute( propName: Name, jsonName: string, required: boolean, - ignore = false, + ignore = false ): Sourcelike | undefined { const escapedName = stringEscape(jsonName); const namesDiffer = this.sourcelikeToString(propName) !== escapedName; @@ -891,7 +881,7 @@ import com.fasterxml.jackson.module.kotlin.*`); const propertyOpts: Sourcelike[] = []; if (namesDiffer || isPrefixBool) { - propertyOpts.push("\"" + escapedName + "\""); + propertyOpts.push('"' + escapedName + '"'); } if (required) { @@ -911,13 +901,13 @@ import com.fasterxml.jackson.module.kotlin.*`); return properties.length === 0 ? undefined : properties; } - protected emitEmptyClassDefinition (c: ClassType, className: Name): void { + protected emitEmptyClassDefinition(c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); this.emitLine("typealias ", className, " = JsonNode"); } - protected emitClassDefinitionMethods (c: ClassType, className: Name) { + protected emitClassDefinitionMethods(c: ClassType, className: Name) { const isTopLevel = iterableSome(this.topLevels, ([_, top]) => top === c); if (isTopLevel) { this.emitBlock(")", () => { @@ -932,14 +922,14 @@ import com.fasterxml.jackson.module.kotlin.*`); } } - protected renameAttribute (name: Name, jsonName: string, required: boolean, meta: Array<() => void>) { + protected renameAttribute(name: Name, jsonName: string, required: boolean, meta: Array<() => void>) { const rename = this.jacksonRenameAttribute(name, jsonName, required); if (rename !== undefined) { meta.push(() => this.emitLine(rename)); } } - protected emitEnumDefinition (e: EnumType, enumName: Name): void { + protected emitEnumDefinition(e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); this.emitBlock(["enum class ", enumName, "(val value: String)"], () => { @@ -961,7 +951,7 @@ import com.fasterxml.jackson.module.kotlin.*`); }); } - private emitGenericConverter (): void { + private emitGenericConverter(): void { this.ensureBlankLine(); this.emitMultiline(` @Suppress("UNCHECKED_CAST") @@ -975,11 +965,11 @@ private fun ObjectMapper.convert(k: kotlin.reflect.KClass<*>, fromJson: (Jso })`); } - protected emitUnionDefinitionMethods ( + protected emitUnionDefinitionMethods( u: UnionType, nonNulls: ReadonlySet, maybeNull: PrimitiveType | null, - unionName: Name, + unionName: Name ) { this.ensureBlankLine(); this.emitLine("fun toJson(): String = mapper.writeValueAsString(when (this) {"); @@ -990,7 +980,7 @@ private fun ObjectMapper.convert(k: kotlin.reflect.KClass<*>, fromJson: (Jso }); if (maybeNull !== null) { const name = this.nameForUnionMember(u, maybeNull); - toJsonTable.push([["is ", name], [" -> \"null\""]]); + toJsonTable.push([["is ", name], [' -> "null"']]); } this.emitTable(toJsonTable); @@ -1022,19 +1012,19 @@ private fun ObjectMapper.convert(k: kotlin.reflect.KClass<*>, fromJson: (Jso * TODO: Union, Any, Top Level Array, Top Level Map */ export class KotlinXRenderer extends KotlinRenderer { - constructor ( + constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - _kotlinOptions: OptionValues, + _kotlinOptions: OptionValues ) { super(targetLanguage, renderContext, _kotlinOptions); } - protected anySourceType (optional: string): Sourcelike { + protected anySourceType(optional: string): Sourcelike { return ["JsonElement", optional]; } - protected arrayType (arrayType: ArrayType, withIssues = false, noOptional = false): Sourcelike { + protected arrayType(arrayType: ArrayType, withIssues = false, noOptional = false): Sourcelike { const valType = this.kotlinType(arrayType.items, withIssues, true); const name = this.sourcelikeToString(valType); if (name === "JsonObject" || name === "JsonElement") { @@ -1044,7 +1034,7 @@ export class KotlinXRenderer extends KotlinRenderer { return super.arrayType(arrayType, withIssues, noOptional); } - protected mapType (mapType: MapType, withIssues = false, noOptional = false): Sourcelike { + protected mapType(mapType: MapType, withIssues = false, noOptional = false): Sourcelike { const valType = this.kotlinType(mapType.values, withIssues, true); const name = this.sourcelikeToString(valType); if (name === "JsonObject" || name === "JsonElement") { @@ -1054,7 +1044,7 @@ export class KotlinXRenderer extends KotlinRenderer { return super.mapType(mapType, withIssues, noOptional); } - protected emitTopLevelMap (t: MapType, name: Name): void { + protected emitTopLevelMap(t: MapType, name: Name): void { const elementType = this.kotlinType(t.values); if (elementType === "JsonObject") { this.emitLine(["typealias ", name, " = JsonObject"]); @@ -1063,12 +1053,12 @@ export class KotlinXRenderer extends KotlinRenderer { } } - protected emitTopLevelArray (t: ArrayType, name: Name): void { + protected emitTopLevelArray(t: ArrayType, name: Name): void { const elementType = this.kotlinType(t.items); this.emitLine(["typealias ", name, " = JsonArray<", elementType, ">"]); } - protected emitUsageHeader (): void { + protected emitUsageHeader(): void { this.emitLine("// To parse the JSON, install kotlin's serialization plugin and do:"); this.emitLine("//"); const table: Sourcelike[][] = []; @@ -1077,13 +1067,13 @@ export class KotlinXRenderer extends KotlinRenderer { table.push([ "// val ", modifySource(camelCase, name), - ` = json.parse(${this.sourcelikeToString(name)}.serializer(), jsonString)`, + ` = json.parse(${this.sourcelikeToString(name)}.serializer(), jsonString)` ]); }); this.emitTable(table); } - protected emitHeader (): void { + protected emitHeader(): void { super.emitHeader(); this.emitLine("import kotlinx.serialization.*"); @@ -1092,28 +1082,28 @@ export class KotlinXRenderer extends KotlinRenderer { this.emitLine("import kotlinx.serialization.encoding.*"); } - protected emitClassAnnotations (_c: Type, _className: Name) { + protected emitClassAnnotations(_c: Type, _className: Name) { this.emitLine("@Serializable"); } - protected renameAttribute (name: Name, jsonName: string, _required: boolean, meta: Array<() => void>) { + protected renameAttribute(name: Name, jsonName: string, _required: boolean, meta: Array<() => void>) { const rename = this._rename(name, jsonName); if (rename !== undefined) { meta.push(() => this.emitLine(rename)); } } - private _rename (propName: Name, jsonName: string): Sourcelike | undefined { + private _rename(propName: Name, jsonName: string): Sourcelike | undefined { const escapedName = stringEscape(jsonName); const namesDiffer = this.sourcelikeToString(propName) !== escapedName; if (namesDiffer) { - return ["@SerialName(\"", escapedName, "\")"]; + return ['@SerialName("', escapedName, '")']; } return undefined; } - protected emitEnumDefinition (e: EnumType, enumName: Name): void { + protected emitEnumDefinition(e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); this.emitLine(["@Serializable"]); diff --git a/packages/quicktype-core/src/language/Rust.ts b/packages/quicktype-core/src/language/Rust.ts index b09b1dc7f..fe5941cdc 100644 --- a/packages/quicktype-core/src/language/Rust.ts +++ b/packages/quicktype-core/src/language/Rust.ts @@ -15,14 +15,14 @@ import { escapeNonPrintableMapper, isPrintable, isAscii, - isLetterOrUnderscore, + isLetterOrUnderscore } from "../support/Strings"; -import { type Name, type Namer} from "../Naming"; +import { type Name, type Namer } from "../Naming"; import { funPrefixNamer } from "../Naming"; import { type Type, type ClassType, type EnumType } from "../Type"; import { UnionType } from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { type Sourcelike} from "../Source"; +import { type Sourcelike } from "../Source"; import { maybeAnnotated } from "../Source"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; import { type Option, type OptionValues } from "../RendererOptions"; @@ -31,32 +31,32 @@ import { defined } from "../support/Support"; import { type RenderContext } from "../Renderer"; export enum Density { - Normal, - Dense + Normal = "Normal", + Dense = "Dense" } export enum Visibility { - Private, - Crate, - Public + Private = "Private", + Crate = "Crate", + Public = "Public" } export const rustOptions = { density: new EnumOption("density", "Density", [ ["normal", Density.Normal], - ["dense", Density.Dense], + ["dense", Density.Dense] ]), visibility: new EnumOption("visibility", "Field visibility", [ ["private", Visibility.Private], ["crate", Visibility.Crate], - ["public", Visibility.Public], + ["public", Visibility.Public] ]), deriveDebug: new BooleanOption("derive-debug", "Derive Debug impl", false), deriveClone: new BooleanOption("derive-clone", "Derive Clone impl", false), derivePartialEq: new BooleanOption("derive-partial-eq", "Derive PartialEq impl", false), skipSerializingNone: new BooleanOption("skip-serializing-none", "Skip serializing empty Option fields", false), edition2018: new BooleanOption("edition-2018", "Edition 2018", true), - leadingComments: new BooleanOption("leading-comments", "Leading Comments", true), + leadingComments: new BooleanOption("leading-comments", "Leading Comments", true) }; type NameToParts = (name: string) => string[]; @@ -71,12 +71,12 @@ const namingStyles: Record = { snake_case: { regex: /^[a-z][a-z0-9]*(_[a-z0-9]+)*$/, toParts: (name: string): string[] => name.split("_"), - fromParts: (parts: string[]): string => parts.map(p => p.toLowerCase()).join("_"), + fromParts: (parts: string[]): string => parts.map(p => p.toLowerCase()).join("_") }, SCREAMING_SNAKE_CASE: { regex: /^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$/, toParts: (name: string): string[] => name.split("_"), - fromParts: (parts: string[]): string => parts.map(p => p.toUpperCase()).join("_"), + fromParts: (parts: string[]): string => parts.map(p => p.toUpperCase()).join("_") }, camelCase: { regex: /^[a-z]+([A-Z0-9][a-z]*)*$/, @@ -84,48 +84,48 @@ const namingStyles: Record = { fromParts: (parts: string[]): string => parts .map((p, i) => - i === 0 ? p.toLowerCase() : p.substring(0, 1).toUpperCase() + p.substring(1).toLowerCase(), + i === 0 ? p.toLowerCase() : p.substring(0, 1).toUpperCase() + p.substring(1).toLowerCase() ) - .join(""), + .join("") }, PascalCase: { regex: /^[A-Z][a-z]*([A-Z0-9][a-z]*)*$/, toParts: (name: string): string[] => namingStyles.snake_case.toParts(name.replace(/(.)([A-Z])/g, "$1_$2")), fromParts: (parts: string[]): string => - parts.map(p => p.substring(0, 1).toUpperCase() + p.substring(1).toLowerCase()).join(""), + parts.map(p => p.substring(0, 1).toUpperCase() + p.substring(1).toLowerCase()).join("") }, "kebab-case": { regex: /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/, toParts: (name: string): string[] => name.split("-"), - fromParts: (parts: string[]): string => parts.map(p => p.toLowerCase()).join("-"), + fromParts: (parts: string[]): string => parts.map(p => p.toLowerCase()).join("-") }, "SCREAMING-KEBAB-CASE": { regex: /^[A-Z][A-Z0-9]*(-[A-Z0-9]+)*$/, toParts: (name: string): string[] => name.split("-"), - fromParts: (parts: string[]): string => parts.map(p => p.toUpperCase()).join("-"), + fromParts: (parts: string[]): string => parts.map(p => p.toUpperCase()).join("-") }, lowercase: { regex: /^[a-z][a-z0-9]*$/, toParts: (name: string): string[] => [name], - fromParts: (parts: string[]): string => parts.map(p => p.toLowerCase()).join(""), + fromParts: (parts: string[]): string => parts.map(p => p.toLowerCase()).join("") }, UPPERCASE: { regex: /^[A-Z][A-Z0-9]*$/, toParts: (name: string): string[] => [name], - fromParts: (parts: string[]): string => parts.map(p => p.toUpperCase()).join(""), - }, + fromParts: (parts: string[]): string => parts.map(p => p.toUpperCase()).join("") + } }; export class RustTargetLanguage extends TargetLanguage { - protected makeRenderer (renderContext: RenderContext, untypedOptionValues: { [name: string]: any, }): RustRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): RustRenderer { return new RustRenderer(this, renderContext, getOptionValues(rustOptions, untypedOptionValues)); } - constructor () { + constructor() { super("Rust", ["rust", "rs", "rustlang"], "rs"); } - protected getOptions (): Array> { + protected getOptions(): Array> { return [ rustOptions.density, rustOptions.visibility, @@ -134,7 +134,7 @@ export class RustTargetLanguage extends TargetLanguage { rustOptions.derivePartialEq, rustOptions.edition2018, rustOptions.leadingComments, - rustOptions.skipSerializingNone, + rustOptions.skipSerializingNone ]; } } @@ -213,7 +213,7 @@ const keywords = [ "union", // Conflict between `std::Option` and potentially generated Option - "option", + "option" ]; const isAsciiLetterOrUnderscoreOrDigit = (codePoint: number): boolean => { @@ -234,7 +234,7 @@ const isAsciiLetterOrUnderscore = (codePoint: number): boolean => { const legalizeName = legalizeCharacters(isAsciiLetterOrUnderscoreOrDigit); -function rustStyle (original: string, isSnakeCase: boolean): string { +function rustStyle(original: string, isSnakeCase: boolean): string { const words = splitIntoWords(original); const wordStyle = isSnakeCase ? allLowerWordStyle : firstUpperWordStyle; @@ -247,7 +247,7 @@ function rustStyle (original: string, isSnakeCase: boolean): string { wordStyle, wordStyle, isSnakeCase ? "_" : "", - isAsciiLetterOrUnderscore, + isAsciiLetterOrUnderscore ); return combined === "_" ? "_underscore" : combined; @@ -267,60 +267,60 @@ const standardUnicodeRustEscape = (codePoint: number): string => { const rustStringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, standardUnicodeRustEscape)); export class RustRenderer extends ConvenienceRenderer { - constructor ( + constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues, + private readonly _options: OptionValues ) { super(targetLanguage, renderContext); } - protected makeNamedTypeNamer (): Namer { + protected makeNamedTypeNamer(): Namer { return camelNamingFunction; } - protected namerForObjectProperty (): Namer | null { + protected namerForObjectProperty(): Namer | null { return snakeNamingFunction; } - protected makeUnionMemberNamer (): Namer | null { + protected makeUnionMemberNamer(): Namer | null { return camelNamingFunction; } - protected makeEnumCaseNamer (): Namer | null { + protected makeEnumCaseNamer(): Namer | null { return camelNamingFunction; } - protected forbiddenNamesForGlobalNamespace (): string[] { + protected forbiddenNamesForGlobalNamespace(): string[] { return keywords; } - protected forbiddenForObjectProperties (_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForUnionMembers (_u: UnionType, _unionName: Name): ForbiddenWordsInfo { + protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForEnumCases (_e: EnumType, _enumName: Name): ForbiddenWordsInfo { + protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected get commentLineStart (): string { + protected get commentLineStart(): string { return "/// "; } - private nullableRustType (t: Type, withIssues: boolean): Sourcelike { + private nullableRustType(t: Type, withIssues: boolean): Sourcelike { return ["Option<", this.breakCycle(t, withIssues), ">"]; } - protected isImplicitCycleBreaker (t: Type): boolean { + protected isImplicitCycleBreaker(t: Type): boolean { const kind = t.kind; return kind === "array" || kind === "map"; } - private rustType (t: Type, withIssues = false): Sourcelike { + private rustType(t: Type, withIssues = false): Sourcelike { return matchType( t, _anyType => maybeAnnotated(withIssues, anyTypeIssueAnnotation, "Option"), @@ -347,40 +347,40 @@ export class RustRenderer extends ConvenienceRenderer { : this.nameForNamedType(unionType); return hasNull !== null ? (["Option<", name, ">"] as Sourcelike) : name; - }, + } ); } - private breakCycle (t: Type, withIssues: boolean): any { + private breakCycle(t: Type, withIssues: boolean): any { const rustType = this.rustType(t, withIssues); const isCycleBreaker = this.isCycleBreakerType(t); return isCycleBreaker ? ["Box<", rustType, ">"] : rustType; } - private emitRenameAttribute ( + private emitRenameAttribute( propName: Name, jsonName: string, defaultNamingStyle: string, - preferedNamingStyle: string, + preferedNamingStyle: string ) { const escapedName = rustStringEscape(jsonName); const name = namingStyles[defaultNamingStyle].fromParts(this.sourcelikeToString(propName).split(" ")); const styledName = nameToNamingStyle(name, preferedNamingStyle); const namesDiffer = escapedName !== styledName; if (namesDiffer) { - this.emitLine("#[serde(rename = \"", escapedName, "\")]"); + this.emitLine('#[serde(rename = "', escapedName, '")]'); } } - private emitSkipSerializeNone (t: Type) { + private emitSkipSerializeNone(t: Type) { if (t instanceof UnionType) { const nullable = nullableFromUnion(t); - if (nullable !== null) this.emitLine("#[serde(skip_serializing_if = \"Option::is_none\")]"); + if (nullable !== null) this.emitLine('#[serde(skip_serializing_if = "Option::is_none")]'); } } - private get visibility (): string { + private get visibility(): string { if (this._options.visibility === Visibility.Crate) { return "pub(crate) "; } else if (this._options.visibility === Visibility.Public) { @@ -390,18 +390,18 @@ export class RustRenderer extends ConvenienceRenderer { return ""; } - protected emitStructDefinition (c: ClassType, className: Name): void { + protected emitStructDefinition(c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); this.emitLine( "#[derive(", this._options.deriveDebug ? "Debug, " : "", this._options.deriveClone ? "Clone, " : "", this._options.derivePartialEq ? "PartialEq, " : "", - "Serialize, Deserialize)]", + "Serialize, Deserialize)]" ); // List the possible naming styles for every class property - const propertiesNamingStyles: { [key: string]: string[], } = {}; + const propertiesNamingStyles: { [key: string]: string[] } = {}; this.forEachClassProperty(c, "none", (_name, jsonName, _prop) => { propertiesNamingStyles[jsonName] = listMatchingNamingStyles(jsonName); }); @@ -425,13 +425,13 @@ export class RustRenderer extends ConvenienceRenderer { this.emitBlock(["pub struct ", className], structBody); } - protected emitBlock (line: Sourcelike, f: () => void): void { + protected emitBlock(line: Sourcelike, f: () => void): void { this.emitLine(line, " {"); this.indent(f); this.emitLine("}"); } - protected emitUnion (u: UnionType, unionName: Name): void { + protected emitUnion(u: UnionType, unionName: Name): void { const isMaybeWithSingleType = nullableFromUnion(u); if (isMaybeWithSingleType !== null) { @@ -444,7 +444,7 @@ export class RustRenderer extends ConvenienceRenderer { this._options.deriveDebug ? "Debug, " : "", this._options.deriveClone ? "Clone, " : "", this._options.derivePartialEq ? "PartialEq, " : "", - "Serialize, Deserialize)]", + "Serialize, Deserialize)]" ); this.emitLine("#[serde(untagged)]"); @@ -455,22 +455,22 @@ export class RustRenderer extends ConvenienceRenderer { this.forEachUnionMember(u, nonNulls, blankLines, null, (fieldName, t) => { const rustType = this.breakCycle(t, true); this.emitLine([fieldName, "(", rustType, "),"]); - }), + }) ); } - protected emitEnumDefinition (e: EnumType, enumName: Name): void { + protected emitEnumDefinition(e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); this.emitLine( "#[derive(", this._options.deriveDebug ? "Debug, " : "", this._options.deriveClone ? "Clone, " : "", this._options.derivePartialEq ? "PartialEq, " : "", - "Serialize, Deserialize)]", + "Serialize, Deserialize)]" ); // List the possible naming styles for every enum case - const enumCasesNamingStyles: { [key: string]: string[], } = {}; + const enumCasesNamingStyles: { [key: string]: string[] } = {}; this.forEachEnumCase(e, "none", (_name, jsonName) => { enumCasesNamingStyles[jsonName] = listMatchingNamingStyles(jsonName); }); @@ -487,15 +487,15 @@ export class RustRenderer extends ConvenienceRenderer { this.forEachEnumCase(e, blankLines, (name, jsonName) => { this.emitRenameAttribute(name, jsonName, defaultStyle, preferedNamingStyle); this.emitLine([name, ","]); - }), + }) ); } - protected emitTopLevelAlias (t: Type, name: Name): void { + protected emitTopLevelAlias(t: Type, name: Name): void { this.emitLine("pub type ", name, " = ", this.rustType(t), ";"); } - protected emitLeadingComments (): void { + protected emitLeadingComments(): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); return; @@ -514,11 +514,11 @@ export class RustRenderer extends ConvenienceRenderer { // fn main() { // let json = r#"{"answer": 42}"#; // let model: ${topLevelName} = serde_json::from_str(&json).unwrap(); -// }`, +// }` ); } - protected emitSourceStructure (): void { + protected emitSourceStructure(): void { if (this._options.leadingComments) { this.emitLeadingComments(); } @@ -537,19 +537,19 @@ export class RustRenderer extends ConvenienceRenderer { this.forEachTopLevel( "leading", (t, name) => this.emitTopLevelAlias(t, name), - t => this.namedTypeToNameForTopLevel(t) === undefined, + t => this.namedTypeToNameForTopLevel(t) === undefined ); this.forEachNamedType( "leading-and-interposing", (c: ClassType, name: Name) => this.emitStructDefinition(c, name), (e, name) => this.emitEnumDefinition(e, name), - (u, name) => this.emitUnion(u, name), + (u, name) => this.emitUnion(u, name) ); } } -function getPreferedNamingStyle (namingStyleOccurences: string[], defaultStyle: string): string { +function getPreferedNamingStyle(namingStyleOccurences: string[], defaultStyle: string): string { const occurrences = Object.fromEntries(Object.keys(namingStyles).map(key => [key, 0])); namingStyleOccurences.forEach(style => ++occurrences[style]); const max = Math.max(...Object.values(occurrences)); @@ -563,13 +563,13 @@ function getPreferedNamingStyle (namingStyleOccurences: string[], defaultStyle: return preferedStyles[0]; } -function listMatchingNamingStyles (name: string): string[] { +function listMatchingNamingStyles(name: string): string[] { return Object.entries(namingStyles) .filter(([_, { regex }]) => regex.test(name)) .map(([namingStyle, _]) => namingStyle); } -function nameToNamingStyle (name: string, style: string): string { +function nameToNamingStyle(name: string, style: string): string { if (namingStyles[style].regex.test(name)) { return name; } diff --git a/packages/quicktype-core/src/language/Scala3.ts b/packages/quicktype-core/src/language/Scala3.ts index 3d93c0343..c173aed7c 100644 --- a/packages/quicktype-core/src/language/Scala3.ts +++ b/packages/quicktype-core/src/language/Scala3.ts @@ -1,11 +1,11 @@ import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Name, type Namer} from "../Naming"; +import { type Name, type Namer } from "../Naming"; import { funPrefixNamer } from "../Naming"; -import { type Option, type OptionValues} from "../RendererOptions"; +import { type Option, type OptionValues } from "../RendererOptions"; import { EnumOption, StringOption, getOptionValues } from "../RendererOptions"; -import { type Sourcelike} from "../Source"; +import { type Sourcelike } from "../Source"; import { maybeAnnotated } from "../Source"; import { allLowerWordStyle, @@ -16,7 +16,7 @@ import { isLetterOrUnderscore, isNumeric, legalizeCharacters, - splitIntoWords, + splitIntoWords } from "../support/Strings"; import { assertNever } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; @@ -26,9 +26,9 @@ import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils" import { type RenderContext } from "../Renderer"; export enum Framework { - None, - Upickle, - Circe + None = "None", + Upickle = "Upickle", + Circe = "Circe" } export const scala3Options = { @@ -38,11 +38,11 @@ export const scala3Options = { [ ["just-types", Framework.None], ["circe", Framework.Circe], - ["upickle", Framework.Upickle], + ["upickle", Framework.Upickle] ], - undefined, + undefined ), - packageName: new StringOption("package", "Package", "PACKAGE", "quicktype"), + packageName: new StringOption("package", "Package", "PACKAGE", "quicktype") }; // Use backticks for param names with symbols @@ -65,13 +65,13 @@ const invalidSymbols = [ "/", ";", "'", - "\"", + '"', "{", "}", ":", "~", "`", - ".", + "." ]; const keywords = [ @@ -130,7 +130,7 @@ const keywords = [ "Array", "List", "Map", - "Enum", + "Enum" ]; /** @@ -154,17 +154,17 @@ const wrapOption = (s: string, optional: boolean): string => { } }; -function isPartCharacter (codePoint: number): boolean { +function isPartCharacter(codePoint: number): boolean { return isLetterOrUnderscore(codePoint) || isNumeric(codePoint); } -function isStartCharacter (codePoint: number): boolean { +function isStartCharacter(codePoint: number): boolean { return isPartCharacter(codePoint) && !isDigit(codePoint); } const legalizeName = legalizeCharacters(isPartCharacter); -function scalaNameStyle (isUpper: boolean, original: string): string { +function scalaNameStyle(isUpper: boolean, original: string): string { const words = splitIntoWords(original); return combineWords( words, @@ -174,7 +174,7 @@ function scalaNameStyle (isUpper: boolean, original: string): string { isUpper ? allUpperWordStyle : allLowerWordStyle, allUpperWordStyle, "", - isStartCharacter, + isStartCharacter ); } @@ -193,87 +193,87 @@ const upperNamingFunction = funPrefixNamer("upper", s => scalaNameStyle(true, s) const lowerNamingFunction = funPrefixNamer("lower", s => scalaNameStyle(false, s)); export class Scala3Renderer extends ConvenienceRenderer { - constructor ( + constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - protected readonly _scalaOptions: OptionValues, + protected readonly _scalaOptions: OptionValues ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace (): string[] { + protected forbiddenNamesForGlobalNamespace(): string[] { return keywords; } - protected forbiddenForObjectProperties (_: ObjectType, _classNamed: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties(_: ObjectType, _classNamed: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForEnumCases (_: EnumType, _enumName: Name): ForbiddenWordsInfo { + protected forbiddenForEnumCases(_: EnumType, _enumName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForUnionMembers (_u: UnionType, _unionName: Name): ForbiddenWordsInfo { + protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: false }; } - protected topLevelNameStyle (rawName: string): string { + protected topLevelNameStyle(rawName: string): string { return scalaNameStyle(true, rawName); } - protected makeNamedTypeNamer (): Namer { + protected makeNamedTypeNamer(): Namer { return upperNamingFunction; } - protected namerForObjectProperty (): Namer { + protected namerForObjectProperty(): Namer { return lowerNamingFunction; } - protected makeUnionMemberNamer (): Namer { + protected makeUnionMemberNamer(): Namer { return funPrefixNamer("upper", s => scalaNameStyle(true, s) + "Value"); } - protected makeEnumCaseNamer (): Namer { + protected makeEnumCaseNamer(): Namer { return funPrefixNamer("upper", s => s.replace(" ", "")); // TODO - add backticks where appropriate } - protected emitDescriptionBlock (lines: Sourcelike[]): void { + protected emitDescriptionBlock(lines: Sourcelike[]): void { this.emitCommentLines(lines, { lineStart: " * ", beforeComment: "/**", afterComment: " */" }); } - protected emitBlock ( + protected emitBlock( line: Sourcelike, f: () => void, - delimiter: "curly" | "paren" | "lambda" | "none" = "curly", + delimiter: "curly" | "paren" | "lambda" | "none" = "curly" ): void { const [open, close] = delimiter === "curly" ? ["{", "}"] : delimiter === "paren" - ? ["(", ")"] - : delimiter === "none" - ? ["", ""] - : ["{", "})"]; + ? ["(", ")"] + : delimiter === "none" + ? ["", ""] + : ["{", "})"]; this.emitLine(line, " ", open); this.indent(f); this.emitLine(close); } - protected anySourceType (optional: boolean): Sourcelike { + protected anySourceType(optional: boolean): Sourcelike { return [wrapOption("Any", optional)]; } // (asarazan): I've broken out the following two functions // because some renderers, such as kotlinx, can cope with `any`, while some get mad. - protected arrayType (arrayType: ArrayType, withIssues = false): Sourcelike { + protected arrayType(arrayType: ArrayType, withIssues = false): Sourcelike { return ["Seq[", this.scalaType(arrayType.items, withIssues), "]"]; } - protected mapType (mapType: MapType, withIssues = false): Sourcelike { + protected mapType(mapType: MapType, withIssues = false): Sourcelike { return ["Map[String, ", this.scalaType(mapType.values, withIssues), "]"]; } - protected scalaType (t: Type, withIssues = false, noOptional = false): Sourcelike { + protected scalaType(t: Type, withIssues = false, noOptional = false): Sourcelike { return matchType( t, _anyType => { @@ -302,15 +302,15 @@ export class Scala3Renderer extends ConvenienceRenderer { } return this.nameForNamedType(unionType); - }, + } ); } - protected emitUsageHeader (): void { + protected emitUsageHeader(): void { // To be overridden } - protected emitHeader (): void { + protected emitHeader(): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } else { @@ -322,22 +322,22 @@ export class Scala3Renderer extends ConvenienceRenderer { this.ensureBlankLine(); } - protected emitTopLevelArray (t: ArrayType, name: Name): void { + protected emitTopLevelArray(t: ArrayType, name: Name): void { const elementType = this.scalaType(t.items); this.emitLine(["type ", name, " = List[", elementType, "]"]); } - protected emitTopLevelMap (t: MapType, name: Name): void { + protected emitTopLevelMap(t: MapType, name: Name): void { const elementType = this.scalaType(t.values); this.emitLine(["type ", name, " = Map[String, ", elementType, "]"]); } - protected emitEmptyClassDefinition (c: ClassType, className: Name): void { + protected emitEmptyClassDefinition(c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); this.emitLine("case class ", className, "()"); } - protected emitClassDefinition (c: ClassType, className: Name): void { + protected emitClassDefinition(c: ClassType, className: Name): void { if (c.getProperties().size === 0) { this.emitEmptyClassDefinition(c, className); return; @@ -383,7 +383,7 @@ export class Scala3Renderer extends ConvenienceRenderer { " : ", scalaType(p), p.isOptional ? " = None" : nullableOrOptional ? " = None" : "", - last ? "" : ",", + last ? "" : "," ); if (meta.length > 0 && !last) { @@ -397,11 +397,11 @@ export class Scala3Renderer extends ConvenienceRenderer { this.emitClassDefinitionMethods(); } - protected emitClassDefinitionMethods () { + protected emitClassDefinitionMethods() { this.emitLine(")"); } - protected emitEnumDefinition (e: EnumType, enumName: Name): void { + protected emitEnumDefinition(e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); this.emitBlock( @@ -433,12 +433,12 @@ export class Scala3Renderer extends ConvenienceRenderer { } }); }, - "none", + "none" ); } - protected emitUnionDefinition (u: UnionType, unionName: Name): void { - function sortBy (t: Type): string { + protected emitUnionDefinition(u: UnionType, unionName: Name): void { + function sortBy(t: Type): string { const kind = t.kind; if (kind === "class") return kind; return "_" + kind; @@ -462,7 +462,7 @@ export class Scala3Renderer extends ConvenienceRenderer { this.ensureBlankLine(); } - protected emitSourceStructure (): void { + protected emitSourceStructure(): void { this.emitHeader(); // Top-level arrays, maps @@ -478,17 +478,17 @@ export class Scala3Renderer extends ConvenienceRenderer { "leading-and-interposing", (c: ClassType, n: Name) => this.emitClassDefinition(c, n), (e, n) => this.emitEnumDefinition(e, n), - (u, n) => this.emitUnionDefinition(u, n), + (u, n) => this.emitUnionDefinition(u, n) ); } } export class UpickleRenderer extends Scala3Renderer { - protected emitClassDefinitionMethods () { + protected emitClassDefinitionMethods() { this.emitLine(") derives ReadWriter "); } - protected emitHeader (): void { + protected emitHeader(): void { super.emitHeader(); this.emitLine("import upickle.default.*"); @@ -497,7 +497,7 @@ export class UpickleRenderer extends Scala3Renderer { } export class Smithy4sRenderer extends Scala3Renderer { - protected emitHeader (): void { + protected emitHeader(): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } else { @@ -509,22 +509,22 @@ export class Smithy4sRenderer extends Scala3Renderer { this.ensureBlankLine(); } - protected emitTopLevelArray (t: ArrayType, name: Name): void { + protected emitTopLevelArray(t: ArrayType, name: Name): void { const elementType = this.scalaType(t.items); this.emitLine(["list ", name, " { member : ", elementType, "}"]); } - protected emitTopLevelMap (t: MapType, name: Name): void { + protected emitTopLevelMap(t: MapType, name: Name): void { const elementType = this.scalaType(t.values); this.emitLine(["map ", name, " { map[ key : String , value : ", elementType, "}"]); } - protected emitEmptyClassDefinition (c: ClassType, className: Name): void { + protected emitEmptyClassDefinition(c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); this.emitLine("structure ", className, "{}"); } - protected emitEnumDefinition (e: EnumType, enumName: Name): void { + protected emitEnumDefinition(e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); this.ensureBlankLine(); @@ -538,7 +538,7 @@ export class Smithy4sRenderer extends Scala3Renderer { !isNaN(parseInt(jsonName.charAt(0))) if (backticks) {this.emitItem("`")} else */ this.emitLine(); - this.emitItem([name, " = \"", jsonName, "\""]); + this.emitItem([name, ' = "', jsonName, '"']); // if (backticks) {this.emitItem("`")} if (--count > 0) this.emitItem([","]); // } else { @@ -553,7 +553,7 @@ export class Smithy4sRenderer extends Scala3Renderer { export class CirceRenderer extends Scala3Renderer { seenUnionTypes: string[] = []; - protected circeEncoderForType (t: Type, _ = false, noOptional = false, paramName: string = ""): Sourcelike { + protected circeEncoderForType(t: Type, _ = false, noOptional = false, paramName: string = ""): Sourcelike { return matchType( t, _anyType => ["Encoder.encodeJson(", paramName, ")"], @@ -577,25 +577,25 @@ export class CirceRenderer extends Scala3Renderer { } return ["Encoder.AsObject[", this.nameForNamedType(unionType), "]"]; - }, + } ); } - protected emitEmptyClassDefinition (c: ClassType, className: Name): void { + protected emitEmptyClassDefinition(c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); this.ensureBlankLine(); this.emitLine("case class ", className, "() derives Encoder.AsObject, Decoder"); } - protected anySourceType (optional: boolean): Sourcelike { + protected anySourceType(optional: boolean): Sourcelike { return [wrapOption("Json", optional)]; } - protected emitClassDefinitionMethods () { + protected emitClassDefinitionMethods() { this.emitLine(") derives Encoder.AsObject, Decoder"); } - protected emitEnumDefinition (e: EnumType, enumName: Name): void { + protected emitEnumDefinition(e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); this.ensureBlankLine(); @@ -608,7 +608,7 @@ export class CirceRenderer extends Scala3Renderer { jsonName.includes(" ") || !isNaN(parseInt(jsonName.charAt(0))) if (backticks) {this.emitItem("`")} else */ - this.emitItem(["\"", jsonName, "\""]); + this.emitItem(['"', jsonName, '"']); // if (backticks) {this.emitItem("`")} if (--count > 0) this.emitItem([" | "]); // } else { @@ -618,7 +618,7 @@ export class CirceRenderer extends Scala3Renderer { this.ensureBlankLine(); } - protected emitHeader (): void { + protected emitHeader(): void { super.emitHeader(); this.emitLine("import scala.util.Try"); @@ -629,17 +629,17 @@ export class CirceRenderer extends Scala3Renderer { this.emitLine("// For serialising string unions"); this.emitLine( - "given [A <: Singleton](using A <:< String): Decoder[A] = Decoder.decodeString.emapTry(x => Try(x.asInstanceOf[A])) ", + "given [A <: Singleton](using A <:< String): Decoder[A] = Decoder.decodeString.emapTry(x => Try(x.asInstanceOf[A])) " ); this.emitLine( - "given [A <: Singleton](using ev: A <:< String): Encoder[A] = Encoder.encodeString.contramap(ev) ", + "given [A <: Singleton](using ev: A <:< String): Encoder[A] = Encoder.encodeString.contramap(ev) " ); this.ensureBlankLine(); this.emitLine("// If a union has a null in, then we'll need this too... "); this.emitLine("type NullValue = None.type"); } - protected emitTopLevelArray (t: ArrayType, name: Name): void { + protected emitTopLevelArray(t: ArrayType, name: Name): void { super.emitTopLevelArray(t, name); const elementType = this.scalaType(t.items); this.emitLine([ @@ -649,11 +649,11 @@ export class CirceRenderer extends Scala3Renderer { elementType, "]] = Encoder.encodeMap[String, ", elementType, - "]", + "]" ]); } - protected emitTopLevelMap (t: MapType, name: Name): void { + protected emitTopLevelMap(t: MapType, name: Name): void { super.emitTopLevelMap(t, name); const elementType = this.scalaType(t.values); this.ensureBlankLine(); @@ -664,12 +664,12 @@ export class CirceRenderer extends Scala3Renderer { elementType, "]] = Encoder.encodeMap[String, ", elementType, - "]", + "]" ]); } - protected emitUnionDefinition (u: UnionType, unionName: Name): void { - function sortBy (t: Type): string { + protected emitUnionDefinition(u: UnionType, unionName: Name): void { + function sortBy(t: Type): string { const kind = t.kind; if (kind === "class") return kind; return "_" + kind; @@ -727,7 +727,7 @@ export class CirceRenderer extends Scala3Renderer { " : ", t[0], " => ", - this.circeEncoderForType(t[1], false, false, paramTemp), + this.circeEncoderForType(t[1], false, false, paramTemp) ]); }); }); @@ -737,25 +737,25 @@ export class CirceRenderer extends Scala3Renderer { } export class Scala3TargetLanguage extends TargetLanguage { - constructor () { + constructor() { super("Scala3", ["scala3"], "scala"); } - protected getOptions (): Array> { + protected getOptions(): Array> { return [scala3Options.framework, scala3Options.packageName]; } - get supportsOptionalClassProperties (): boolean { + get supportsOptionalClassProperties(): boolean { return true; } - get supportsUnionsWithBothNumberTypes (): boolean { + get supportsUnionsWithBothNumberTypes(): boolean { return true; } - protected makeRenderer ( + protected makeRenderer( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any, }, + untypedOptionValues: { [name: string]: any } ): ConvenienceRenderer { const options = getOptionValues(scala3Options, untypedOptionValues); diff --git a/packages/quicktype-core/src/language/Smithy4s.ts b/packages/quicktype-core/src/language/Smithy4s.ts index 8e794fbd5..816da3125 100644 --- a/packages/quicktype-core/src/language/Smithy4s.ts +++ b/packages/quicktype-core/src/language/Smithy4s.ts @@ -1,11 +1,11 @@ import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Name, type Namer} from "../Naming"; +import { type Name, type Namer } from "../Naming"; import { funPrefixNamer } from "../Naming"; -import { type Option, type OptionValues} from "../RendererOptions"; +import { type Option, type OptionValues } from "../RendererOptions"; import { EnumOption, StringOption, getOptionValues } from "../RendererOptions"; -import { type Sourcelike} from "../Source"; +import { type Sourcelike } from "../Source"; import { maybeAnnotated } from "../Source"; import { allLowerWordStyle, @@ -16,7 +16,7 @@ import { isLetterOrUnderscore, isNumeric, legalizeCharacters, - splitIntoWords, + splitIntoWords } from "../support/Strings"; import { assertNever } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; @@ -26,12 +26,12 @@ import { matchCompoundType, matchType, nullableFromUnion, removeNullFromUnion } import { type RenderContext } from "../Renderer"; export enum Framework { - None + None = "None" } export const SmithyOptions = { framework: new EnumOption("framework", "Serialization framework", [["just-types", Framework.None]], undefined), - packageName: new StringOption("package", "Package", "PACKAGE", "quicktype"), + packageName: new StringOption("package", "Package", "PACKAGE", "quicktype") }; // Use backticks for param names with symbols @@ -53,13 +53,13 @@ const invalidSymbols = [ "/", ";", "'", - "\"", + '"', "{", "}", ":", "~", "`", - ".", + "." ]; const keywords = [ @@ -109,7 +109,7 @@ const keywords = [ "Array", "List", "Map", - "Enum", + "Enum" ]; /** @@ -125,17 +125,17 @@ const shouldAddBacktick = (paramName: string): boolean => { ); }; -function isPartCharacter (codePoint: number): boolean { +function isPartCharacter(codePoint: number): boolean { return isLetterOrUnderscore(codePoint) || isNumeric(codePoint); } -function isStartCharacter (codePoint: number): boolean { +function isStartCharacter(codePoint: number): boolean { return isPartCharacter(codePoint) && !isDigit(codePoint); } const legalizeName = legalizeCharacters(isPartCharacter); -function scalaNameStyle (isUpper: boolean, original: string): string { +function scalaNameStyle(isUpper: boolean, original: string): string { const words = splitIntoWords(original); return combineWords( words, @@ -145,7 +145,7 @@ function scalaNameStyle (isUpper: boolean, original: string): string { isUpper ? allUpperWordStyle : allLowerWordStyle, allUpperWordStyle, "", - isStartCharacter, + isStartCharacter ); } @@ -153,93 +153,93 @@ const upperNamingFunction = funPrefixNamer("upper", s => scalaNameStyle(true, s) const lowerNamingFunction = funPrefixNamer("lower", s => scalaNameStyle(false, s)); export class Smithy4sRenderer extends ConvenienceRenderer { - constructor ( + constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - protected readonly _scalaOptions: OptionValues, + protected readonly _scalaOptions: OptionValues ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace (): string[] { + protected forbiddenNamesForGlobalNamespace(): string[] { return keywords; } - protected forbiddenForObjectProperties (_: ObjectType, _classNamed: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties(_: ObjectType, _classNamed: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForEnumCases (_: EnumType, _enumName: Name): ForbiddenWordsInfo { + protected forbiddenForEnumCases(_: EnumType, _enumName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForUnionMembers (_u: UnionType, _unionName: Name): ForbiddenWordsInfo { + protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: false }; } - protected topLevelNameStyle (rawName: string): string { + protected topLevelNameStyle(rawName: string): string { return scalaNameStyle(true, rawName); } - protected makeNamedTypeNamer (): Namer { + protected makeNamedTypeNamer(): Namer { return upperNamingFunction; } - protected namerForObjectProperty (): Namer { + protected namerForObjectProperty(): Namer { return lowerNamingFunction; } - protected makeUnionMemberNamer (): Namer { + protected makeUnionMemberNamer(): Namer { return funPrefixNamer("upper", s => scalaNameStyle(true, s) + "Value"); } - protected makeEnumCaseNamer (): Namer { + protected makeEnumCaseNamer(): Namer { return funPrefixNamer("upper", s => s.replace(" ", "")); // TODO - add backticks where appropriate } - protected emitDescriptionBlock (lines: Sourcelike[]): void { + protected emitDescriptionBlock(lines: Sourcelike[]): void { this.emitCommentLines(lines, { lineStart: " * ", beforeComment: "/**", afterComment: " */" }); } - protected emitBlock ( + protected emitBlock( line: Sourcelike, f: () => void, - delimiter: "curly" | "paren" | "lambda" | "none" = "curly", + delimiter: "curly" | "paren" | "lambda" | "none" = "curly" ): void { const [open, close] = delimiter === "curly" ? ["{", "}"] : delimiter === "paren" - ? ["(", ")"] - : delimiter === "none" - ? ["", ""] - : ["{", "})"]; + ? ["(", ")"] + : delimiter === "none" + ? ["", ""] + : ["{", "})"]; this.emitLine(line, " ", open); this.indent(f); this.emitLine(close); } - protected anySourceType (_: boolean): Sourcelike { + protected anySourceType(_: boolean): Sourcelike { return ["Document"]; } // (asarazan): I've broken out the following two functions // because some renderers, such as kotlinx, can cope with `any`, while some get mad. - protected arrayType (arrayType: ArrayType, _ = false): Sourcelike { + protected arrayType(arrayType: ArrayType, _ = false): Sourcelike { // this.emitTopLevelArray(arrayType, new Name(arrayType.getCombinedName().toString() + "List")) return arrayType.getCombinedName().toString() + "List"; } - protected emitArrayType (_: ArrayType, smithyType: Sourcelike): void { + protected emitArrayType(_: ArrayType, smithyType: Sourcelike): void { this.emitLine(["list ", smithyType, " { member : ", "}"]); } - protected mapType (mapType: MapType, _ = false): Sourcelike { + protected mapType(mapType: MapType, _ = false): Sourcelike { return mapType.getCombinedName().toString() + "Map"; // return [this.scalaType(mapType.values, withIssues), "Map"]; } - protected scalaType (t: Type, withIssues = false, noOptional = false): Sourcelike { + protected scalaType(t: Type, withIssues = false, noOptional = false): Sourcelike { return matchType( t, _anyType => { @@ -264,15 +264,15 @@ export class Smithy4sRenderer extends ConvenienceRenderer { } return this.nameForNamedType(unionType); - }, + } ); } - protected emitUsageHeader (): void { + protected emitUsageHeader(): void { // To be overridden } - protected emitHeader (): void { + protected emitHeader(): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } else { @@ -280,7 +280,7 @@ export class Smithy4sRenderer extends ConvenienceRenderer { } this.ensureBlankLine(); - this.emitLine("$version: \"2\""); + this.emitLine('$version: "2"'); this.emitLine("namespace ", this._scalaOptions.packageName); this.ensureBlankLine(); @@ -288,22 +288,22 @@ export class Smithy4sRenderer extends ConvenienceRenderer { this.ensureBlankLine(); } - protected emitTopLevelArray (t: ArrayType, name: Name): void { + protected emitTopLevelArray(t: ArrayType, name: Name): void { const elementType = this.scalaType(t.items); this.emitLine(["list ", name, " { member : ", elementType, "}"]); } - protected emitTopLevelMap (t: MapType, name: Name): void { + protected emitTopLevelMap(t: MapType, name: Name): void { const elementType = this.scalaType(t.values); this.emitLine(["map ", name, " { map[ key : String , value : ", elementType, "}"]); } - protected emitEmptyClassDefinition (c: ClassType, className: Name): void { + protected emitEmptyClassDefinition(c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); this.emitLine("structure ", className, "{}"); } - protected emitClassDefinition (c: ClassType, className: Name): void { + protected emitClassDefinition(c: ClassType, className: Name): void { if (c.getProperties().size === 0) { this.emitEmptyClassDefinition(c, className); return; @@ -357,7 +357,7 @@ export class Smithy4sRenderer extends ConvenienceRenderer { " : ", scalaType(p), - last ? "" : ",", + last ? "" : "," ); if (meta.length > 0 && !last) { @@ -370,10 +370,10 @@ export class Smithy4sRenderer extends ConvenienceRenderer { this.emitClassDefinitionMethods(emitLater); } - protected emitClassDefinitionMethods (arrayTypes: ClassProperty[]) { + protected emitClassDefinitionMethods(arrayTypes: ClassProperty[]) { this.emitLine("}"); arrayTypes.forEach(p => { - function ignore (_: T): void { + function ignore(_: T): void { return; } @@ -385,7 +385,7 @@ export class Smithy4sRenderer extends ConvenienceRenderer { this.scalaType(at, true), "{ member: ", this.scalaType(at.items, true), - "}", + "}" ]); }, ignore, @@ -395,16 +395,16 @@ export class Smithy4sRenderer extends ConvenienceRenderer { this.scalaType(mt, true), "{ key: String , value: ", this.scalaType(mt.values, true), - "}", + "}" ]); }, ignore, - ignore, + ignore ); }); } - protected emitEnumDefinition (e: EnumType, enumName: Name): void { + protected emitEnumDefinition(e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); this.ensureBlankLine(); @@ -420,7 +420,7 @@ export class Smithy4sRenderer extends ConvenienceRenderer { if (backticks) {this.emitItem("`")} else */ this.emitLine(); - this.emitItem([name, " = \"", jsonName, "\""]); + this.emitItem([name, ' = "', jsonName, '"']); // if (backticks) {this.emitItem("`")} if (--count > 0) this.emitItem([","]); @@ -433,8 +433,8 @@ export class Smithy4sRenderer extends ConvenienceRenderer { this.emitItem(["}"]); } - protected emitUnionDefinition (u: UnionType, unionName: Name): void { - function sortBy (t: Type): string { + protected emitUnionDefinition(u: UnionType, unionName: Name): void { + function sortBy(t: Type): string { const kind = t.kind; if (kind === "class") return kind; return "_" + kind; @@ -468,7 +468,7 @@ export class Smithy4sRenderer extends ConvenienceRenderer { this.ensureBlankLine(); emitLater.forEach(p => { - function ignore (_: T): void { + function ignore(_: T): void { return; } @@ -480,7 +480,7 @@ export class Smithy4sRenderer extends ConvenienceRenderer { this.scalaType(at, true), "{ member: ", this.scalaType(at.items, true), - "}", + "}" ]); }, ignore, @@ -490,16 +490,16 @@ export class Smithy4sRenderer extends ConvenienceRenderer { this.scalaType(mt, true), "{ key: String , value: ", this.scalaType(mt.values, true), - "}", + "}" ]); }, ignore, - ignore, + ignore ); }); } - protected emitSourceStructure (): void { + protected emitSourceStructure(): void { this.emitHeader(); // Top-level arrays, maps @@ -515,31 +515,31 @@ export class Smithy4sRenderer extends ConvenienceRenderer { "leading-and-interposing", (c: ClassType, n: Name) => this.emitClassDefinition(c, n), (e, n) => this.emitEnumDefinition(e, n), - (u, n) => this.emitUnionDefinition(u, n), + (u, n) => this.emitUnionDefinition(u, n) ); } } export class SmithyTargetLanguage extends TargetLanguage { - constructor () { + constructor() { super("Smithy", ["Smithy"], "smithy"); } - protected getOptions (): Array> { + protected getOptions(): Array> { return [SmithyOptions.framework, SmithyOptions.packageName]; } - get supportsOptionalClassProperties (): boolean { + get supportsOptionalClassProperties(): boolean { return true; } - get supportsUnionsWithBothNumberTypes (): boolean { + get supportsUnionsWithBothNumberTypes(): boolean { return true; } - protected makeRenderer ( + protected makeRenderer( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any, }, + untypedOptionValues: { [name: string]: any } ): ConvenienceRenderer { const options = getOptionValues(SmithyOptions, untypedOptionValues); From 885b35a903fdf80404e5de123b9c5b4e042aecf4 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Thu, 11 Apr 2024 09:09:00 -0700 Subject: [PATCH 31/94] add all missing accessibility modifiers fixup! add all missing accessibility modifiers fixup! add all missing accessibility modifiers --- packages/quicktype-core/src/Annotation.ts | 6 +- .../quicktype-core/src/ConvenienceRenderer.ts | 259 +++++------ packages/quicktype-core/src/CycleBreaker.ts | 9 +- packages/quicktype-core/src/DateTime.ts | 7 +- packages/quicktype-core/src/DeclarationIR.ts | 27 +- packages/quicktype-core/src/GatherNames.ts | 28 +- packages/quicktype-core/src/Graph.ts | 36 +- packages/quicktype-core/src/GraphRewriting.ts | 191 ++++---- .../quicktype-core/src/MakeTransformations.ts | 108 ++--- packages/quicktype-core/src/MarkovChain.ts | 26 +- packages/quicktype-core/src/Messages.ts | 143 +++--- packages/quicktype-core/src/Naming.ts | 122 ++--- packages/quicktype-core/src/Renderer.ts | 95 ++-- .../quicktype-core/src/RendererOptions.ts | 44 +- packages/quicktype-core/src/Run.ts | 161 ++++--- packages/quicktype-core/src/Source.ts | 50 +- packages/quicktype-core/src/TargetLanguage.ts | 40 +- packages/quicktype-core/src/Transformers.ts | 426 +++++++++-------- packages/quicktype-core/src/Type.ts | 302 ++++++------ packages/quicktype-core/src/TypeBuilder.ts | 187 ++++---- packages/quicktype-core/src/TypeGraph.ts | 161 +++---- packages/quicktype-core/src/TypeUtils.ts | 102 ++-- packages/quicktype-core/src/UnifyClasses.ts | 54 +-- packages/quicktype-core/src/UnionBuilder.ts | 97 ++-- .../src/attributes/AccessorNames.ts | 48 +- .../src/attributes/Constraints.ts | 54 +-- .../src/attributes/Description.ts | 32 +- .../src/attributes/EnumValues.ts | 12 +- .../src/attributes/StringTypes.ts | 58 +-- .../src/attributes/TypeAttributes.ts | 54 +-- .../src/attributes/TypeNames.ts | 94 ++-- .../src/attributes/URIAttributes.ts | 20 +- .../src/input/CompressedJSON.ts | 26 +- .../src/input/FetchingJSONSchemaStore.ts | 6 +- .../quicktype-core/src/input/Inference.ts | 66 ++- packages/quicktype-core/src/input/Inputs.ts | 61 +-- .../src/input/JSONSchemaInput.ts | 86 ++-- .../src/input/JSONSchemaStore.ts | 8 +- packages/quicktype-core/src/language/CJSON.ts | 8 +- .../quicktype-core/src/language/CPlusPlus.ts | 36 +- .../quicktype-core/src/language/CSharp.ts | 22 +- .../quicktype-core/src/language/Crystal.ts | 80 ++-- packages/quicktype-core/src/language/Dart.ts | 196 ++++---- packages/quicktype-core/src/language/Elm.ts | 136 +++--- .../quicktype-core/src/language/Golang.ts | 120 ++--- .../quicktype-core/src/language/Haskell.ts | 122 ++--- .../quicktype-core/src/language/JSONSchema.ts | 60 +-- packages/quicktype-core/src/language/Java.ts | 434 +++++++++--------- .../quicktype-core/src/language/JavaScript.ts | 140 +++--- .../src/language/JavaScriptPropTypes.ts | 91 ++-- .../src/language/JavaScriptUnicodeMaps.ts | 25 +- .../quicktype-core/src/language/Kotlin.ts | 14 +- .../src/language/Objective-C.ts | 225 ++++----- packages/quicktype-core/src/language/Php.ts | 222 ++++----- packages/quicktype-core/src/language/Pike.ts | 80 ++-- .../quicktype-core/src/language/Python.ts | 390 ++++++++-------- packages/quicktype-core/src/language/Rust.ts | 4 +- .../quicktype-core/src/language/Scala3.ts | 18 +- .../quicktype-core/src/language/Smithy4s.ts | 16 +- packages/quicktype-core/src/language/Swift.ts | 220 +++++---- .../src/language/TypeScriptEffectSchema.ts | 68 +-- .../src/language/TypeScriptFlow.ts | 128 +++--- .../src/language/TypeScriptZod.ts | 85 ++-- .../quicktype-core/src/language/ruby/index.ts | 126 ++--- .../src/rewrites/CombineClasses.ts | 28 +- .../src/rewrites/ExpandStrings.ts | 24 +- .../src/rewrites/FlattenStrings.ts | 16 +- .../src/rewrites/FlattenUnions.ts | 10 +- .../quicktype-core/src/rewrites/InferMaps.ts | 22 +- .../src/rewrites/ReplaceObjectType.ts | 16 +- .../src/rewrites/ResolveIntersections.ts | 93 ++-- packages/quicktype-core/src/support/Chance.ts | 61 +-- .../quicktype-core/src/support/Comments.ts | 6 +- .../quicktype-core/src/support/Converters.ts | 6 +- .../quicktype-core/src/support/Strings.ts | 188 ++++---- .../quicktype-core/src/support/Support.ts | 48 +- packages/quicktype-graphql-input/src/index.ts | 110 ++--- src/CompressedJSONFromStream.ts | 14 +- 78 files changed, 3540 insertions(+), 3474 deletions(-) diff --git a/packages/quicktype-core/src/Annotation.ts b/packages/quicktype-core/src/Annotation.ts index e6483462c..38cb82622 100644 --- a/packages/quicktype-core/src/Annotation.ts +++ b/packages/quicktype-core/src/Annotation.ts @@ -1,14 +1,14 @@ export class AnnotationData {} export class IssueAnnotationData extends AnnotationData { - constructor (readonly message: string) { + public constructor(public readonly message: string) { super(); } } export const anyTypeIssueAnnotation = new IssueAnnotationData( - "quicktype cannot infer this type because there is no data about it in the input.", + "quicktype cannot infer this type because there is no data about it in the input." ); export const nullTypeIssueAnnotation = new IssueAnnotationData( - "The only value for this in the input is null, which means you probably need a more complete input sample.", + "The only value for this in the input is null, which means you probably need a more complete input sample." ); diff --git a/packages/quicktype-core/src/ConvenienceRenderer.ts b/packages/quicktype-core/src/ConvenienceRenderer.ts index 175db7e3e..7fd2041db 100644 --- a/packages/quicktype-core/src/ConvenienceRenderer.ts +++ b/packages/quicktype-core/src/ConvenienceRenderer.ts @@ -6,19 +6,19 @@ import { mapFilter, mapSortBy, mapFilterMap, - mapSome, + mapSome } from "collection-utils"; -import { type Type, type TypeKind, type ClassProperty} from "./Type"; +import { type Type, type TypeKind, type ClassProperty } from "./Type"; import { ClassType, EnumType, UnionType, MapType, ObjectType } from "./Type"; import { separateNamedTypes, nullableFromUnion, matchTypeExhaustive, isNamedType } from "./TypeUtils"; -import { type Name, type Namer} from "./Naming"; +import { type Name, type Namer } from "./Naming"; import { Namespace, FixedName, SimpleName, DependencyName, keywordNamespace } from "./Naming"; import { type BlankLineConfig, type RenderContext, type ForEachPosition } from "./Renderer"; import { Renderer } from "./Renderer"; import { defined, panic, nonNull, assert } from "./support/Support"; import { trimEnd } from "./support/Strings"; -import { type Sourcelike} from "./Source"; +import { type Sourcelike } from "./Source"; import { sourcelikeToSource, serializeRenderResult } from "./Source"; import { type DeclarationIR, type Declaration } from "./DeclarationIR"; @@ -47,7 +47,7 @@ const assignedEnumCaseNameOrder = 10; const unionMemberNameOrder = 40; -function splitDescription (descriptions: Iterable | undefined): string[] | undefined { +function splitDescription(descriptions: Iterable | undefined): string[] | undefined { if (descriptions === undefined) return undefined; const description = Array.from(descriptions).join("\n\n").trim(); if (description === "") return undefined; @@ -57,7 +57,8 @@ function splitDescription (descriptions: Iterable | undefined): string[] } export interface ForbiddenWordsInfo { - includeGlobalForbidden: boolean; names: Array; + includeGlobalForbidden: boolean; + names: Array; } const assignedNameAttributeKind = new TypeAttributeKind("assignedName"); @@ -110,11 +111,11 @@ export abstract class ConvenienceRenderer extends Renderer { private _alphabetizeProperties = false; - constructor (targetLanguage: TargetLanguage, renderContext: RenderContext) { + public constructor(targetLanguage: TargetLanguage, renderContext: RenderContext) { super(targetLanguage, renderContext); } - get topLevels (): ReadonlyMap { + public get topLevels(): ReadonlyMap { return this.typeGraph.topLevels; } @@ -125,7 +126,7 @@ export abstract class ConvenienceRenderer extends Renderer { * that can conflict with that, such as reserved keywords or common type * names. */ - protected forbiddenNamesForGlobalNamespace (): string[] { + protected forbiddenNamesForGlobalNamespace(): string[] { return []; } @@ -139,37 +140,37 @@ export abstract class ConvenienceRenderer extends Renderer { * Note: That doesn't mean that the names in the global namespace will be * forbidden, too! */ - protected forbiddenForObjectProperties (_o: ObjectType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties(_o: ObjectType, _className: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: false }; } - protected forbiddenForUnionMembers (_u: UnionType, _unionName: Name): ForbiddenWordsInfo { + protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: false }; } - protected forbiddenForEnumCases (_e: EnumType, _enumName: Name): ForbiddenWordsInfo { + protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: false }; } - protected makeTopLevelDependencyNames (_t: Type, _topLevelName: Name): DependencyName[] { + protected makeTopLevelDependencyNames(_t: Type, _topLevelName: Name): DependencyName[] { return []; } - protected makeNamedTypeDependencyNames (_t: Type, _name: Name): DependencyName[] { + protected makeNamedTypeDependencyNames(_t: Type, _name: Name): DependencyName[] { return []; } - protected abstract makeNamedTypeNamer (): Namer; - protected abstract namerForObjectProperty (o: ObjectType, p: ClassProperty): Namer | null; - protected abstract makeUnionMemberNamer (): Namer | null; - protected abstract makeEnumCaseNamer (): Namer | null; - protected abstract emitSourceStructure (givenOutputFilename: string): void; + protected abstract makeNamedTypeNamer(): Namer; + protected abstract namerForObjectProperty(o: ObjectType, p: ClassProperty): Namer | null; + protected abstract makeUnionMemberNamer(): Namer | null; + protected abstract makeEnumCaseNamer(): Namer | null; + protected abstract emitSourceStructure(givenOutputFilename: string): void; - protected makeNameForTransformation (_xf: Transformation, _typeName: Name | undefined): Name | undefined { + protected makeNameForTransformation(_xf: Transformation, _typeName: Name | undefined): Name | undefined { return undefined; } - protected namedTypeToNameForTopLevel (type: Type): Type | undefined { + protected namedTypeToNameForTopLevel(type: Type): Type | undefined { if (isNamedType(type)) { return type; } @@ -177,58 +178,58 @@ export abstract class ConvenienceRenderer extends Renderer { return undefined; } - protected get unionMembersInGlobalNamespace (): boolean { + protected get unionMembersInGlobalNamespace(): boolean { return false; } - protected get enumCasesInGlobalNamespace (): boolean { + protected get enumCasesInGlobalNamespace(): boolean { return false; } - protected get needsTypeDeclarationBeforeUse (): boolean { + protected get needsTypeDeclarationBeforeUse(): boolean { return false; } - protected canBeForwardDeclared (_t: Type): boolean { + protected canBeForwardDeclared(_t: Type): boolean { return panic("If needsTypeDeclarationBeforeUse returns true, canBeForwardDeclared must be implemented"); } - protected unionNeedsName (u: UnionType): boolean { + protected unionNeedsName(u: UnionType): boolean { return nullableFromUnion(u) === null; } - private get globalNamespace (): Namespace { + private get globalNamespace(): Namespace { return defined(this._globalNamespace); } - private get nameStoreView (): TypeAttributeStoreView { + private get nameStoreView(): TypeAttributeStoreView { return defined(this._nameStoreView); } - protected descriptionForType (t: Type): string[] | undefined { + protected descriptionForType(t: Type): string[] | undefined { let description = this.typeGraph.attributeStore.tryGet(descriptionTypeAttributeKind, t); return splitDescription(description); } - protected descriptionForClassProperty (o: ObjectType, name: string): string[] | undefined { + protected descriptionForClassProperty(o: ObjectType, name: string): string[] | undefined { const descriptions = this.typeGraph.attributeStore.tryGet(propertyDescriptionsTypeAttributeKind, o); if (descriptions === undefined) return undefined; return splitDescription(descriptions.get(name)); } - protected setUpNaming (): ReadonlySet { + protected setUpNaming(): ReadonlySet { this._nameStoreView = new TypeAttributeStoreView(this.typeGraph.attributeStore, assignedNameAttributeKind); this._propertyNamesStoreView = new TypeAttributeStoreView( this.typeGraph.attributeStore, - assignedPropertyNamesAttributeKind, + assignedPropertyNamesAttributeKind ); this._memberNamesStoreView = new TypeAttributeStoreView( this.typeGraph.attributeStore, - assignedMemberNamesAttributeKind, + assignedMemberNamesAttributeKind ); this._caseNamesStoreView = new TypeAttributeStoreView( this.typeGraph.attributeStore, - assignedCaseNamesAttributeKind, + assignedCaseNamesAttributeKind ); this._namesForTransformations = new Map(); @@ -266,22 +267,22 @@ export abstract class ConvenienceRenderer extends Renderer { return setUnion( [this._globalForbiddenNamespace, this._globalNamespace], - this._otherForbiddenNamespaces.values(), + this._otherForbiddenNamespaces.values() ); } - private addDependenciesForNamedType (type: Type, named: Name): void { + private addDependenciesForNamedType(type: Type, named: Name): void { const dependencyNames = this.makeNamedTypeDependencyNames(type, named); for (const dn of dependencyNames) { this.globalNamespace.add(dn); } } - protected makeNameForTopLevel (_t: Type, givenName: string, _maybeNamedType: Type | undefined): Name { + protected makeNameForTopLevel(_t: Type, givenName: string, _maybeNamedType: Type | undefined): Name { return new SimpleName([givenName], defined(this._namedTypeNamer), topLevelNameOrder); } - private addNameForTopLevel (type: Type, givenName: string): Name { + private addNameForTopLevel(type: Type, givenName: string): Name { const maybeNamedType = this.namedTypeToNameForTopLevel(type); const name = this.makeNameForTopLevel(type, givenName, maybeNamedType); this.globalNamespace.add(name); @@ -298,17 +299,17 @@ export abstract class ConvenienceRenderer extends Renderer { return name; } - private makeNameForType (t: Type, namer: Namer, givenOrder: number, inferredOrder: number): Name { + private makeNameForType(t: Type, namer: Namer, givenOrder: number, inferredOrder: number): Name { const names = t.getNames(); const order = names.areInferred ? inferredOrder : givenOrder; return new SimpleName(names.proposedNames, namer, order); } - protected makeNameForNamedType (t: Type): Name { + protected makeNameForNamedType(t: Type): Name { return this.makeNameForType(t, defined(this._namedTypeNamer), givenNameOrder, inferredNameOrder); } - private addNameForNamedType (type: Type): Name { + private addNameForNamedType(type: Type): Name { const existing = this.nameStoreView.tryGet(type); if (existing !== undefined) return existing; @@ -320,11 +321,11 @@ export abstract class ConvenienceRenderer extends Renderer { return name; } - protected get typesWithNamedTransformations (): ReadonlyMap { + protected get typesWithNamedTransformations(): ReadonlyMap { return defined(this._namesForTransformations); } - protected nameForTransformation (t: Type): Name | undefined { + protected nameForTransformation(t: Type): Name | undefined { const xf = transformationForType(t); if (xf === undefined) return undefined; @@ -336,13 +337,13 @@ export abstract class ConvenienceRenderer extends Renderer { return name; } - private addNameForTransformation (t: Type): void { + private addNameForTransformation(t: Type): void { const xf = transformationForType(t); if (xf === undefined) return; assert( defined(this._namesForTransformations).get(t) === undefined, - "Tried to give two names to the same transformation", + "Tried to give two names to the same transformation" ); const name = this.makeNameForTransformation(xf, this.nameStoreView.tryGet(xf.targetType)); @@ -352,10 +353,10 @@ export abstract class ConvenienceRenderer extends Renderer { defined(this._namesForTransformations).set(t, name); } - private processForbiddenWordsInfo ( + private processForbiddenWordsInfo( info: ForbiddenWordsInfo, - namespaceName: string, - ): { forbiddenNames: ReadonlySet, forbiddenNamespaces: ReadonlySet, } { + namespaceName: string + ): { forbiddenNames: ReadonlySet; forbiddenNamespaces: ReadonlySet } { const forbiddenNames: Name[] = []; const forbiddenStrings: string[] = []; for (const nameOrString of info.names) { @@ -384,12 +385,12 @@ export abstract class ConvenienceRenderer extends Renderer { return { forbiddenNames: new Set(forbiddenNames), forbiddenNamespaces }; } - protected makeNameForProperty ( + protected makeNameForProperty( o: ObjectType, _className: Name, p: ClassProperty, jsonName: string, - assignedName: string | undefined, + assignedName: string | undefined ): Name | undefined { const namer = this.namerForObjectProperty(o, p); if (namer === null) return undefined; @@ -408,20 +409,20 @@ export abstract class ConvenienceRenderer extends Renderer { return new SimpleName(names, namer, order); } - protected makePropertyDependencyNames ( + protected makePropertyDependencyNames( _o: ObjectType, _className: Name, _p: ClassProperty, _jsonName: string, - _name: Name, + _name: Name ): Name[] { return []; } - private addPropertyNames (o: ObjectType, className: Name): void { + private addPropertyNames(o: ObjectType, className: Name): void { const { forbiddenNames, forbiddenNamespaces } = this.processForbiddenWordsInfo( this.forbiddenForObjectProperties(o, className), - "forbidden-for-properties", + "forbidden-for-properties" ); let ns: Namespace | undefined; @@ -451,7 +452,7 @@ export abstract class ConvenienceRenderer extends Renderer { defined(this._propertyNamesStoreView).set(o, names); } - protected makeNameForUnionMember (u: UnionType, unionName: Name, t: Type): Name { + protected makeNameForUnionMember(u: UnionType, unionName: Name, t: Type): Name { const [assignedName, isFixed] = unionMemberName(u, t, this.targetLanguage.name); if (isFixed) { return new FixedName(defined(assignedName)); @@ -463,13 +464,13 @@ export abstract class ConvenienceRenderer extends Renderer { }); } - private addUnionMemberNames (u: UnionType, unionName: Name): void { + private addUnionMemberNames(u: UnionType, unionName: Name): void { const memberNamer = this._unionMemberNamer; if (memberNamer === null) return; const { forbiddenNames, forbiddenNamespaces } = this.processForbiddenWordsInfo( this.forbiddenForUnionMembers(u, unionName), - "forbidden-for-union-members", + "forbidden-for-union-members" ); let ns: Namespace; @@ -488,11 +489,11 @@ export abstract class ConvenienceRenderer extends Renderer { defined(this._memberNamesStoreView).set(u, names); } - protected makeNameForEnumCase ( + protected makeNameForEnumCase( e: EnumType, _enumName: Name, caseName: string, - assignedName: string | undefined, + assignedName: string | undefined ): Name { // FIXME: See the FIXME in `makeNameForProperty`. We do have global // enum cases, though (in Go), so this is actually useful already. @@ -503,12 +504,12 @@ export abstract class ConvenienceRenderer extends Renderer { } // FIXME: this is very similar to addPropertyNameds and addUnionMemberNames - private addEnumCaseNames (e: EnumType, enumName: Name): void { + private addEnumCaseNames(e: EnumType, enumName: Name): void { if (this._enumCaseNamer === null) return; const { forbiddenNames, forbiddenNamespaces } = this.processForbiddenWordsInfo( this.forbiddenForEnumCases(e, enumName), - "forbidden-for-enum-cases", + "forbidden-for-enum-cases" ); let ns: Namespace; @@ -535,7 +536,7 @@ export abstract class ConvenienceRenderer extends Renderer { defined(this._caseNamesStoreView).set(e, names); } - private childrenOfType (t: Type): ReadonlySet { + private childrenOfType(t: Type): ReadonlySet { const names = this.names; if (t instanceof ClassType) { const propertyNameds = defined(this._propertyNamesStoreView).get(t); @@ -550,49 +551,49 @@ export abstract class ConvenienceRenderer extends Renderer { return t.getChildren(); } - protected get namedUnions (): ReadonlySet { + protected get namedUnions(): ReadonlySet { return defined(this._namedUnions); } - protected get haveNamedUnions (): boolean { + protected get haveNamedUnions(): boolean { return this.namedUnions.size > 0; } - protected get haveNamedTypes (): boolean { + protected get haveNamedTypes(): boolean { return defined(this._namedTypes).length > 0; } - protected get haveUnions (): boolean { + protected get haveUnions(): boolean { return defined(this._haveUnions); } - protected get haveMaps (): boolean { + protected get haveMaps(): boolean { return defined(this._haveMaps); } - protected get haveOptionalProperties (): boolean { + protected get haveOptionalProperties(): boolean { return defined(this._haveOptionalProperties); } // FIXME: Inconsistently named, though technically correct. Right now all enums are named, // but this should really be called `namedEnums`. - protected get enums (): ReadonlySet { + protected get enums(): ReadonlySet { return defined(this._namedEnums); } - protected get haveEnums (): boolean { + protected get haveEnums(): boolean { return this.enums.size > 0; } - protected proposedUnionMemberNameForTypeKind (_kind: TypeKind): string | null { + protected proposedUnionMemberNameForTypeKind(_kind: TypeKind): string | null { return null; } - protected proposeUnionMemberName ( + protected proposeUnionMemberName( _u: UnionType, _unionName: Name, fieldType: Type, - lookup: (n: Name) => string, + lookup: (n: Name) => string ): string { const simpleName = this.proposedUnionMemberNameForTypeKind(fieldType.kind); if (simpleName !== null) { @@ -617,50 +618,50 @@ export abstract class ConvenienceRenderer extends Renderer { objectType => { assert( this.targetLanguage.supportsFullObjectType, - "Object type should have been replaced in `replaceObjectType`", + "Object type should have been replaced in `replaceObjectType`" ); return lookup(this.nameForNamedType(objectType)); }, _enumType => "enum", _unionType => "union", - transformedType => transformedType.kind.replace("-", "_"), + transformedType => transformedType.kind.replace("-", "_") ); return typeNameForUnionMember(fieldType); } - protected nameForNamedType (t: Type): Name { + protected nameForNamedType(t: Type): Name { return this.nameStoreView.get(t); } - protected isForwardDeclaredType (t: Type): boolean { + protected isForwardDeclaredType(t: Type): boolean { return defined(this._declarationIR).forwardedTypes.has(t); } - protected isImplicitCycleBreaker (_t: Type): boolean { + protected isImplicitCycleBreaker(_t: Type): boolean { return panic("A renderer that invokes isCycleBreakerType must implement isImplicitCycleBreaker"); } - protected canBreakCycles (_t: Type): boolean { + protected canBreakCycles(_t: Type): boolean { return true; } - protected isCycleBreakerType (t: Type): boolean { + protected isCycleBreakerType(t: Type): boolean { if (this._cycleBreakerTypes === undefined) { this._cycleBreakerTypes = cycleBreakerTypesForGraph( this.typeGraph, s => this.isImplicitCycleBreaker(s), - s => this.canBreakCycles(s), + s => this.canBreakCycles(s) ); } return this._cycleBreakerTypes.has(t); } - protected forEachTopLevel ( + protected forEachTopLevel( blankLocations: BlankLineConfig, f: (t: Type, name: Name, position: ForEachPosition) => void, - predicate?: (t: Type) => boolean, + predicate?: (t: Type) => boolean ): boolean { let topLevels: ReadonlyMap; if (predicate !== undefined) { @@ -670,38 +671,38 @@ export abstract class ConvenienceRenderer extends Renderer { } return this.forEachWithBlankLines(topLevels, blankLocations, (t, name, pos) => - f(t, this.nameStoreView.getForTopLevel(name), pos), + f(t, this.nameStoreView.getForTopLevel(name), pos) ); } - protected forEachDeclaration ( + protected forEachDeclaration( blankLocations: BlankLineConfig, - f: (decl: Declaration, position: ForEachPosition) => void, + f: (decl: Declaration, position: ForEachPosition) => void ) { this.forEachWithBlankLines( iterableEnumerate(defined(this._declarationIR).declarations), blankLocations, - (decl, _, pos) => f(decl, pos), + (decl, _, pos) => f(decl, pos) ); } - setAlphabetizeProperties (value: boolean): void { + public setAlphabetizeProperties(value: boolean): void { this._alphabetizeProperties = value; } - protected getAlphabetizeProperties (): boolean { + protected getAlphabetizeProperties(): boolean { return this._alphabetizeProperties; } // Returns the number of properties defined for the specified object type. - protected propertyCount (o: ObjectType): number { + protected propertyCount(o: ObjectType): number { const propertyNames = defined(this._propertyNamesStoreView).get(o); return propertyNames.size; } - protected sortClassProperties ( + protected sortClassProperties( properties: ReadonlyMap, - propertyNames: ReadonlyMap, + propertyNames: ReadonlyMap ): ReadonlyMap { if (this._alphabetizeProperties) { return mapSortBy(properties, (_p: ClassProperty, jsonName: string) => { @@ -713,10 +714,10 @@ export abstract class ConvenienceRenderer extends Renderer { } } - protected forEachClassProperty ( + protected forEachClassProperty( o: ObjectType, blankLocations: BlankLineConfig, - f: (name: Name, jsonName: string, p: ClassProperty, position: ForEachPosition) => void, + f: (name: Name, jsonName: string, p: ClassProperty, position: ForEachPosition) => void ): void { const propertyNames = defined(this._propertyNamesStoreView).get(o); const sortedProperties = this.sortClassProperties(o.getProperties(), propertyNames); @@ -726,21 +727,21 @@ export abstract class ConvenienceRenderer extends Renderer { }); } - protected nameForUnionMember (u: UnionType, t: Type): Name { + protected nameForUnionMember(u: UnionType, t: Type): Name { return defined(defined(this._memberNamesStoreView).get(u).get(t)); } - protected nameForEnumCase (e: EnumType, caseName: string): Name { + protected nameForEnumCase(e: EnumType, caseName: string): Name { const caseNames = defined(this._caseNamesStoreView).get(e); return defined(caseNames.get(caseName)); } - protected forEachUnionMember ( + protected forEachUnionMember( u: UnionType, members: ReadonlySet | null, blankLocations: BlankLineConfig, sortOrder: ((n: Name, t: Type) => string) | null, - f: (name: Name, t: Type, position: ForEachPosition) => void, + f: (name: Name, t: Type, position: ForEachPosition) => void ): void { const iterateMembers = members === null ? u.members : members; if (sortOrder === null) { @@ -752,19 +753,19 @@ export abstract class ConvenienceRenderer extends Renderer { this.forEachWithBlankLines(sortedMemberNames, blankLocations, f); } - protected forEachEnumCase ( + protected forEachEnumCase( e: EnumType, blankLocations: BlankLineConfig, - f: (name: Name, jsonName: string, position: ForEachPosition) => void, + f: (name: Name, jsonName: string, position: ForEachPosition) => void ): void { const caseNames = defined(this._caseNamesStoreView).get(e); const sortedCaseNames = mapSortBy(caseNames, n => defined(this.names.get(n))); this.forEachWithBlankLines(sortedCaseNames, blankLocations, f); } - protected forEachTransformation ( + protected forEachTransformation( blankLocations: BlankLineConfig, - f: (n: Name, t: Type, position: ForEachPosition) => void, + f: (n: Name, t: Type, position: ForEachPosition) => void ): void { this.forEachWithBlankLines(defined(this._namesForTransformations), blankLocations, f); } @@ -772,31 +773,31 @@ export abstract class ConvenienceRenderer extends Renderer { protected forEachSpecificNamedType( blankLocations: BlankLineConfig, types: Iterable<[any, T]>, - f: (t: T, name: Name, position: ForEachPosition) => void, + f: (t: T, name: Name, position: ForEachPosition) => void ): void { this.forEachWithBlankLines(types, blankLocations, (t, _, pos) => f(t, this.nameForNamedType(t), pos)); } - protected forEachObject ( + protected forEachObject( blankLocations: BlankLineConfig, f: - | ((c: ClassType, className: Name, position: ForEachPosition) => void) - | ((o: ObjectType, objectName: Name, position: ForEachPosition) => void), + | ((c: ClassType, className: Name, position: ForEachPosition) => void) + | ((o: ObjectType, objectName: Name, position: ForEachPosition) => void) ): void { // FIXME: This is ugly. this.forEachSpecificNamedType(blankLocations, defined(this._namedObjects).entries(), f as any); } - protected forEachEnum ( + protected forEachEnum( blankLocations: BlankLineConfig, - f: (u: EnumType, enumName: Name, position: ForEachPosition) => void, + f: (u: EnumType, enumName: Name, position: ForEachPosition) => void ): void { this.forEachSpecificNamedType(blankLocations, this.enums.entries(), f); } - protected forEachUnion ( + protected forEachUnion( blankLocations: BlankLineConfig, - f: (u: UnionType, unionName: Name, position: ForEachPosition) => void, + f: (u: UnionType, unionName: Name, position: ForEachPosition) => void ): void { this.forEachSpecificNamedType(blankLocations, this.namedUnions.entries(), f); } @@ -804,7 +805,7 @@ export abstract class ConvenienceRenderer extends Renderer { protected forEachUniqueUnion( blankLocations: BlankLineConfig, uniqueValue: (u: UnionType) => T, - f: (firstUnion: UnionType, value: T, position: ForEachPosition) => void, + f: (firstUnion: UnionType, value: T, position: ForEachPosition) => void ): void { const firstUnionByValue = new Map(); for (const u of this.namedUnions) { @@ -817,13 +818,13 @@ export abstract class ConvenienceRenderer extends Renderer { this.forEachWithBlankLines(firstUnionByValue, blankLocations, f); } - protected forEachNamedType ( + protected forEachNamedType( blankLocations: BlankLineConfig, objectFunc: - | ((c: ClassType, className: Name, position: ForEachPosition) => void) - | ((o: ObjectType, objectName: Name, position: ForEachPosition) => void), + | ((c: ClassType, className: Name, position: ForEachPosition) => void) + | ((o: ObjectType, objectName: Name, position: ForEachPosition) => void), enumFunc: (e: EnumType, enumName: Name, position: ForEachPosition) => void, - unionFunc: (u: UnionType, unionName: Name, position: ForEachPosition) => void, + unionFunc: (u: UnionType, unionName: Name, position: ForEachPosition) => void ): void { this.forEachWithBlankLines(defined(this._namedTypes).entries(), blankLocations, (t, _, pos) => { const name = this.nameForNamedType(t); @@ -844,15 +845,15 @@ export abstract class ConvenienceRenderer extends Renderer { // You should never have to use this to produce parts of your generated // code. If you need to modify a Name, for example to change its casing, // use `modifySource`. - protected sourcelikeToString (src: Sourcelike): string { + protected sourcelikeToString(src: Sourcelike): string { return serializeRenderResult(sourcelikeToSource(src), this.names, "").lines.join("\n"); } - protected get commentLineStart (): string { + protected get commentLineStart(): string { return "// "; } - protected emitComments (comments: Comment[]): void { + protected emitComments(comments: Comment[]): void { comments.forEach(comment => { if (isStringComment(comment)) { this.emitCommentLines([comment]); @@ -868,15 +869,15 @@ export abstract class ConvenienceRenderer extends Renderer { }); } - protected emitCommentLines ( + protected emitCommentLines( lines: Sourcelike[], { lineStart = this.commentLineStart, firstLineStart = lineStart, lineEnd, beforeComment, - afterComment, - }: CommentOptions = {}, + afterComment + }: CommentOptions = {} ): void { if (beforeComment !== undefined) { this.emitLine(beforeComment); @@ -903,19 +904,19 @@ export abstract class ConvenienceRenderer extends Renderer { } } - protected emitDescription (description: Sourcelike[] | undefined): void { + protected emitDescription(description: Sourcelike[] | undefined): void { if (description === undefined) return; // FIXME: word-wrap this.emitDescriptionBlock(description); } - protected emitDescriptionBlock (lines: Sourcelike[]): void { + protected emitDescriptionBlock(lines: Sourcelike[]): void { this.emitCommentLines(lines); } - protected emitPropertyTable ( + protected emitPropertyTable( c: ClassType, - makePropertyRow: (name: Name, jsonName: string, p: ClassProperty) => Sourcelike[], + makePropertyRow: (name: Name, jsonName: string, p: ClassProperty) => Sourcelike[] ): void { let table: Sourcelike[][] = []; const emitTable = () => { @@ -936,7 +937,7 @@ export abstract class ConvenienceRenderer extends Renderer { emitTable(); } - private processGraph (): void { + private processGraph(): void { this._declarationIR = declarationsForGraph( this.typeGraph, this.needsTypeDeclarationBeforeUse ? t => this.canBeForwardDeclared(t) : undefined, @@ -947,7 +948,7 @@ export abstract class ConvenienceRenderer extends Renderer { } return isNamedType(t); - }, + } ); const types = this.typeGraph.allTypesUnordered(); @@ -962,7 +963,7 @@ export abstract class ConvenienceRenderer extends Renderer { this._namedUnions = new Set(unions); } - protected emitSource (givenOutputFilename: string): void { + protected emitSource(givenOutputFilename: string): void { this.processGraph(); this.emitSourceStructure(givenOutputFilename); } @@ -972,7 +973,7 @@ export abstract class ConvenienceRenderer extends Renderer { const processed = new Set(); const queue = Array.from(this.typeGraph.topLevels.values()); - function visit (t: Type) { + function visit(t: Type) { if (visitedTypes.has(t)) return; for (const c of t.getChildren()) { queue.push(c); diff --git a/packages/quicktype-core/src/CycleBreaker.ts b/packages/quicktype-core/src/CycleBreaker.ts index 586ae8f49..9497d9140 100644 --- a/packages/quicktype-core/src/CycleBreaker.ts +++ b/packages/quicktype-core/src/CycleBreaker.ts @@ -1,6 +1,9 @@ import { assert, panic } from "./support/Support"; -export function breakCycles (outEdges: number[][], chooseBreaker: (cycle: number[]) => [number, T]): Array<[number, T]> { +export function breakCycles( + outEdges: number[][], + chooseBreaker: (cycle: number[]) => [number, T] +): Array<[number, T]> { const numNodes = outEdges.length; const inEdges: number[][] = []; const inDegree: number[] = []; @@ -28,7 +31,7 @@ export function breakCycles (outEdges: number[][], chooseBreaker: (cycle: num } } - function removeNode (node: number): void { + function removeNode(node: number): void { for (const n of outEdges[node]) { assert(inDegree[n] > 0); inDegree[n] -= 1; @@ -51,7 +54,7 @@ export function breakCycles (outEdges: number[][], chooseBreaker: (cycle: num for (;;) { const i = workList.pop(); if (i !== undefined) { - if (done[i] || inDegree[i] === 0 && outDegree[i] === 0) { + if (done[i] || (inDegree[i] === 0 && outDegree[i] === 0)) { done[i] = true; continue; } diff --git a/packages/quicktype-core/src/DateTime.ts b/packages/quicktype-core/src/DateTime.ts index 899daa704..9f2bc4ae8 100644 --- a/packages/quicktype-core/src/DateTime.ts +++ b/packages/quicktype-core/src/DateTime.ts @@ -1,3 +1,4 @@ +/* eslint-disable */ // https://github.com/epoberezkin/ajv/blob/4d76c6fb813b136b6ec4fe74990bc97233d75dea/lib/compile/formats.js /* @@ -37,7 +38,7 @@ export interface DateTimeRecognizer { const DATE_TIME_SEPARATOR = /t|\s/i; export class DefaultDateTimeRecognizer implements DateTimeRecognizer { - isDate (str: string) { + isDate(str: string) { // full-date from http://tools.ietf.org/html/rfc3339#section-5.6 const matches = DATE.exec(str); if (matches === null) return false; @@ -47,7 +48,7 @@ export class DefaultDateTimeRecognizer implements DateTimeRecognizer { return month >= 1 && month <= 12 && day >= 1 && day <= DAYS[month]; } - isTime (str: string): boolean { + isTime(str: string): boolean { const matches = TIME.exec(str); if (matches === null) return false; @@ -57,7 +58,7 @@ export class DefaultDateTimeRecognizer implements DateTimeRecognizer { return hour <= 23 && minute <= 59 && second <= 59; } - isDateTime (str: string): boolean { + isDateTime(str: string): boolean { // http://tools.ietf.org/html/rfc3339#section-5.6 const dateTime = str.split(DATE_TIME_SEPARATOR); return dateTime.length === 2 && this.isDate(dateTime[0]) && this.isTime(dateTime[1]); diff --git a/packages/quicktype-core/src/DeclarationIR.ts b/packages/quicktype-core/src/DeclarationIR.ts index 2a42f716f..47d53d2de 100644 --- a/packages/quicktype-core/src/DeclarationIR.ts +++ b/packages/quicktype-core/src/DeclarationIR.ts @@ -14,18 +14,17 @@ export interface Declaration { } export class DeclarationIR { - readonly declarations: readonly Declaration[]; + public readonly declarations: readonly Declaration[]; - constructor (declarations: Iterable, readonly forwardedTypes: Set) { + public constructor( + declarations: Iterable, + public readonly forwardedTypes: Set + ) { this.declarations = Array.from(declarations); } } -function findBreaker ( - t: Type, - path: readonly Type[], - canBreak: ((t: Type) => boolean) | undefined, -): Type | undefined { +function findBreaker(t: Type, path: readonly Type[], canBreak: ((t: Type) => boolean) | undefined): Type | undefined { const index = path.indexOf(t); if (index < 0) return undefined; if (canBreak === undefined) { @@ -41,16 +40,16 @@ function findBreaker ( return maybeBreaker; } -export function cycleBreakerTypesForGraph ( +export function cycleBreakerTypesForGraph( graph: TypeGraph, isImplicitCycleBreaker: (t: Type) => boolean, - canBreakCycles: (t: Type) => boolean, + canBreakCycles: (t: Type) => boolean ): Set { const visitedTypes = new Set(); const cycleBreakerTypes = new Set(); const queue: Type[] = Array.from(graph.topLevels.values()); - function visit (t: Type, path: Type[]): void { + function visit(t: Type, path: Type[]): void { if (visitedTypes.has(t)) return; if (isImplicitCycleBreaker(t)) { @@ -85,11 +84,11 @@ export function cycleBreakerTypesForGraph ( return cycleBreakerTypes; } -export function declarationsForGraph ( +export function declarationsForGraph( typeGraph: TypeGraph, canBeForwardDeclared: ((t: Type) => boolean) | undefined, childrenOfType: (t: Type) => ReadonlySet, - needsDeclaration: (t: Type) => boolean, + needsDeclaration: (t: Type) => boolean ): DeclarationIR { /* function nodeTitle(t: Type): string { @@ -110,9 +109,9 @@ export function declarationsForGraph ( const forwardedTypes = new Set(); const visitedComponents = new Set>(); - function processGraph (graph: Graph, _writeComponents: boolean): void { + function processGraph(graph: Graph, _writeComponents: boolean): void { const componentsGraph = graph.stronglyConnectedComponents(); - function visitComponent (component: ReadonlySet): void { + function visitComponent(component: ReadonlySet): void { if (visitedComponents.has(component)) return; visitedComponents.add(component); diff --git a/packages/quicktype-core/src/GatherNames.ts b/packages/quicktype-core/src/GatherNames.ts index 85bbeb5ca..e5b7d3b86 100644 --- a/packages/quicktype-core/src/GatherNames.ts +++ b/packages/quicktype-core/src/GatherNames.ts @@ -2,7 +2,7 @@ import * as pluralize from "pluralize"; import { setUnion, setMap, setSortBy } from "collection-utils"; import { type TypeGraph } from "./TypeGraph"; -import { type Type} from "./Type"; +import { type Type } from "./Type"; import { ObjectType } from "./Type"; import { matchCompoundType, nullableFromUnion } from "./TypeUtils"; import { TypeNames, namesTypeAttributeKind, TooManyTypeNames, tooManyNamesThreshold } from "./attributes/TypeNames"; @@ -16,21 +16,21 @@ class UniqueQueue { private _front = 0; - get size (): number { + public get size(): number { return this._queue.length - this._front; } - get isEmpty (): boolean { + public get isEmpty(): boolean { return this.size <= 0; } - push (v: T): void { + public push(v: T): void { if (this._present.has(v)) return; this._queue.push(v); this._present.add(v); } - unshift (): T { + public unshift(): T { assert(!this.isEmpty, "Trying to unshift from an empty queue"); const v = this._queue[this._front]; if (v === undefined) { @@ -86,8 +86,8 @@ class UniqueQueue { // step 1, and its alternatives to a union of its direct and ancestor // alternatives, gathered in steps 2 and 3. -export function gatherNames (graph: TypeGraph, destructive: boolean, debugPrint: boolean): void { - function setNames (t: Type, tn: TypeNames): void { +export function gatherNames(graph: TypeGraph, destructive: boolean, debugPrint: boolean): void { + function setNames(t: Type, tn: TypeNames): void { graph.attributeStore.set(namesTypeAttributeKind, t, tn); } @@ -103,7 +103,7 @@ export function gatherNames (graph: TypeGraph, destructive: boolean, debugPrint: // null means there are too many const namesForType = new Map | null>(); - function addNames (t: Type, names: ReadonlySet | null) { + function addNames(t: Type, names: ReadonlySet | null) { // Always use the type's given names if it has some if (t.hasNames) { const originalNames = t.getNames(); @@ -178,7 +178,7 @@ export function gatherNames (graph: TypeGraph, destructive: boolean, debugPrint: for (const memberType of members) { addNames(memberType, names); } - }, + } ); } } @@ -198,9 +198,9 @@ export function gatherNames (graph: TypeGraph, destructive: boolean, debugPrint: const ancestorAlternativesForType = new Map | null>(); const pairsProcessed = new Map>(); - function addAlternatives ( + function addAlternatives( existing: ReadonlySet | undefined, - alternatives: string[], + alternatives: string[] ): ReadonlySet | undefined | null { if (alternatives.length === 0) { return existing; @@ -218,7 +218,7 @@ export function gatherNames (graph: TypeGraph, destructive: boolean, debugPrint: return null; } - function processType (ancestor: Type | undefined, t: Type, alternativeSuffix: string | undefined) { + function processType(ancestor: Type | undefined, t: Type, alternativeSuffix: string | undefined) { const names = defined(namesForType.get(t)); let processedEntry = pairsProcessed.get(ancestor); @@ -302,7 +302,7 @@ export function gatherNames (graph: TypeGraph, destructive: boolean, debugPrint: for (const memberType of members) { processType(ancestorForMembers, memberType, undefined); } - }, + } ); } } @@ -327,7 +327,7 @@ export function gatherNames (graph: TypeGraph, destructive: boolean, debugPrint: alternatives = setUnion( alternatives, - setMap(names, name => `${name}_${t.kind}`), + setMap(names, name => `${name}_${t.kind}`) ); directAlternativesForType.set(t, alternatives); } diff --git a/packages/quicktype-core/src/Graph.ts b/packages/quicktype-core/src/Graph.ts index 5bcf6ba87..c54e3ed05 100644 --- a/packages/quicktype-core/src/Graph.ts +++ b/packages/quicktype-core/src/Graph.ts @@ -2,7 +2,7 @@ import { setMap } from "collection-utils"; import { defined, repeated, assert, repeatedCall } from "./support/Support"; -function countComponentGraphNodes (components: number[][]): number { +function countComponentGraphNodes(components: number[][]): number { if (components.length === 0) return 0; let largest = -1; @@ -22,7 +22,7 @@ function countComponentGraphNodes (components: number[][]): number { } // https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm -function stronglyConnectedComponents (successors: number[][]): number[][] { +function stronglyConnectedComponents(successors: number[][]): number[][] { let index = 0; const stack: number[] = []; const numNodes = successors.length; @@ -31,7 +31,7 @@ function stronglyConnectedComponents (successors: number[][]): number[][] { const onStack: boolean[] = repeated(numNodes, false); const sccs: number[][] = []; - function strongconnect (v: number): void { + function strongconnect(v: number): void { // Set the depth index for v to the smallest unused index indexes[v] = index; lowLinks[v] = index; @@ -80,7 +80,7 @@ function stronglyConnectedComponents (successors: number[][]): number[][] { return sccs; } -function buildComponentOfNodeMap (successors: number[][], components: number[][]): number[] { +function buildComponentOfNodeMap(successors: number[][], components: number[][]): number[] { const numComponents = components.length; const numNodes = successors.length; @@ -97,7 +97,7 @@ function buildComponentOfNodeMap (successors: number[][], components: number[][] return componentOfNode; } -function buildMetaSuccessors (successors: number[][], components: number[][]): number[][] { +function buildMetaSuccessors(successors: number[][], components: number[][]): number[][] { const numComponents = components.length; const componentOfNode = buildComponentOfNodeMap(successors, components); const componentAdded: boolean[] = repeated(numComponents, false); @@ -127,7 +127,7 @@ function buildMetaSuccessors (successors: number[][], components: number[][]): n return metaSuccessors; } -function invertEdges (successors: number[][]): number[][] { +function invertEdges(successors: number[][]): number[][] { const numNodes = successors.length; const predecessors: number[][] = repeatedCall(numNodes, () => []); @@ -140,7 +140,7 @@ function invertEdges (successors: number[][]): number[][] { return predecessors; } -function calculateInDegrees (successors: number[][]): number[] { +function calculateInDegrees(successors: number[][]): number[] { const numNodes = successors.length; const inDegrees: number[] = repeated(numNodes, 0); @@ -153,7 +153,7 @@ function calculateInDegrees (successors: number[][]): number[] { return inDegrees; } -function findRoots (successors: number[][]): number[] { +function findRoots(successors: number[][]): number[] { const numNodes = successors.length; const inDegrees = calculateInDegrees(successors); const roots: number[] = []; @@ -174,7 +174,11 @@ export class Graph { private readonly _successors: number[][]; - constructor (nodes: Iterable, invertDirection: boolean, edges: number[][] | ((node: T) => ReadonlySet)) { + public constructor( + nodes: Iterable, + invertDirection: boolean, + edges: number[][] | ((node: T) => ReadonlySet) + ) { this._nodes = Array.from(nodes); this._indexByNode = new Map(this._nodes.map((n, i): [T, number] => [n, i])); let edgesArray: number[][]; @@ -191,21 +195,21 @@ export class Graph { this._successors = edgesArray; } - get size (): number { + public get size(): number { return this._nodes.length; } - get nodes (): readonly T[] { + public get nodes(): readonly T[] { return this._nodes; } - findRoots (): ReadonlySet { + public findRoots(): ReadonlySet { const roots = findRoots(this._successors); return new Set(roots.map(n => this._nodes[n])); } // The subgraph starting at `root` must be acyclic. - dfsTraversal (root: T, preOrder: boolean, process: (node: T) => void): void { + public dfsTraversal(root: T, preOrder: boolean, process: (node: T) => void): void { const visited = repeated(this.size, false); const visit = (v: number): void => { @@ -228,17 +232,17 @@ export class Graph { visit(defined(this._indexByNode.get(root))); } - stronglyConnectedComponents (): Graph> { + public stronglyConnectedComponents(): Graph> { const components = stronglyConnectedComponents(this._successors); const componentSuccessors = buildMetaSuccessors(this._successors, components); return new Graph( components.map(ns => setMap(ns, n => this._nodes[n])), false, - componentSuccessors, + componentSuccessors ); } - makeDot (includeNode: (n: T) => boolean, nodeLabel: (n: T) => string): string { + public makeDot(includeNode: (n: T) => boolean, nodeLabel: (n: T) => string): string { const lines: string[] = []; lines.push("digraph G {"); lines.push(" ordering = out;"); diff --git a/packages/quicktype-core/src/GraphRewriting.ts b/packages/quicktype-core/src/GraphRewriting.ts index e4c099fee..e60360890 100644 --- a/packages/quicktype-core/src/GraphRewriting.ts +++ b/packages/quicktype-core/src/GraphRewriting.ts @@ -2,17 +2,9 @@ import { mapMap, EqualityMap } from "collection-utils"; import { type PrimitiveTypeKind, type Type, type ClassProperty, type MaybeTypeIdentity } from "./Type"; import { combineTypeAttributesOfTypes } from "./TypeUtils"; -import { - type TypeGraph, - type TypeRef} from "./TypeGraph"; -import { - derefTypeRef, - typeAndAttributesForTypeRef, - assertTypeRefGraph, - typeRefIndex, - isTypeRef, -} from "./TypeGraph"; -import { type TypeAttributes} from "./attributes/TypeAttributes"; +import { type TypeGraph, type TypeRef } from "./TypeGraph"; +import { derefTypeRef, typeAndAttributesForTypeRef, assertTypeRefGraph, typeRefIndex, isTypeRef } from "./TypeGraph"; +import { type TypeAttributes } from "./attributes/TypeAttributes"; import { emptyTypeAttributes, combineTypeAttributes } from "./attributes/TypeAttributes"; import { assert, panic, indentationString } from "./support/Support"; import { type StringTypeMapping } from "./TypeBuilder"; @@ -28,26 +20,26 @@ export class TypeReconstituter { private _typeRef: TypeRef | undefined = undefined; - constructor ( + public constructor( private readonly _typeBuilder: TBuilder, private readonly _makeClassUnique: boolean, private readonly _typeAttributes: TypeAttributes, private readonly _forwardingRef: TypeRef | undefined, - private readonly _register: (tref: TypeRef) => void, + private readonly _register: (tref: TypeRef) => void ) {} - private builderForNewType (): TBuilder { + private builderForNewType(): TBuilder { assert(!this._wasUsed, "TypeReconstituter used more than once"); this._wasUsed = true; return this._typeBuilder; } - private builderForSetting (): TBuilder { + private builderForSetting(): TBuilder { assert(this._wasUsed && this._typeRef !== undefined, "Can't set type members before constructing a type"); return this._typeBuilder; } - getResult (): TypeRef { + public getResult(): TypeRef { if (this._typeRef === undefined) { return panic("Type was not reconstituted"); } @@ -56,20 +48,20 @@ export class TypeReconstituter { } // FIXME: Do registration automatically. - private register (tref: TypeRef): void { + private register(tref: TypeRef): void { assert(this._typeRef === undefined, "Cannot register a type twice"); this._typeRef = tref; this._register(tref); } - private registerAndAddAttributes (tref: TypeRef): void { + private registerAndAddAttributes(tref: TypeRef): void { this._typeBuilder.addAttributes(tref, this._typeAttributes); this.register(tref); } - lookup (tref: TypeRef): TypeRef | undefined; - lookup (trefs: Iterable): readonly TypeRef[] | undefined; - lookup (trefs: TypeRef | Iterable): TypeRef | readonly TypeRef[] | undefined { + public lookup(tref: TypeRef): TypeRef | undefined; + public lookup(trefs: Iterable): readonly TypeRef[] | undefined; + public lookup(trefs: TypeRef | Iterable): TypeRef | readonly TypeRef[] | undefined { assert(!this._wasUsed, "Cannot lookup constituents after building type"); if (isTypeRef(trefs)) { return this._typeBuilder.lookupTypeRefs([trefs], undefined, false); @@ -80,7 +72,7 @@ export class TypeReconstituter { } } - lookupMap(trefs: ReadonlyMap): ReadonlyMap | undefined { + public lookupMap(trefs: ReadonlyMap): ReadonlyMap | undefined { const resultValues = this.lookup(trefs.values()); if (resultValues === undefined) return undefined; assert(resultValues.length === trefs.size, "Didn't get back the correct number of types"); @@ -94,9 +86,9 @@ export class TypeReconstituter { return result; } - reconstitute (tref: TypeRef): TypeRef; - reconstitute (trefs: Iterable): readonly TypeRef[]; - reconstitute (trefs: TypeRef | Iterable): TypeRef | readonly TypeRef[] { + public reconstitute(tref: TypeRef): TypeRef; + public reconstitute(trefs: Iterable): readonly TypeRef[]; + public reconstitute(trefs: TypeRef | Iterable): TypeRef | readonly TypeRef[] { assert(this._wasUsed, "Cannot reconstitute constituents before building type"); if (isTypeRef(trefs)) { return this._typeBuilder.reconstituteTypeRef(trefs); @@ -105,68 +97,71 @@ export class TypeReconstituter { } } - reconstituteMap(trefs: ReadonlyMap): ReadonlyMap { + public reconstituteMap(trefs: ReadonlyMap): ReadonlyMap { return mapMap(trefs, tref => this._typeBuilder.reconstituteTypeRef(tref)); } - getPrimitiveType (kind: PrimitiveTypeKind): void { + public getPrimitiveType(kind: PrimitiveTypeKind): void { this.register(this.builderForNewType().getPrimitiveType(kind, this._typeAttributes, this._forwardingRef)); } - getEnumType (cases: ReadonlySet): void { + public getEnumType(cases: ReadonlySet): void { this.register(this.builderForNewType().getEnumType(this._typeAttributes, cases, this._forwardingRef)); } - getUniqueMapType (): void { + public getUniqueMapType(): void { this.registerAndAddAttributes(this.builderForNewType().getUniqueMapType(this._forwardingRef)); } - getMapType (values: TypeRef): void { + public getMapType(values: TypeRef): void { this.register(this.builderForNewType().getMapType(this._typeAttributes, values, this._forwardingRef)); } - getUniqueArrayType (): void { + public getUniqueArrayType(): void { this.registerAndAddAttributes(this.builderForNewType().getUniqueArrayType(this._forwardingRef)); } - getArrayType (items: TypeRef): void { + public getArrayType(items: TypeRef): void { this.register(this.builderForNewType().getArrayType(this._typeAttributes, items, this._forwardingRef)); } - setArrayItems (items: TypeRef): void { + public setArrayItems(items: TypeRef): void { this.builderForSetting().setArrayItems(this.getResult(), items); } - makeClassProperty (tref: TypeRef, isOptional: boolean): ClassProperty { + public makeClassProperty(tref: TypeRef, isOptional: boolean): ClassProperty { return this._typeBuilder.makeClassProperty(tref, isOptional); } - getObjectType (properties: ReadonlyMap, additionalProperties: TypeRef | undefined): void { + public getObjectType( + properties: ReadonlyMap, + additionalProperties: TypeRef | undefined + ): void { this.register( this.builderForNewType().getUniqueObjectType( this._typeAttributes, properties, additionalProperties, - this._forwardingRef, - ), + this._forwardingRef + ) ); } - getUniqueObjectType ( + public getUniqueObjectType( properties: ReadonlyMap | undefined, - additionalProperties: TypeRef | undefined, + additionalProperties: TypeRef | undefined ): void { this.register( this.builderForNewType().getUniqueObjectType( this._typeAttributes, properties, additionalProperties, - this._forwardingRef, - ), + this._forwardingRef + ) ); } - getClassType (properties: ReadonlyMap): void { + public getClassType(properties: ReadonlyMap): void { if (this._makeClassUnique) { this.getUniqueClassType(false, properties); return; @@ -175,40 +170,40 @@ export class TypeReconstituter { this.register(this.builderForNewType().getClassType(this._typeAttributes, properties, this._forwardingRef)); } - getUniqueClassType (isFixed: boolean, properties: ReadonlyMap | undefined): void { + public getUniqueClassType(isFixed: boolean, properties: ReadonlyMap | undefined): void { this.register( - this.builderForNewType().getUniqueClassType(this._typeAttributes, isFixed, properties, this._forwardingRef), + this.builderForNewType().getUniqueClassType(this._typeAttributes, isFixed, properties, this._forwardingRef) ); } - setObjectProperties ( + public setObjectProperties( properties: ReadonlyMap, - additionalProperties: TypeRef | undefined, + additionalProperties: TypeRef | undefined ): void { this.builderForSetting().setObjectProperties(this.getResult(), properties, additionalProperties); } - getUnionType (members: ReadonlySet): void { + public getUnionType(members: ReadonlySet): void { this.register(this.builderForNewType().getUnionType(this._typeAttributes, members, this._forwardingRef)); } - getUniqueUnionType (): void { + public getUniqueUnionType(): void { this.register( - this.builderForNewType().getUniqueUnionType(this._typeAttributes, undefined, this._forwardingRef), + this.builderForNewType().getUniqueUnionType(this._typeAttributes, undefined, this._forwardingRef) ); } - getIntersectionType (members: ReadonlySet): void { + public getIntersectionType(members: ReadonlySet): void { this.register(this.builderForNewType().getIntersectionType(this._typeAttributes, members, this._forwardingRef)); } - getUniqueIntersectionType (members?: ReadonlySet): void { + public getUniqueIntersectionType(members?: ReadonlySet): void { this.register( - this.builderForNewType().getUniqueIntersectionType(this._typeAttributes, members, this._forwardingRef), + this.builderForNewType().getUniqueIntersectionType(this._typeAttributes, members, this._forwardingRef) ); } - setSetOperationMembers (members: ReadonlySet): void { + public setSetOperationMembers(members: ReadonlySet): void { this.builderForSetting().setSetOperationMembers(this.getResult(), members); } } @@ -220,12 +215,12 @@ export abstract class BaseGraphRewriteBuilder extends TypeBuilder implements Typ private _printIndent = 0; - constructor ( - readonly originalGraph: TypeGraph, + public constructor( + protected readonly originalGraph: TypeGraph, stringTypeMapping: StringTypeMapping, alphabetizeProperties: boolean, graphHasProvenanceAttributes: boolean, - protected readonly debugPrint: boolean, + protected readonly debugPrint: boolean ) { super( originalGraph.serial + 1, @@ -233,13 +228,13 @@ export abstract class BaseGraphRewriteBuilder extends TypeBuilder implements Typ alphabetizeProperties, false, false, - graphHasProvenanceAttributes, + graphHasProvenanceAttributes ); } - withForwardingRef ( + public withForwardingRef( maybeForwardingRef: TypeRef | undefined, - typeCreator: (forwardingRef: TypeRef) => TypeRef, + typeCreator: (forwardingRef: TypeRef) => TypeRef ): TypeRef { if (maybeForwardingRef !== undefined) { return typeCreator(maybeForwardingRef); @@ -251,18 +246,26 @@ export abstract class BaseGraphRewriteBuilder extends TypeBuilder implements Typ return actualRef; } - reconstituteType (t: Type, attributes?: TypeAttributes, forwardingRef?: TypeRef): TypeRef { + public reconstituteType(t: Type, attributes?: TypeAttributes, forwardingRef?: TypeRef): TypeRef { return this.reconstituteTypeRef(t.typeRef, attributes, forwardingRef); } - abstract lookupTypeRefs (typeRefs: TypeRef[], forwardingRef?: TypeRef, replaceSet?: boolean): TypeRef | undefined; - protected abstract forceReconstituteTypeRef ( + public abstract lookupTypeRefs( + typeRefs: TypeRef[], + forwardingRef?: TypeRef, + replaceSet?: boolean + ): TypeRef | undefined; + protected abstract forceReconstituteTypeRef( originalRef: TypeRef, attributes?: TypeAttributes, maybeForwardingRef?: TypeRef ): TypeRef; - reconstituteTypeRef (originalRef: TypeRef, attributes?: TypeAttributes, maybeForwardingRef?: TypeRef): TypeRef { + public reconstituteTypeRef( + originalRef: TypeRef, + attributes?: TypeAttributes, + maybeForwardingRef?: TypeRef + ): TypeRef { const maybeRef = this.lookupTypeRefs([originalRef], maybeForwardingRef); if (maybeRef !== undefined) { if (attributes !== undefined) { @@ -275,11 +278,11 @@ export abstract class BaseGraphRewriteBuilder extends TypeBuilder implements Typ return this.forceReconstituteTypeRef(originalRef, attributes, maybeForwardingRef); } - reconstituteTypeAttributes (attributes: TypeAttributes): TypeAttributes { + public reconstituteTypeAttributes(attributes: TypeAttributes): TypeAttributes { return mapMap(attributes, (v, a) => a.reconstitute(this, v)); } - protected assertTypeRefsToReconstitute (typeRefs: TypeRef[], forwardingRef?: TypeRef): void { + protected assertTypeRefsToReconstitute(typeRefs: TypeRef[], forwardingRef?: TypeRef): void { assert(typeRefs.length > 0, "Must have at least one type to reconstitute"); for (const originalRef of typeRefs) { assertTypeRefGraph(originalRef, this.originalGraph); @@ -290,15 +293,15 @@ export abstract class BaseGraphRewriteBuilder extends TypeBuilder implements Typ } } - protected changeDebugPrintIndent (delta: number): void { + protected changeDebugPrintIndent(delta: number): void { this._printIndent += delta; } - protected get debugPrintIndentation (): string { + protected get debugPrintIndentation(): string { return indentationString(this._printIndent); } - finish (): TypeGraph { + public finish(): TypeGraph { for (const [name, t] of this.originalGraph.topLevels) { this.addTopLevel(name, this.reconstituteType(t)); } @@ -306,11 +309,11 @@ export abstract class BaseGraphRewriteBuilder extends TypeBuilder implements Typ return super.finish(); } - setLostTypeAttributes (): void { + public setLostTypeAttributes(): void { this._lostTypeAttributes = true; } - get lostTypeAttributes (): boolean { + public get lostTypeAttributes(): boolean { return this._lostTypeAttributes; } } @@ -318,20 +321,20 @@ export abstract class BaseGraphRewriteBuilder extends TypeBuilder implements Typ export class GraphRemapBuilder extends BaseGraphRewriteBuilder { private readonly _attributeSources: Map = new Map(); - constructor ( + public constructor( originalGraph: TypeGraph, stringTypeMapping: StringTypeMapping, alphabetizeProperties: boolean, graphHasProvenanceAttributes: boolean, private readonly _map: ReadonlyMap, - debugPrintRemapping: boolean, + debugPrintRemapping: boolean ) { super( originalGraph, stringTypeMapping, alphabetizeProperties, graphHasProvenanceAttributes, - debugPrintRemapping, + debugPrintRemapping ); for (const [source, target] of _map) { @@ -345,22 +348,22 @@ export class GraphRemapBuilder extends BaseGraphRewriteBuilder { } } - protected makeIdentity (_maker: () => MaybeTypeIdentity): MaybeTypeIdentity { + protected makeIdentity(_maker: () => MaybeTypeIdentity): MaybeTypeIdentity { return undefined; } - private getMapTarget (tref: TypeRef): TypeRef { + private getMapTarget(tref: TypeRef): TypeRef { const maybeType = this._map.get(derefTypeRef(tref, this.originalGraph)); if (maybeType === undefined) return tref; assert(this._map.get(maybeType) === undefined, "We have a type that's remapped to a remapped type"); return maybeType.typeRef; } - protected addForwardingIntersection (_forwardingRef: TypeRef, _tref: TypeRef): TypeRef { + protected addForwardingIntersection(_forwardingRef: TypeRef, _tref: TypeRef): TypeRef { return panic("We can't add forwarding intersections when we're removing forwarding intersections"); } - lookupTypeRefs (typeRefs: TypeRef[], forwardingRef?: TypeRef): TypeRef | undefined { + public lookupTypeRefs(typeRefs: TypeRef[], forwardingRef?: TypeRef): TypeRef | undefined { assert(forwardingRef === undefined, "We can't have a forwarding ref when we remap"); this.assertTypeRefsToReconstitute(typeRefs, forwardingRef); @@ -376,10 +379,10 @@ export class GraphRemapBuilder extends BaseGraphRewriteBuilder { return first; } - protected forceReconstituteTypeRef ( + protected forceReconstituteTypeRef( originalRef: TypeRef, attributes?: TypeAttributes, - maybeForwardingRef?: TypeRef, + maybeForwardingRef?: TypeRef ): TypeRef { originalRef = this.getMapTarget(originalRef); @@ -407,13 +410,13 @@ export class GraphRemapBuilder extends BaseGraphRewriteBuilder { attributes = combineTypeAttributes( "union", attributes, - this.reconstituteTypeAttributes(originalAttributes), + this.reconstituteTypeAttributes(originalAttributes) ); } else { attributes = combineTypeAttributes( "union", attributes, - this.reconstituteTypeAttributes(combineTypeAttributesOfTypes("union", attributeSources)), + this.reconstituteTypeAttributes(combineTypeAttributesOfTypes("union", attributeSources)) ); } @@ -430,7 +433,7 @@ export class GraphRemapBuilder extends BaseGraphRewriteBuilder { this.changeDebugPrintIndent(-1); console.log(`${this.debugPrintIndentation}reconstituted ${index} as ${typeRefIndex(tref)}`); } - }, + } ); originalType.reconstitute(reconstituter, this.canonicalOrder); return reconstituter.getResult(); @@ -443,7 +446,7 @@ export class GraphRewriteBuilder extends BaseGraphRewriteBuilder private readonly _reconstitutedUnions: EqualityMap, TypeRef> = new EqualityMap(); - constructor ( + public constructor( originalGraph: TypeGraph, stringTypeMapping: StringTypeMapping, alphabetizeProperties: boolean, @@ -454,14 +457,14 @@ export class GraphRewriteBuilder extends BaseGraphRewriteBuilder typesToReplace: ReadonlySet, builder: GraphRewriteBuilder, forwardingRef: TypeRef - ) => TypeRef, + ) => TypeRef ) { super( originalGraph, stringTypeMapping, alphabetizeProperties, graphHasProvenanceAttributes, - debugPrintReconstitution, + debugPrintReconstitution ); this._setsToReplaceByMember = new Map(); @@ -475,19 +478,19 @@ export class GraphRewriteBuilder extends BaseGraphRewriteBuilder } } - registerUnion (typeRefs: TypeRef[], reconstituted: TypeRef): void { + public registerUnion(typeRefs: TypeRef[], reconstituted: TypeRef): void { const set = new Set(typeRefs); assert(!this._reconstitutedUnions.has(set), "Cannot register reconstituted set twice"); this._reconstitutedUnions.set(set, reconstituted); } - private replaceSet (typesToReplace: ReadonlySet, maybeForwardingRef: TypeRef | undefined): TypeRef { + private replaceSet(typesToReplace: ReadonlySet, maybeForwardingRef: TypeRef | undefined): TypeRef { return this.withForwardingRef(maybeForwardingRef, forwardingRef => { if (this.debugPrint) { console.log( `${this.debugPrintIndentation}replacing set ${Array.from(typesToReplace) .map(t => t.index.toString()) - .join(",")} as ${typeRefIndex(forwardingRef)}`, + .join(",")} as ${typeRefIndex(forwardingRef)}` ); this.changeDebugPrintIndent(1); } @@ -507,7 +510,7 @@ export class GraphRewriteBuilder extends BaseGraphRewriteBuilder console.log( `${this.debugPrintIndentation}replaced set ${Array.from(typesToReplace) .map(t => t.index.toString()) - .join(",")} as ${typeRefIndex(forwardingRef)}`, + .join(",")} as ${typeRefIndex(forwardingRef)}` ); } @@ -515,10 +518,10 @@ export class GraphRewriteBuilder extends BaseGraphRewriteBuilder }); } - protected forceReconstituteTypeRef ( + protected forceReconstituteTypeRef( originalRef: TypeRef, attributes?: TypeAttributes, - maybeForwardingRef?: TypeRef, + maybeForwardingRef?: TypeRef ): TypeRef { const [originalType, originalAttributes] = typeAndAttributesForTypeRef(originalRef, this.originalGraph); const index = typeRefIndex(originalRef); @@ -534,7 +537,7 @@ export class GraphRewriteBuilder extends BaseGraphRewriteBuilder attributes = combineTypeAttributes( "union", attributes, - this.reconstituteTypeAttributes(originalAttributes), + this.reconstituteTypeAttributes(originalAttributes) ); } @@ -560,7 +563,7 @@ export class GraphRewriteBuilder extends BaseGraphRewriteBuilder } /* - reconstituteTypeUnmodified(originalType: Type): TypeRef { + public reconstituteTypeUnmodified(originalType: Type): TypeRef { const reconstituter = new TypeReconstituter( this, this.alphabetizeProperties, @@ -575,7 +578,7 @@ export class GraphRewriteBuilder extends BaseGraphRewriteBuilder // If the union of these type refs have been, or are supposed to be, reconstituted to // one target type, return it. Otherwise return undefined. - lookupTypeRefs (typeRefs: TypeRef[], forwardingRef?: TypeRef, replaceSet = true): TypeRef | undefined { + public lookupTypeRefs(typeRefs: TypeRef[], forwardingRef?: TypeRef, replaceSet = true): TypeRef | undefined { this.assertTypeRefsToReconstitute(typeRefs, forwardingRef); // Check whether we have already reconstituted them. That means ensuring diff --git a/packages/quicktype-core/src/MakeTransformations.ts b/packages/quicktype-core/src/MakeTransformations.ts index 0b98b390f..8daede47e 100644 --- a/packages/quicktype-core/src/MakeTransformations.ts +++ b/packages/quicktype-core/src/MakeTransformations.ts @@ -1,26 +1,20 @@ import { setFilter, iterableFirst, mapMapEntries, withDefault, iterableSome, arraySortByInto } from "collection-utils"; -import { type TypeGraph, type TypeRef} from "./TypeGraph"; +import { type TypeGraph, type TypeRef } from "./TypeGraph"; import { typeRefIndex } from "./TypeGraph"; import { type TargetLanguage } from "./TargetLanguage"; -import { - type TypeKind, - type Type, - type PrimitiveType, - type PrimitiveStringTypeKind, -} from "./Type"; +import { type TypeKind, type Type, type PrimitiveType, type PrimitiveStringTypeKind } from "./Type"; import { UnionType, EnumType, ArrayType, isNumberTypeKind, isPrimitiveStringTypeKind, - targetTypeKindForTransformedStringTypeKind, + targetTypeKindForTransformedStringTypeKind } from "./Type"; import { type GraphRewriteBuilder } from "./GraphRewriting"; import { defined, assert, panic } from "./support/Support"; -import { - type Transformer} from "./Transformers"; +import { type Transformer } from "./Transformers"; import { UnionInstantiationTransformer, DecodingChoiceTransformer, @@ -33,19 +27,19 @@ import { ParseStringTransformer, ArrayDecodingTransformer, MinMaxLengthCheckTransformer, - MinMaxValueTransformer, + MinMaxValueTransformer } from "./Transformers"; -import { type TypeAttributes} from "./attributes/TypeAttributes"; +import { type TypeAttributes } from "./attributes/TypeAttributes"; import { emptyTypeAttributes, combineTypeAttributes } from "./attributes/TypeAttributes"; import { StringTypes } from "./attributes/StringTypes"; import { type RunContext } from "./Run"; import { minMaxLengthForType, minMaxValueForType } from "./attributes/Constraints"; -function transformationAttributes ( +function transformationAttributes( graph: TypeGraph, reconstitutedTargetType: TypeRef, transformer: Transformer, - debugPrintTransformations: boolean, + debugPrintTransformations: boolean ): TypeAttributes { const transformation = new Transformation(graph, reconstitutedTargetType, transformer); if (debugPrintTransformations) { @@ -58,11 +52,11 @@ function transformationAttributes ( return transformationTypeAttributeKind.makeAttributes(transformation); } -function makeEnumTransformer ( +function makeEnumTransformer( graph: TypeGraph, enumType: EnumType, stringType: TypeRef, - continuation?: Transformer, + continuation?: Transformer ): Transformer { const sortedCases = Array.from(enumType.cases).sort(); const caseTransformers = sortedCases.map( @@ -71,18 +65,18 @@ function makeEnumTransformer ( graph, stringType, new StringProducerTransformer(graph, stringType, continuation, c), - c, - ), + c + ) ); return new ChoiceTransformer(graph, stringType, caseTransformers); } -function replaceUnion ( +function replaceUnion( union: UnionType, builder: GraphRewriteBuilder, forwardingRef: TypeRef, transformedTypes: Set, - debugPrintTransformations: boolean, + debugPrintTransformations: boolean ): TypeRef { const graph = builder.typeGraph; @@ -91,7 +85,7 @@ function replaceUnion ( // Type attributes that we lost during reconstitution. let additionalAttributes = emptyTypeAttributes; - function reconstituteMember (t: Type): TypeRef { + function reconstituteMember(t: Type): TypeRef { // Special handling for some transformed string type kinds: The type in // the union must be the target type, so if one already exists, use that // one, otherwise make a new one. @@ -123,16 +117,16 @@ function replaceUnion ( ? builder.getUnionType(union.getAttributes(), reconstitutedMemberSet) : defined(iterableFirst(reconstitutedMemberSet)); - function memberForKind (kind: TypeKind) { + function memberForKind(kind: TypeKind) { return defined(reconstitutedMembersByKind.get(kind)); } - function consumer (memberTypeRef: TypeRef): Transformer | undefined { + function consumer(memberTypeRef: TypeRef): Transformer | undefined { if (!haveUnion) return undefined; return new UnionInstantiationTransformer(graph, memberTypeRef); } - function transformerForKind (kind: TypeKind) { + function transformerForKind(kind: TypeKind) { const member = union.findMember(kind); if (member === undefined) return undefined; const memberTypeRef = memberForKind(kind); @@ -140,7 +134,7 @@ function replaceUnion ( } let maybeStringType: TypeRef | undefined = undefined; - function getStringType (): TypeRef { + function getStringType(): TypeRef { if (maybeStringType === undefined) { maybeStringType = builder.getStringType(emptyTypeAttributes, StringTypes.unrestricted); } @@ -148,7 +142,7 @@ function replaceUnion ( return maybeStringType; } - function transformerForStringType (t: Type): Transformer | undefined { + function transformerForStringType(t: Type): Transformer | undefined { const memberRef = memberForKind(t.kind); if (t.kind === "string") { const minMax = minMaxLengthForType(t); @@ -179,8 +173,8 @@ function replaceUnion ( new ChoiceTransformer( graph, getStringType(), - stringTypes.map(t => defined(transformerForStringType(t))), - ), + stringTypes.map(t => defined(transformerForStringType(t))) + ) ); } @@ -188,7 +182,7 @@ function replaceUnion ( const transformerForMap = transformerForKind("map"); assert( transformerForClass === undefined || transformerForMap === undefined, - "Can't have both class and map in a transformed union", + "Can't have both class and map in a transformed union" ); const transformerForObject = transformerForClass !== undefined ? transformerForClass : transformerForMap; @@ -201,21 +195,21 @@ function replaceUnion ( transformerForKind("bool"), transformerForString, transformerForKind("array"), - transformerForObject, + transformerForObject ); const attributes = transformationAttributes(graph, reconstitutedTargetType, transformer, debugPrintTransformations); return builder.getPrimitiveType( "any", combineTypeAttributes("union", attributes, additionalAttributes), - forwardingRef, + forwardingRef ); } -function replaceArray ( +function replaceArray( arrayType: ArrayType, builder: GraphRewriteBuilder, forwardingRef: TypeRef, - debugPrintTransformations: boolean, + debugPrintTransformations: boolean ): TypeRef { const anyType = builder.getPrimitiveType("any"); const anyArrayType = builder.getArrayType(emptyTypeAttributes, anyType); @@ -225,74 +219,74 @@ function replaceArray ( anyArrayType, undefined, reconstitutedItems, - new DecodingTransformer(builder.typeGraph, anyType, undefined), + new DecodingTransformer(builder.typeGraph, anyType, undefined) ); const reconstitutedArray = builder.getArrayType( builder.reconstituteTypeAttributes(arrayType.getAttributes()), - reconstitutedItems, + reconstitutedItems ); const attributes = transformationAttributes( builder.typeGraph, reconstitutedArray, transformer, - debugPrintTransformations, + debugPrintTransformations ); return builder.getArrayType(attributes, anyType, forwardingRef); } -function replaceEnum ( +function replaceEnum( enumType: EnumType, builder: GraphRewriteBuilder, forwardingRef: TypeRef, - debugPrintTransformations: boolean, + debugPrintTransformations: boolean ): TypeRef { const stringType = builder.getStringType(emptyTypeAttributes, StringTypes.unrestricted); const transformer = new DecodingTransformer( builder.typeGraph, stringType, - makeEnumTransformer(builder.typeGraph, enumType, stringType), + makeEnumTransformer(builder.typeGraph, enumType, stringType) ); const reconstitutedEnum = builder.getEnumType(enumType.getAttributes(), enumType.cases); const attributes = transformationAttributes( builder.typeGraph, reconstitutedEnum, transformer, - debugPrintTransformations, + debugPrintTransformations ); return builder.getStringType(attributes, StringTypes.unrestricted, forwardingRef); } -function replaceNumber ( +function replaceNumber( t: PrimitiveType, builder: GraphRewriteBuilder, forwardingRef: TypeRef, - debugPrintTransformations: boolean, + debugPrintTransformations: boolean ): TypeRef { const stringType = builder.getStringType(emptyTypeAttributes, StringTypes.unrestricted); const [min, max] = defined(minMaxValueForType(t)); const transformer = new DecodingTransformer( builder.typeGraph, stringType, - new MinMaxValueTransformer(builder.typeGraph, stringType, undefined, min, max), + new MinMaxValueTransformer(builder.typeGraph, stringType, undefined, min, max) ); const reconstitutedAttributes = builder.reconstituteTypeAttributes(t.getAttributes()); const attributes = transformationAttributes( builder.typeGraph, builder.getPrimitiveType("double", reconstitutedAttributes, undefined), transformer, - debugPrintTransformations, + debugPrintTransformations ); return builder.getPrimitiveType("double", attributes, forwardingRef); } -function replaceString ( +function replaceString( t: PrimitiveType, builder: GraphRewriteBuilder, forwardingRef: TypeRef, - debugPrintTransformations: boolean, + debugPrintTransformations: boolean ): TypeRef { const [min, max] = defined(minMaxLengthForType(t)); const reconstitutedAttributes = builder.reconstituteTypeAttributes(t.getAttributes()); @@ -300,23 +294,23 @@ function replaceString ( const transformer = new DecodingTransformer( builder.typeGraph, stringType, - new MinMaxLengthCheckTransformer(builder.typeGraph, stringType, undefined, min, max), + new MinMaxLengthCheckTransformer(builder.typeGraph, stringType, undefined, min, max) ); const attributes = transformationAttributes( builder.typeGraph, builder.getStringType(reconstitutedAttributes, undefined), transformer, - debugPrintTransformations, + debugPrintTransformations ); return builder.getStringType(attributes, StringTypes.unrestricted, forwardingRef); } -function replaceTransformedStringType ( +function replaceTransformedStringType( t: PrimitiveType, kind: PrimitiveStringTypeKind, builder: GraphRewriteBuilder, forwardingRef: TypeRef, - debugPrintTransformations: boolean, + debugPrintTransformations: boolean ): TypeRef { const reconstitutedAttributes = builder.reconstituteTypeAttributes(t.getAttributes()); const targetTypeKind = withDefault(targetTypeKindForTransformedStringTypeKind(kind), kind); @@ -324,18 +318,18 @@ function replaceTransformedStringType ( const transformer = new DecodingTransformer( builder.typeGraph, stringType, - new ParseStringTransformer(builder.typeGraph, stringType, undefined), + new ParseStringTransformer(builder.typeGraph, stringType, undefined) ); const attributes = transformationAttributes( builder.typeGraph, builder.getPrimitiveType(targetTypeKind, reconstitutedAttributes), transformer, - debugPrintTransformations, + debugPrintTransformations ); return builder.getStringType(attributes, StringTypes.unrestricted, forwardingRef); } -export function makeTransformations (ctx: RunContext, graph: TypeGraph, targetLanguage: TargetLanguage): TypeGraph { +export function makeTransformations(ctx: RunContext, graph: TypeGraph, targetLanguage: TargetLanguage): TypeGraph { const transformedTypes = setFilter(graph.allTypesUnordered(), t => { if (targetLanguage.needsTransformerForType(t)) return true; if (!(t instanceof UnionType)) return false; @@ -344,10 +338,10 @@ export function makeTransformations (ctx: RunContext, graph: TypeGraph, targetLa return iterableSome(stringMembers, m => targetLanguage.needsTransformerForType(m)); }); - function replace ( + function replace( setOfOneUnion: ReadonlySet, builder: GraphRewriteBuilder, - forwardingRef: TypeRef, + forwardingRef: TypeRef ): TypeRef { const t = defined(iterableFirst(setOfOneUnion)); if (t instanceof UnionType) { @@ -376,7 +370,7 @@ export function makeTransformations (ctx: RunContext, graph: TypeGraph, targetLa t.kind, builder, forwardingRef, - ctx.debugPrintTransformations, + ctx.debugPrintTransformations ); } @@ -390,6 +384,6 @@ export function makeTransformations (ctx: RunContext, graph: TypeGraph, targetLa false, groups, ctx.debugPrintReconstitution, - replace, + replace ); } diff --git a/packages/quicktype-core/src/MarkovChain.ts b/packages/quicktype-core/src/MarkovChain.ts index 85bd62b4d..a2e6f453b 100644 --- a/packages/quicktype-core/src/MarkovChain.ts +++ b/packages/quicktype-core/src/MarkovChain.ts @@ -13,7 +13,7 @@ export interface MarkovChain { trie: Trie; } -function makeTrie (): Trie { +function makeTrie(): Trie { const arr: SubTrie[] = []; for (let i = 0; i < 128; i++) { arr.push(null); @@ -22,7 +22,7 @@ function makeTrie (): Trie { return { count: 0, arr }; } -function lookup (t: Trie, seq: string, i: number): Trie | number | undefined { +function lookup(t: Trie, seq: string, i: number): Trie | number | undefined { if (i >= seq.length) { return t; } @@ -44,7 +44,7 @@ function lookup (t: Trie, seq: string, i: number): Trie | number | undefined { } } -function increment (t: Trie, seq: string, i: number): void { +function increment(t: Trie, seq: string, i: number): void { let first = seq.charCodeAt(i); if (first >= 128) { first = 0; @@ -79,7 +79,7 @@ function increment (t: Trie, seq: string, i: number): void { increment(st, seq, i + 1); } -export function train (lines: string[], depth: number): MarkovChain { +export function train(lines: string[], depth: number): MarkovChain { const trie = makeTrie(); for (const l of lines) { for (let i = depth; i <= l.length; i++) { @@ -90,11 +90,11 @@ export function train (lines: string[], depth: number): MarkovChain { return { trie, depth }; } -export function load (): MarkovChain { +export function load(): MarkovChain { return JSON.parse(inflateBase64(encodedMarkovChain)); } -export function evaluateFull (mc: MarkovChain, word: string): [number, number[]] { +export function evaluateFull(mc: MarkovChain, word: string): [number, number[]] { const { trie, depth } = mc; if (word.length < depth) { return [1, []]; @@ -119,16 +119,16 @@ export function evaluateFull (mc: MarkovChain, word: string): [number, number[]] return [Math.pow(p, 1 / (word.length - depth + 1)), scores]; } -export function evaluate (mc: MarkovChain, word: string): number { +export function evaluate(mc: MarkovChain, word: string): number { return evaluateFull(mc, word)[0]; } -function randomInt (lower: number, upper: number) { +function randomInt(lower: number, upper: number) { const range = upper - lower; return lower + Math.floor(Math.random() * range); } -export function generate (mc: MarkovChain, state: string, unseenWeight: number): string { +export function generate(mc: MarkovChain, state: string, unseenWeight: number): string { assert(state.length === mc.depth - 1, "State and chain length don't match up"); const t = lookup(mc.trie, state, 0); if (typeof t === "number") { @@ -139,7 +139,7 @@ export function generate (mc: MarkovChain, state: string, unseenWeight: number): return String.fromCharCode(randomInt(32, 127)); } - const counts = t.arr.map((x, i) => x === null ? i === 0 ? 0 : unseenWeight : (x as number)); + const counts = t.arr.map((x, i) => (x === null ? (i === 0 ? 0 : unseenWeight) : (x as number))); let n = 0; for (const c of counts) { n += c; @@ -157,11 +157,11 @@ export function generate (mc: MarkovChain, state: string, unseenWeight: number): return panic("We screwed up bookkeeping, or randomInt"); } -function testWord (mc: MarkovChain, word: string): void { +function testWord(mc: MarkovChain, word: string): void { console.log(`"${word}": ${evaluate(mc, word)}`); } -export function test (): void { +export function test(): void { const mc = load(); testWord(mc, "url"); @@ -185,6 +185,6 @@ export function test (): void { testWord( mc, - "\ud83d\udebe \ud83c\udd92 \ud83c\udd93 \ud83c\udd95 \ud83c\udd96 \ud83c\udd97 \ud83c\udd99 \ud83c\udfe7", + "\ud83d\udebe \ud83c\udd92 \ud83c\udd93 \ud83c\udd95 \ud83c\udd96 \ud83c\udd97 \ud83c\udd99 \ud83c\udfe7" ); } diff --git a/packages/quicktype-core/src/Messages.ts b/packages/quicktype-core/src/Messages.ts index 082c3ce40..0236235f9 100644 --- a/packages/quicktype-core/src/Messages.ts +++ b/packages/quicktype-core/src/Messages.ts @@ -2,84 +2,84 @@ import { type StringMap } from "./support/Support"; import { type Ref } from "./input/JSONSchemaInput"; export type ErrorProperties = - | { kind: "InternalError", properties: { message: string, }, } + | { kind: "InternalError"; properties: { message: string } } // Misc | { - kind: "MiscJSONParseError", - properties: { address: string, description: string, message: string, }, - } - | { kind: "MiscReadError", properties: { fileOrURL: string, message: string, }, } - | { kind: "MiscUnicodeHighSurrogateWithoutLowSurrogate", properties: {}, } - | { kind: "MiscInvalidMinMaxConstraint", properties: { max: number, min: number, }, } + kind: "MiscJSONParseError"; + properties: { address: string; description: string; message: string }; + } + | { kind: "MiscReadError"; properties: { fileOrURL: string; message: string } } + | { kind: "MiscUnicodeHighSurrogateWithoutLowSurrogate"; properties: {} } + | { kind: "MiscInvalidMinMaxConstraint"; properties: { max: number; min: number } } // Inference - | { kind: "InferenceJSONReferenceNotRooted", properties: { reference: string, }, } - | { kind: "InferenceJSONReferenceToUnion", properties: { reference: string, }, } - | { kind: "InferenceJSONReferenceWrongProperty", properties: { reference: string, }, } - | { kind: "InferenceJSONReferenceInvalidArrayIndex", properties: { reference: string, }, } + | { kind: "InferenceJSONReferenceNotRooted"; properties: { reference: string } } + | { kind: "InferenceJSONReferenceToUnion"; properties: { reference: string } } + | { kind: "InferenceJSONReferenceWrongProperty"; properties: { reference: string } } + | { kind: "InferenceJSONReferenceInvalidArrayIndex"; properties: { reference: string } } // JSON Schema input - | { kind: "SchemaArrayIsInvalidSchema", properties: { ref: Ref, }, } - | { kind: "SchemaNullIsInvalidSchema", properties: { ref: Ref, }, } - | { kind: "SchemaRefMustBeString", properties: { actual: string, ref: Ref, }, } - | { kind: "SchemaAdditionalTypesForbidRequired", properties: { ref: Ref, }, } - | { kind: "SchemaNoTypeSpecified", properties: { ref: Ref, }, } - | { kind: "SchemaInvalidType", properties: { ref: Ref, type: string, }, } - | { kind: "SchemaFalseNotSupported", properties: { ref: Ref, }, } - | { kind: "SchemaInvalidJSONSchemaType", properties: { ref: Ref, type: string, }, } - | { kind: "SchemaRequiredMustBeStringOrStringArray", properties: { actual: any, ref: Ref, }, } - | { kind: "SchemaRequiredElementMustBeString", properties: { element: any, ref: Ref, }, } - | { kind: "SchemaTypeMustBeStringOrStringArray", properties: { actual: any, }, } - | { kind: "SchemaTypeElementMustBeString", properties: { element: any, ref: Ref, }, } - | { kind: "SchemaArrayItemsMustBeStringOrArray", properties: { actual: any, ref: Ref, }, } - | { kind: "SchemaIDMustHaveAddress", properties: { id: string, ref: Ref, }, } - | { kind: "SchemaWrongAccessorEntryArrayLength", properties: { operation: string, ref: Ref, }, } + | { kind: "SchemaArrayIsInvalidSchema"; properties: { ref: Ref } } + | { kind: "SchemaNullIsInvalidSchema"; properties: { ref: Ref } } + | { kind: "SchemaRefMustBeString"; properties: { actual: string; ref: Ref } } + | { kind: "SchemaAdditionalTypesForbidRequired"; properties: { ref: Ref } } + | { kind: "SchemaNoTypeSpecified"; properties: { ref: Ref } } + | { kind: "SchemaInvalidType"; properties: { ref: Ref; type: string } } + | { kind: "SchemaFalseNotSupported"; properties: { ref: Ref } } + | { kind: "SchemaInvalidJSONSchemaType"; properties: { ref: Ref; type: string } } + | { kind: "SchemaRequiredMustBeStringOrStringArray"; properties: { actual: any; ref: Ref } } + | { kind: "SchemaRequiredElementMustBeString"; properties: { element: any; ref: Ref } } + | { kind: "SchemaTypeMustBeStringOrStringArray"; properties: { actual: any } } + | { kind: "SchemaTypeElementMustBeString"; properties: { element: any; ref: Ref } } + | { kind: "SchemaArrayItemsMustBeStringOrArray"; properties: { actual: any; ref: Ref } } + | { kind: "SchemaIDMustHaveAddress"; properties: { id: string; ref: Ref } } + | { kind: "SchemaWrongAccessorEntryArrayLength"; properties: { operation: string; ref: Ref } } | { - kind: "SchemaSetOperationCasesIsNotArray", - properties: { cases: any, operation: string, ref: Ref, }, - } - | { kind: "SchemaMoreThanOneUnionMemberName", properties: { names: string[], }, } - | { kind: "SchemaCannotGetTypesFromBoolean", properties: { ref: string, }, } - | { kind: "SchemaCannotIndexArrayWithNonNumber", properties: { actual: string, ref: Ref, }, } - | { kind: "SchemaIndexNotInArray", properties: { index: number, ref: Ref, }, } - | { kind: "SchemaKeyNotInObject", properties: { key: string, ref: Ref, }, } - | { kind: "SchemaFetchError", properties: { address: string, base: Ref, }, } - | { kind: "SchemaFetchErrorTopLevel", properties: { address: string, }, } - | { kind: "SchemaFetchErrorAdditional", properties: { address: string, }, } + kind: "SchemaSetOperationCasesIsNotArray"; + properties: { cases: any; operation: string; ref: Ref }; + } + | { kind: "SchemaMoreThanOneUnionMemberName"; properties: { names: string[] } } + | { kind: "SchemaCannotGetTypesFromBoolean"; properties: { ref: string } } + | { kind: "SchemaCannotIndexArrayWithNonNumber"; properties: { actual: string; ref: Ref } } + | { kind: "SchemaIndexNotInArray"; properties: { index: number; ref: Ref } } + | { kind: "SchemaKeyNotInObject"; properties: { key: string; ref: Ref } } + | { kind: "SchemaFetchError"; properties: { address: string; base: Ref } } + | { kind: "SchemaFetchErrorTopLevel"; properties: { address: string } } + | { kind: "SchemaFetchErrorAdditional"; properties: { address: string } } // GraphQL input - | { kind: "GraphQLNoQueriesDefined", properties: {}, } + | { kind: "GraphQLNoQueriesDefined"; properties: {} } // Driver - | { kind: "DriverUnknownSourceLanguage", properties: { lang: string, }, } - | { kind: "DriverUnknownOutputLanguage", properties: { lang: string, }, } - | { kind: "DriverMoreThanOneInputGiven", properties: { topLevel: string, }, } - | { kind: "DriverCannotInferNameForSchema", properties: { uri: string, }, } - | { kind: "DriverNoGraphQLQueryGiven", properties: {}, } - | { kind: "DriverNoGraphQLSchemaInDir", properties: { dir: string, }, } - | { kind: "DriverMoreThanOneGraphQLSchemaInDir", properties: { dir: string, }, } - | { kind: "DriverSourceLangMustBeGraphQL", properties: {}, } - | { kind: "DriverGraphQLSchemaNeeded", properties: {}, } - | { kind: "DriverInputFileDoesNotExist", properties: { filename: string, }, } - | { kind: "DriverCannotMixJSONWithOtherSamples", properties: { dir: string, }, } - | { kind: "DriverCannotMixNonJSONInputs", properties: { dir: string, }, } - | { kind: "DriverUnknownDebugOption", properties: { option: string, }, } - | { kind: "DriverNoLanguageOrExtension", properties: {}, } - | { kind: "DriverCLIOptionParsingFailed", properties: { message: string, }, } + | { kind: "DriverUnknownSourceLanguage"; properties: { lang: string } } + | { kind: "DriverUnknownOutputLanguage"; properties: { lang: string } } + | { kind: "DriverMoreThanOneInputGiven"; properties: { topLevel: string } } + | { kind: "DriverCannotInferNameForSchema"; properties: { uri: string } } + | { kind: "DriverNoGraphQLQueryGiven"; properties: {} } + | { kind: "DriverNoGraphQLSchemaInDir"; properties: { dir: string } } + | { kind: "DriverMoreThanOneGraphQLSchemaInDir"; properties: { dir: string } } + | { kind: "DriverSourceLangMustBeGraphQL"; properties: {} } + | { kind: "DriverGraphQLSchemaNeeded"; properties: {} } + | { kind: "DriverInputFileDoesNotExist"; properties: { filename: string } } + | { kind: "DriverCannotMixJSONWithOtherSamples"; properties: { dir: string } } + | { kind: "DriverCannotMixNonJSONInputs"; properties: { dir: string } } + | { kind: "DriverUnknownDebugOption"; properties: { option: string } } + | { kind: "DriverNoLanguageOrExtension"; properties: {} } + | { kind: "DriverCLIOptionParsingFailed"; properties: { message: string } } // IR - | { kind: "IRNoForwardDeclarableTypeInCycle", properties: {}, } - | { kind: "IRTypeAttributesNotPropagated", properties: { count: number, indexes: number[], }, } - | { kind: "IRNoEmptyUnions", properties: {}, } + | { kind: "IRNoForwardDeclarableTypeInCycle"; properties: {} } + | { kind: "IRTypeAttributesNotPropagated"; properties: { count: number; indexes: number[] } } + | { kind: "IRNoEmptyUnions"; properties: {} } // Rendering - | { kind: "RendererUnknownOptionValue", properties: { name: string, value: string, }, } + | { kind: "RendererUnknownOptionValue"; properties: { name: string; value: string } } // TypeScript input - | { kind: "TypeScriptCompilerError", properties: { message: string, }, }; + | { kind: "TypeScriptCompilerError"; properties: { message: string } }; -export type ErrorKinds = ErrorProperties extends { kind: infer K, } ? K : never; +export type ErrorKinds = ErrorProperties extends { kind: infer K } ? K : never; type ErrorMessages = { readonly [K in ErrorKinds]: string }; @@ -106,7 +106,7 @@ const errorMessages: ErrorMessages = { "Can't have non-specified required properties but forbidden additionalTypes at ${ref}", SchemaNoTypeSpecified: "JSON Schema must specify at least one type at ${ref}", SchemaInvalidType: "Invalid type ${type} in JSON Schema at ${ref}", - SchemaFalseNotSupported: "Schema \"false\" is not supported at ${ref}", + SchemaFalseNotSupported: 'Schema "false" is not supported at ${ref}', SchemaInvalidJSONSchemaType: "Value of type ${type} is not valid JSON Schema at ${ref}", SchemaRequiredMustBeStringOrStringArray: "`required` must be string or array of strings, but is ${actual} at ${ref}", @@ -161,25 +161,24 @@ const errorMessages: ErrorMessages = { RendererUnknownOptionValue: "Unknown value ${value} for option ${name}", // TypeScript input - TypeScriptCompilerError: "TypeScript error: ${message}", + TypeScriptCompilerError: "TypeScript error: ${message}" }; -export type ErrorPropertiesForName = Extract extends { properties: infer P, } - ? P - : never; +export type ErrorPropertiesForName = + Extract extends { properties: infer P } ? P : never; export class QuickTypeError extends Error { - constructor ( - readonly errorMessage: string, - readonly messageName: string, - userMessage: string, - readonly properties: StringMap, + public constructor( + public readonly errorMessage: string, + public readonly messageName: string, + public userMessage: string, + public readonly properties: StringMap ) { super(userMessage); } } -export function messageError (kind: N, properties: ErrorPropertiesForName): never { +export function messageError(kind: N, properties: ErrorPropertiesForName): never { const message = errorMessages[kind]; let userMessage: string = message; const propertiesMap = properties as StringMap; @@ -200,10 +199,10 @@ export function messageError (kind: N, properties: ErrorPr throw new QuickTypeError(message, kind, userMessage, propertiesMap); } -export function messageAssert ( +export function messageAssert( assertion: boolean, kind: N, - properties: ErrorPropertiesForName, + properties: ErrorPropertiesForName ): void { if (assertion) return; return messageError(kind, properties); diff --git a/packages/quicktype-core/src/Naming.ts b/packages/quicktype-core/src/Naming.ts index 819163748..f49ad815b 100644 --- a/packages/quicktype-core/src/Naming.ts +++ b/packages/quicktype-core/src/Naming.ts @@ -10,25 +10,25 @@ import { setFilterMap, iterableFirst, iterableEvery, - mapMergeInto, + mapMergeInto } from "collection-utils"; import { defined, assert, panic } from "./support/Support"; export class Namespace { - readonly forbiddenNamespaces: ReadonlySet; + public readonly forbiddenNamespaces: ReadonlySet; - readonly additionalForbidden: ReadonlySet; + public readonly additionalForbidden: ReadonlySet; private readonly _children = new Set(); private readonly _members = new Set(); - constructor ( + public constructor( _name: string, parent: Namespace | undefined, forbiddenNamespaces: Iterable, - additionalForbidden: Iterable, + additionalForbidden: Iterable ) { this.forbiddenNamespaces = new Set(forbiddenNamespaces); this.additionalForbidden = new Set(additionalForbidden); @@ -37,24 +37,24 @@ export class Namespace { } } - private addChild (child: Namespace): void { + private addChild(child: Namespace): void { this._children.add(child); } - get children (): ReadonlySet { + public get children(): ReadonlySet { return this._children; } - get members (): ReadonlySet { + public get members(): ReadonlySet { return this._members; } - get forbiddenNameds (): ReadonlySet { + public get forbiddenNameds(): ReadonlySet { // FIXME: cache return setUnion(this.additionalForbidden, ...Array.from(this.forbiddenNamespaces).map(ns => ns.members)); } - add(named: TName): TName { + public add(named: TName): TName { this._members.add(named); return named; } @@ -80,16 +80,20 @@ export type NameStyle = (rawName: string) => string; export class Namer { private readonly _prefixes: ReadonlySet; - constructor (readonly name: string, readonly nameStyle: NameStyle, prefixes: string[]) { + public constructor( + public readonly name: string, + public readonly nameStyle: NameStyle, + public prefixes: string[] + ) { this._prefixes = new Set(prefixes); } // The namesIterable comes directly out of the context and will // be modified if we assign - assignNames ( + public assignNames( names: ReadonlyMap, forbiddenNamesIterable: Iterable, - namesToAssignIterable: Iterable, + namesToAssignIterable: Iterable ): ReadonlyMap { const forbiddenNames = new Set(forbiddenNamesIterable); const namesToAssign = Array.from(namesToAssignIterable); @@ -108,7 +112,7 @@ export class Namer { proposedNames, proposed => !forbiddenNames.has(namingFunction.nameStyle(proposed)) && - namesToAssign.every(n => n === name || !n.proposeUnstyledNames(names).has(proposed)), + namesToAssign.every(n => n === name || !n.proposeUnstyledNames(names).has(proposed)) ); if (maybeUniqueName !== undefined) { const styledName = namingFunction.nameStyle(maybeUniqueName); @@ -165,10 +169,10 @@ const funPrefixes = [ "Magenta", "Frisky", "Mischievous", - "Braggadocious", + "Braggadocious" ]; -export function funPrefixNamer (name: string, nameStyle: NameStyle): Namer { +export function funPrefixNamer(name: string, nameStyle: NameStyle): Namer { return new Namer(name, nameStyle, funPrefixes); } @@ -181,30 +185,36 @@ export abstract class Name { private readonly _associates = new Set(); // If a Named is fixed, the namingFunction is undefined. - constructor (private readonly _namingFunction: Namer | undefined, readonly order: number) {} + public constructor( + private readonly _namingFunction: Namer | undefined, + public readonly order: number + ) {} - addAssociate (associate: AssociatedName): void { + public addAssociate(associate: AssociatedName): void { this._associates.add(associate); } - abstract get dependencies (): readonly Name[]; + public abstract get dependencies(): readonly Name[]; - isFixed (): this is FixedName { + public isFixed(): this is FixedName { return this instanceof FixedName; } - get namingFunction (): Namer { + public get namingFunction(): Namer { return defined(this._namingFunction); } // Must return at least one proposal. The proposals are considered in order. - abstract proposeUnstyledNames (names: ReadonlyMap): ReadonlySet; + public abstract proposeUnstyledNames(names: ReadonlyMap): ReadonlySet; - firstProposedName (names: ReadonlyMap): string { + public firstProposedName(names: ReadonlyMap): string { return defined(iterableFirst(this.proposeUnstyledNames(names))); } - nameAssignments (forbiddenNames: ReadonlySet, assignedName: string): ReadonlyMap | null { + public nameAssignments( + forbiddenNames: ReadonlySet, + assignedName: string + ): ReadonlyMap | null { if (forbiddenNames.has(assignedName)) return null; const assignments = new Map([[this, assignedName]]); for (const an of this._associates) { @@ -222,23 +232,23 @@ export abstract class Name { // FIXME: FixedNameds should optionally be user-configurable export class FixedName extends Name { - constructor (private readonly _fixedName: string) { + public constructor(private readonly _fixedName: string) { super(undefined, 0); } - get dependencies (): readonly Name[] { + public get dependencies(): readonly Name[] { return []; } - addAssociate (_: AssociatedName): never { + public addAssociate(_: AssociatedName): never { return panic("Cannot add associates to fixed names"); } - get fixedName (): string { + public get fixedName(): string { return this._fixedName; } - proposeUnstyledNames (_?: ReadonlyMap): ReadonlySet { + public proposeUnstyledNames(_?: ReadonlyMap): ReadonlySet { return panic("Only fixedName should be called on FixedName."); } } @@ -246,30 +256,34 @@ export class FixedName extends Name { export class SimpleName extends Name { private readonly _unstyledNames: ReadonlySet; - constructor (unstyledNames: Iterable, namingFunction: Namer, order: number) { + public constructor(unstyledNames: Iterable, namingFunction: Namer, order: number) { super(namingFunction, order); this._unstyledNames = new Set(unstyledNames); } - get dependencies (): readonly Name[] { + public get dependencies(): readonly Name[] { return []; } - proposeUnstyledNames (_?: ReadonlyMap): ReadonlySet { + public proposeUnstyledNames(_?: ReadonlyMap): ReadonlySet { return this._unstyledNames; } } export class AssociatedName extends Name { - constructor (private readonly _sponsor: Name, order: number, readonly getName: (sponsorName: string) => string) { + public constructor( + private readonly _sponsor: Name, + order: number, + public readonly getName: (sponsorName: string) => string + ) { super(undefined, order); } - get dependencies (): readonly Name[] { + public get dependencies(): readonly Name[] { return [this._sponsor]; } - proposeUnstyledNames (_?: ReadonlyMap): never { + public proposeUnstyledNames(_?: ReadonlyMap): never { return panic("AssociatedName must be assigned via its sponsor"); } } @@ -277,10 +291,10 @@ export class AssociatedName extends Name { export class DependencyName extends Name { private readonly _dependencies: ReadonlySet; - constructor ( + public constructor( namingFunction: Namer | undefined, order: number, - private readonly _proposeUnstyledName: (lookup: (n: Name) => string) => string, + private readonly _proposeUnstyledName: (lookup: (n: Name) => string) => string ) { super(namingFunction, order); const dependencies: Name[] = []; @@ -291,21 +305,21 @@ export class DependencyName extends Name { this._dependencies = new Set(dependencies); } - get dependencies (): readonly Name[] { + public get dependencies(): readonly Name[] { return Array.from(this._dependencies); } - proposeUnstyledNames (names: ReadonlyMap): ReadonlySet { + public proposeUnstyledNames(names: ReadonlyMap): ReadonlySet { return new Set([ this._proposeUnstyledName(n => { assert(this._dependencies.has(n), "DependencyName proposer is not pure"); return defined(names.get(n)); - }), + }) ]); } } -export function keywordNamespace (name: string, keywords: string[]) { +export function keywordNamespace(name: string, keywords: string[]) { const ns = new Namespace(name, undefined, [], []); for (const kw of keywords) { ns.add(new FixedName(kw)); @@ -314,7 +328,7 @@ export function keywordNamespace (name: string, keywords: string[]) { return ns; } -function allNamespacesRecursively (namespaces: Iterable): ReadonlySet { +function allNamespacesRecursively(namespaces: Iterable): ReadonlySet { return setUnion(namespaces, ...Array.from(setMap(namespaces, ns => allNamespacesRecursively(ns.children)))); } @@ -323,26 +337,26 @@ class NamingContext { private readonly _namedsForName: Map> = new Map(); - readonly namespaces: ReadonlySet; + public readonly namespaces: ReadonlySet; - constructor (rootNamespaces: Iterable) { + public constructor(rootNamespaces: Iterable) { this.namespaces = allNamespacesRecursively(rootNamespaces); } - get names (): ReadonlyMap { + public get names(): ReadonlyMap { return this._names; } - isReadyToBeNamed = (named: Name): boolean => { + public isReadyToBeNamed(named: Name): boolean { if (this._names.has(named)) return false; return named.dependencies.every((n: Name) => this._names.has(n)); - }; + } - areForbiddensFullyNamed (namespace: Namespace): boolean { + public areForbiddensFullyNamed(namespace: Namespace): boolean { return iterableEvery(namespace.forbiddenNameds, n => this._names.has(n)); } - isConflicting = (namedNamespace: Namespace, proposed: string): boolean => { + public isConflicting(namedNamespace: Namespace, proposed: string): boolean { const namedsForProposed = this._namedsForName.get(proposed); // If the name is not assigned at all, there is no conflict. if (namedsForProposed === undefined) return false; @@ -354,9 +368,9 @@ class NamingContext { } return false; - }; + } - assign = (named: Name, namedNamespace: Namespace, name: string): void => { + public assign(named: Name, namedNamespace: Namespace, name: string): void { assert(!this.names.has(named), `Name "${name}" assigned twice`); assert(!this.isConflicting(namedNamespace, name), `Assigned name "${name}" conflicts`); this._names.set(named, name); @@ -367,11 +381,11 @@ class NamingContext { } namedsForName.add(named); - }; + } } // Naming algorithm -export function assignNames (rootNamespaces: Iterable): ReadonlyMap { +export function assignNames(rootNamespaces: Iterable): ReadonlyMap { const ctx = new NamingContext(rootNamespaces); // Assign all fixed names. @@ -415,7 +429,7 @@ export function assignNames (rootNamespaces: Iterable): ReadonlyMap n.namingFunction); for (const [namer, namedsForNamingFunction] of byNamingFunction) { const byProposed = setGroupBy(namedsForNamingFunction, n => - n.namingFunction.nameStyle(n.firstProposedName(ctx.names)), + n.namingFunction.nameStyle(n.firstProposedName(ctx.names)) ); for (const [, nameds] of byProposed) { // 3. Use each set's naming function to name its members. diff --git a/packages/quicktype-core/src/Renderer.ts b/packages/quicktype-core/src/Renderer.ts index b0665f36f..f22dc7c0a 100644 --- a/packages/quicktype-core/src/Renderer.ts +++ b/packages/quicktype-core/src/Renderer.ts @@ -1,11 +1,11 @@ import { iterableEnumerate } from "collection-utils"; import { type TypeGraph } from "./TypeGraph"; -import { type Name, type Namespace} from "./Naming"; +import { type Name, type Namespace } from "./Naming"; import { assignNames } from "./Naming"; -import { type Source, type Sourcelike, type NewlineSource} from "./Source"; +import { type Source, type Sourcelike, type NewlineSource } from "./Source"; import { annotated, sourcelikeToSource, newline } from "./Source"; -import { type AnnotationData} from "./Annotation"; +import { type AnnotationData } from "./Annotation"; import { IssueAnnotationData } from "./Annotation"; import { assert, panic } from "./support/Support"; import { type TargetLanguage } from "./TargetLanguage"; @@ -19,7 +19,7 @@ export interface RenderResult { export type BlankLinePosition = "none" | "interposing" | "leading" | "leading-and-interposing"; export type BlankLineConfig = BlankLinePosition | [BlankLinePosition, number]; -function getBlankLineConfig (cfg: BlankLineConfig): { count: number, position: BlankLinePosition, } { +function getBlankLineConfig(cfg: BlankLineConfig): { count: number; position: BlankLinePosition } { if (Array.isArray(cfg)) { return { position: cfg[0], count: cfg[1] }; } @@ -27,7 +27,7 @@ function getBlankLineConfig (cfg: BlankLineConfig): { count: number, position: B return { position: cfg, count: 1 }; } -function lineIndentation (line: string): { indent: number, text: string | null, } { +function lineIndentation(line: string): { indent: number; text: string | null } { const len = line.length; let indent = 0; for (let i = 0; i < len; i++) { @@ -54,48 +54,44 @@ export type ForEachPosition = "first" | "last" | "middle" | "only"; class EmitContext { private _lastNewline?: NewlineSource; - // @ts-expect-error: Initialized in startEmit, which is called from the constructor private readonly _emitted: Sourcelike[]; - // @ts-expect-error: Initialized in startEmit, which is called from the constructor private readonly _currentEmitTarget: Sourcelike[]; - // @ts-expect-error: Initialized in startEmit, which is called from the constructor private _numBlankLinesNeeded: number; - // @ts-expect-error: Initialized in startEmit, which is called from the constructor private _preventBlankLine: boolean; - constructor () { + public constructor() { this._currentEmitTarget = this._emitted = []; this._numBlankLinesNeeded = 0; this._preventBlankLine = true; // no blank lines at start of file } - get isEmpty (): boolean { + public get isEmpty(): boolean { return this._emitted.length === 0; } - get isNested (): boolean { + public get isNested(): boolean { return this._emitted !== this._currentEmitTarget; } - get source (): Sourcelike[] { + public get source(): Sourcelike[] { return this._emitted; } - private pushItem (item: Sourcelike): void { + public pushItem(item: Sourcelike): void { this._currentEmitTarget.push(item); this._preventBlankLine = false; } - emitNewline (): void { + public emitNewline(): void { const nl = newline(); this.pushItem(nl); this._lastNewline = nl; } - emitItem (item: Sourcelike): void { + public emitItem(item: Sourcelike): void { if (!this.isEmpty) { for (let i = 0; i < this._numBlankLinesNeeded; i++) { this.emitNewline(); @@ -106,22 +102,22 @@ class EmitContext { this.pushItem(item); } - containsItem (item: Sourcelike): boolean { + public containsItem(item: Sourcelike): boolean { const existingItem = this._currentEmitTarget.find((value: Sourcelike) => item === value); return existingItem !== undefined; } - ensureBlankLine (numBlankLines: number): void { + public ensureBlankLine(numBlankLines: number): void { if (this._preventBlankLine) return; this._numBlankLinesNeeded = Math.max(this._numBlankLinesNeeded, numBlankLines); } - preventBlankLine (): void { + public preventBlankLine(): void { this._numBlankLinesNeeded = 0; this._preventBlankLine = true; } - changeIndent (offset: number): void { + public changeIndent(offset: number): void { if (this._lastNewline === undefined) { return panic("Cannot change indent for the first line"); } @@ -143,9 +139,9 @@ export abstract class Renderer { private _emitContext: EmitContext; - constructor ( + public constructor( protected readonly targetLanguage: TargetLanguage, - renderContext: RenderContext, + renderContext: RenderContext ) { this.typeGraph = renderContext.typeGraph; this.leadingComments = renderContext.leadingComments; @@ -155,19 +151,20 @@ export abstract class Renderer { this._emitContext = new EmitContext(); } - ensureBlankLine (numBlankLines = 1): void { + // FIXME: make protected once JavaDateTimeRenderer is refactored + public ensureBlankLine(numBlankLines = 1): void { this._emitContext.ensureBlankLine(numBlankLines); } - preventBlankLine (): void { + protected preventBlankLine(): void { this._emitContext.preventBlankLine(); } - emitItem (item: Sourcelike): void { + protected emitItem(item: Sourcelike): void { this._emitContext.emitItem(item); } - emitItemOnce (item: Sourcelike): boolean { + protected emitItemOnce(item: Sourcelike): boolean { if (this._emitContext.containsItem(item)) { return false; } @@ -176,7 +173,7 @@ export abstract class Renderer { return true; } - emitLineOnce (...lineParts: Sourcelike[]): void { + protected emitLineOnce(...lineParts: Sourcelike[]): void { let lineEmitted = true; if (lineParts.length === 1) { lineEmitted = this.emitItemOnce(lineParts[0]); @@ -189,7 +186,8 @@ export abstract class Renderer { } } - emitLine (...lineParts: Sourcelike[]): void { + // FIXME: make protected once JavaDateTimeRenderer is refactored + public emitLine(...lineParts: Sourcelike[]): void { if (lineParts.length === 1) { this._emitContext.emitItem(lineParts[0]); } else if (lineParts.length > 1) { @@ -199,7 +197,7 @@ export abstract class Renderer { this._emitContext.emitNewline(); } - emitMultiline (linesString: string): void { + protected emitMultiline(linesString: string): void { const lines = linesString.split("\n"); const numLines = lines.length; if (numLines === 0) return; @@ -224,7 +222,7 @@ export abstract class Renderer { } } - gatherSource (emitter: () => void): Sourcelike[] { + protected gatherSource(emitter: () => void): Sourcelike[] { const oldEmitContext = this._emitContext; this._emitContext = new EmitContext(); emitter(); @@ -234,19 +232,19 @@ export abstract class Renderer { return source; } - emitGatheredSource (items: Sourcelike[]): void { + protected emitGatheredSource(items: Sourcelike[]): void { for (const item of items) { this._emitContext.emitItem(item); } } - emitAnnotated (annotation: AnnotationData, emitter: () => void): void { + protected emitAnnotated(annotation: AnnotationData, emitter: () => void): void { const lines = this.gatherSource(emitter); const source = sourcelikeToSource(lines); this._emitContext.emitItem(annotated(annotation, source)); } - emitIssue (message: string, emitter: () => void): void { + protected emitIssue(message: string, emitter: () => void): void { this.emitAnnotated(new IssueAnnotationData(message), emitter); } @@ -257,11 +255,11 @@ export abstract class Renderer { this._emitContext.emitNewline(); }; - changeIndent (offset: number): void { + protected changeIndent(offset: number): void { this._emitContext.changeIndent(offset); } - iterableForEach(iterable: Iterable, emitter: (v: T, position: ForEachPosition) => void): void { + protected iterableForEach(iterable: Iterable, emitter: (v: T, position: ForEachPosition) => void): void { const items = Array.from(iterable); let onFirst = true; for (const [i, v] of iterableEnumerate(items)) { @@ -272,11 +270,11 @@ export abstract class Renderer { } } - forEach( + protected forEach( iterable: Iterable<[K, V]>, interposedBlankLines: number, leadingBlankLines: number, - emitter: (v: V, k: K, position: ForEachPosition) => void, + emitter: (v: V, k: K, position: ForEachPosition) => void ): boolean { let didEmit = false; this.iterableForEach(iterable, ([k, v], position) => { @@ -292,10 +290,10 @@ export abstract class Renderer { return didEmit; } - forEachWithBlankLines( + protected forEachWithBlankLines( iterable: Iterable<[K, V]>, blankLineConfig: BlankLineConfig, - emitter: (v: V, k: K, position: ForEachPosition) => void, + emitter: (v: V, k: K, position: ForEachPosition) => void ): boolean { const { position, count } = getBlankLineConfig(blankLineConfig); const interposing = ["interposing", "leading-and-interposing"].includes(position); @@ -303,20 +301,21 @@ export abstract class Renderer { return this.forEach(iterable, interposing ? count : 0, leading ? count : 0, emitter); } - indent (fn: () => void): void { + // FIXME: make protected once JavaDateTimeRenderer is refactored + public indent(fn: () => void): void { this.changeIndent(1); fn(); this.changeIndent(-1); } - protected abstract setUpNaming (): Iterable; - protected abstract emitSource (givenOutputFilename: string): void; + protected abstract setUpNaming(): Iterable; + protected abstract emitSource(givenOutputFilename: string): void; - private assignNames (): ReadonlyMap { + protected assignNames(): ReadonlyMap { return assignNames(this.setUpNaming()); } - protected initializeEmitContextForFilename (filename: string): void { + protected initializeEmitContextForFilename(filename: string): void { if (this._finishedEmitContexts.has(filename.toLowerCase())) { const existingEmitContext = this._finishedEmitContexts.get(filename.toLowerCase()); if (existingEmitContext !== undefined) { @@ -325,10 +324,10 @@ export abstract class Renderer { } } - protected finishFile (filename: string): void { + protected finishFile(filename: string): void { if (this._finishedFiles.has(filename)) { console.log( - `[WARNING] Tried to emit file ${filename} more than once. If performing multi-file output this warning can be safely ignored.`, + `[WARNING] Tried to emit file ${filename} more than once. If performing multi-file output this warning can be safely ignored.` ); } @@ -340,7 +339,7 @@ export abstract class Renderer { this._emitContext = new EmitContext(); } - render (givenOutputFilename: string): RenderResult { + public render(givenOutputFilename: string): RenderResult { this._names = this.assignNames(); this.emitSource(givenOutputFilename); if (!this._emitContext.isEmpty) { @@ -350,7 +349,7 @@ export abstract class Renderer { return { sources: this._finishedFiles, names: this._names }; } - get names (): ReadonlyMap { + public get names(): ReadonlyMap { if (this._names === undefined) { return panic("Names accessed before they were assigned"); } diff --git a/packages/quicktype-core/src/RendererOptions.ts b/packages/quicktype-core/src/RendererOptions.ts index f3fae9ffa..4aab7d4ec 100644 --- a/packages/quicktype-core/src/RendererOptions.ts +++ b/packages/quicktype-core/src/RendererOptions.ts @@ -27,15 +27,15 @@ export interface OptionDefinition { * subclasses, `BooleanOption`, `EnumOption`, or `StringOption`. */ export abstract class Option { - readonly definition: OptionDefinition; + public readonly definition: OptionDefinition; - constructor (definition: OptionDefinition) { + public constructor(definition: OptionDefinition) { definition.renderer = true; this.definition = definition; assert(definition.kind !== undefined, "Renderer option kind must be defined"); } - getValue (values: { [name: string]: any, }): T { + public getValue(values: { [name: string]: any }): T { const value = values[this.definition.name]; if (value === undefined) { return this.definition.defaultValue; @@ -44,7 +44,7 @@ export abstract class Option { return value; } - get cliDefinitions (): { actual: OptionDefinition[], display: OptionDefinition[], } { + public get cliDefinitions(): { actual: OptionDefinition[]; display: OptionDefinition[] } { return { actual: [this.definition], display: [this.definition] }; } } @@ -52,11 +52,11 @@ export abstract class Option { export type OptionValueType = O extends Option ? T : never; export type OptionValues = { [P in keyof T]: OptionValueType }; -export function getOptionValues, }> ( +export function getOptionValues }>( options: T, - untypedOptionValues: { [name: string]: any, }, + untypedOptionValues: { [name: string]: any } ): OptionValues { - const optionValues: { [name: string]: any, } = {}; + const optionValues: { [name: string]: any } = {}; for (const name of Object.getOwnPropertyNames(options)) { optionValues[name] = options[name].getValue(untypedOptionValues); } @@ -74,32 +74,32 @@ export class BooleanOption extends Option { * @param defaultValue The default value. * @param kind Whether it's a primary or secondary option. */ - constructor (name: string, description: string, defaultValue: boolean, kind: OptionKind = "primary") { + public constructor(name: string, description: string, defaultValue: boolean, kind: OptionKind = "primary") { super({ name, kind, type: Boolean, description, - defaultValue, + defaultValue }); } - get cliDefinitions (): { actual: OptionDefinition[], display: OptionDefinition[], } { + public get cliDefinitions(): { actual: OptionDefinition[]; display: OptionDefinition[] } { const negated = Object.assign({}, this.definition, { name: `no-${this.definition.name}`, - defaultValue: !this.definition.defaultValue, + defaultValue: !this.definition.defaultValue }); const display = Object.assign({}, this.definition, { name: `[no-]${this.definition.name}`, - description: `${this.definition.description} (${this.definition.defaultValue ? "on" : "off"} by default)`, + description: `${this.definition.description} (${this.definition.defaultValue ? "on" : "off"} by default)` }); return { display: [display], - actual: [this.definition, negated], + actual: [this.definition, negated] }; } - getValue (values: { [name: string]: any, }): boolean { + public getValue(values: { [name: string]: any }): boolean { let value = values[this.definition.name]; if (value === undefined) { value = this.definition.defaultValue; @@ -125,12 +125,12 @@ export class BooleanOption extends Option { } export class StringOption extends Option { - constructor ( + public constructor( name: string, description: string, typeLabel: string, defaultValue: string, - kind: OptionKind = "primary", + kind: OptionKind = "primary" ) { const definition = { name, @@ -138,21 +138,21 @@ export class StringOption extends Option { type: String, description, typeLabel, - defaultValue, + defaultValue }; super(definition); } } export class EnumOption extends Option { - private readonly _values: { [name: string]: T, }; + private readonly _values: { [name: string]: T }; - constructor ( + public constructor( name: string, description: string, values: Array<[string, T]>, defaultValue: string | undefined = undefined, - kind: OptionKind = "primary", + kind: OptionKind = "primary" ) { if (defaultValue === undefined) { defaultValue = values[0][0]; @@ -165,7 +165,7 @@ export class EnumOption extends Option { description, typeLabel: values.map(([n, _]) => n).join("|"), legalValues: values.map(([n, _]) => n), - defaultValue, + defaultValue }; super(definition); @@ -175,7 +175,7 @@ export class EnumOption extends Option { } } - getValue (values: { [name: string]: any, }): T { + public getValue(values: { [name: string]: any }): T { let name: string = values[this.definition.name]; if (name === undefined) { name = this.definition.defaultValue; diff --git a/packages/quicktype-core/src/Run.ts b/packages/quicktype-core/src/Run.ts index 1faaed8e6..2e2790781 100644 --- a/packages/quicktype-core/src/Run.ts +++ b/packages/quicktype-core/src/Run.ts @@ -8,7 +8,7 @@ import { combineClasses } from "./rewrites/CombineClasses"; import { inferMaps } from "./rewrites/InferMaps"; import { type StringTypeMapping } from "./TypeBuilder"; import { TypeBuilder } from "./TypeBuilder"; -import { type TypeGraph} from "./TypeGraph"; +import { type TypeGraph } from "./TypeGraph"; import { noneToAny, optionalToNullable, removeIndirectionIntersections } from "./TypeGraph"; import { initTypeNames } from "./attributes/TypeNames"; import { gatherNames } from "./GatherNames"; @@ -23,7 +23,7 @@ import { makeTransformations } from "./MakeTransformations"; import { type TransformedStringTypeKind } from "./Type"; import { type Comment } from "./support/Comments"; -export function getTargetLanguage (nameOrInstance: string | TargetLanguage): TargetLanguage { +export function getTargetLanguage(nameOrInstance: string | TargetLanguage): TargetLanguage { if (typeof nameOrInstance === "object") { return nameOrInstance; } @@ -37,7 +37,7 @@ export function getTargetLanguage (nameOrInstance: string | TargetLanguage): Tar } export interface RendererOptions { - [name: string]: string | boolean; + [name: string]: string | boolean; } export interface InferenceFlag { @@ -54,14 +54,14 @@ export const inferenceFlagsObject = { description: "Detect maps", negationDescription: "Don't infer maps, always use classes", explanation: "Infer maps when object keys look like map keys.", - order: 1, + order: 1 }, /** Whether to infer enum types from JSON data */ inferEnums: { description: "Detect enums", negationDescription: "Don't infer enums, always use strings", explanation: "If string values occur within a relatively small domain,\ninfer them as enum values.", - order: 2, + order: 2 }, /** Whether to convert UUID strings to UUID objects */ inferUuids: { @@ -69,7 +69,7 @@ export const inferenceFlagsObject = { negationDescription: "Don't convert UUIDs to UUID objects", explanation: "Detect UUIDs like '123e4567-e89b-12d3-a456-426655440000' (partial support).", stringType: "uuid" as TransformedStringTypeKind, - order: 3, + order: 3 }, /** Whether to assume that JSON strings that look like dates are dates */ inferDateTimes: { @@ -77,24 +77,24 @@ export const inferenceFlagsObject = { negationDescription: "Don't infer dates or times", explanation: "Infer dates from strings (partial support).", stringType: "date-time" as TransformedStringTypeKind, - order: 4, + order: 4 }, /** Whether to convert stringified integers to integers */ inferIntegerStrings: { description: "Detect integers in strings", negationDescription: "Don't convert stringified integers to integers", - explanation: "Automatically convert stringified integers to integers.\nFor example, \"1\" is converted to 1.", + explanation: 'Automatically convert stringified integers to integers.\nFor example, "1" is converted to 1.', stringType: "integer-string" as TransformedStringTypeKind, - order: 5, + order: 5 }, /** Whether to convert stringified booleans to boolean values */ inferBooleanStrings: { description: "Detect booleans in strings", negationDescription: "Don't convert stringified booleans to booleans", explanation: - "Automatically convert stringified booleans to booleans.\nFor example, \"true\" is converted to true.", + 'Automatically convert stringified booleans to booleans.\nFor example, "true" is converted to true.', stringType: "bool-string" as TransformedStringTypeKind, - order: 6, + order: 6 }, /** Combine similar classes. This doesn't apply to classes from a schema, only from inference. */ combineClasses: { @@ -102,7 +102,7 @@ export const inferenceFlagsObject = { negationDescription: "Don't combine similar classes", explanation: "Combine classes with significantly overlapping properties,\ntreating contingent properties as nullable.", - order: 7, + order: 7 }, /** Whether to treat $ref as references within JSON */ ignoreJsonRefs: { @@ -110,8 +110,8 @@ export const inferenceFlagsObject = { negationDescription: "Treat $ref as a reference in JSON", explanation: "Like in JSON Schema, allow objects like\n'{ $ref: \"#/foo/bar\" }' to refer\nto another part of the input.", - order: 8, - }, + order: 8 + } }; export type InferenceFlagName = keyof typeof inferenceFlagsObject; export const inferenceFlagNames = Object.getOwnPropertyNames(inferenceFlagsObject) as InferenceFlagName[]; @@ -194,7 +194,7 @@ const defaultOptions: NonInferenceOptions = { debugPrintGatherNames: false, debugPrintTransformations: false, debugPrintTimes: false, - debugPrintSchemaResolving: false, + debugPrintSchemaResolving: false }; export interface RunContext { @@ -214,7 +214,7 @@ interface GraphInputs { typeBuilder: TypeBuilder; } -function makeDefaultInferenceFlags (): InferenceFlags { +function makeDefaultInferenceFlags(): InferenceFlags { const flags = {} as InferenceFlags; for (const flag of inferenceFlagNames) { flags[flag] = true; @@ -228,7 +228,7 @@ export const defaultInferenceFlags = makeDefaultInferenceFlags(); class Run implements RunContext { private readonly _options: Options; - constructor (options: Partial) { + public constructor(options: Partial) { // We must not overwrite defaults with undefined values, which // we sometimes get. this._options = Object.assign({}, defaultOptions, defaultInferenceFlags); @@ -240,7 +240,7 @@ class Run implements RunContext { } } - get stringTypeMapping (): StringTypeMapping { + public get stringTypeMapping(): StringTypeMapping { const targetLanguage = getTargetLanguage(this._options.lang); const mapping = new Map(targetLanguage.stringTypeMapping); for (const flag of inferenceFlagNames) { @@ -253,19 +253,19 @@ class Run implements RunContext { return mapping; } - get debugPrintReconstitution (): boolean { + public get debugPrintReconstitution(): boolean { return this._options.debugPrintReconstitution === true; } - get debugPrintTransformations (): boolean { + public get debugPrintTransformations(): boolean { return this._options.debugPrintTransformations; } - get debugPrintSchemaResolving (): boolean { + public get debugPrintSchemaResolving(): boolean { return this._options.debugPrintSchemaResolving; } - async timeSync(name: string, f: () => Promise): Promise { + public async timeSync(name: string, f: () => Promise): Promise { const start = Date.now(); const result = await f(); const end = Date.now(); @@ -276,7 +276,7 @@ class Run implements RunContext { return result; } - time(name: string, f: () => T): T { + public time(name: string, f: () => T): T { const start = Date.now(); const result = f(); const end = Date.now(); @@ -287,7 +287,7 @@ class Run implements RunContext { return result; } - private makeGraphInputs (): GraphInputs { + private makeGraphInputs(): GraphInputs { const targetLanguage = getTargetLanguage(this._options.lang); const stringTypeMapping = this.stringTypeMapping; const conflateNumbers = !targetLanguage.supportsUnionsWithBothNumberTypes; @@ -297,13 +297,13 @@ class Run implements RunContext { this._options.alphabetizeProperties, this._options.allPropertiesOptional, this._options.checkProvenance, - false, + false ); return { targetLanguage, stringTypeMapping, conflateNumbers, typeBuilder }; } - private async makeGraph (allInputs: InputData): Promise { + private async makeGraph(allInputs: InputData): Promise { const graphInputs = this.makeGraphInputs(); await this.timeSync( @@ -314,14 +314,14 @@ class Run implements RunContext { graphInputs.typeBuilder, this._options.inferMaps, this._options.inferEnums, - this._options.fixedTopLevels, - ), + this._options.fixedTopLevels + ) ); return this.processGraph(allInputs, graphInputs); } - private makeGraphSync (allInputs: InputData): TypeGraph { + private makeGraphSync(allInputs: InputData): TypeGraph { const graphInputs = this.makeGraphInputs(); this.time("read input", () => @@ -330,14 +330,14 @@ class Run implements RunContext { graphInputs.typeBuilder, this._options.inferMaps, this._options.inferEnums, - this._options.fixedTopLevels, - ), + this._options.fixedTopLevels + ) ); return this.processGraph(allInputs, graphInputs); } - private processGraph (allInputs: InputData, graphInputs: GraphInputs): TypeGraph { + private processGraph(allInputs: InputData, graphInputs: GraphInputs): TypeGraph { const { targetLanguage, stringTypeMapping, conflateNumbers, typeBuilder } = graphInputs; let graph = typeBuilder.finish(); @@ -351,7 +351,7 @@ class Run implements RunContext { if (typeBuilder.didAddForwardingIntersection || !this._options.ignoreJsonRefs) { this.time( "remove indirection intersections", - () => graph = removeIndirectionIntersections(graph, stringTypeMapping, debugPrintReconstitution), + () => (graph = removeIndirectionIntersections(graph, stringTypeMapping, debugPrintReconstitution)) ); } @@ -364,11 +364,11 @@ class Run implements RunContext { this.time( "resolve intersections", () => - [graph, intersectionsDone] = resolveIntersections( + ([graph, intersectionsDone] = resolveIntersections( graph, stringTypeMapping, - debugPrintReconstitution, - ), + debugPrintReconstitution + )) ); } @@ -376,13 +376,13 @@ class Run implements RunContext { this.time( "flatten unions", () => - [graph, unionsDone] = flattenUnions( + ([graph, unionsDone] = flattenUnions( graph, stringTypeMapping, conflateNumbers, true, - debugPrintReconstitution, - ), + debugPrintReconstitution + )) ); } @@ -395,31 +395,31 @@ class Run implements RunContext { this.time( "replace object type", () => - graph = replaceObjectType( + (graph = replaceObjectType( graph, stringTypeMapping, conflateNumbers, targetLanguage.supportsFullObjectType, - debugPrintReconstitution, - ), + debugPrintReconstitution + )) ); do { this.time( "flatten unions", () => - [graph, unionsDone] = flattenUnions( + ([graph, unionsDone] = flattenUnions( graph, stringTypeMapping, conflateNumbers, false, - debugPrintReconstitution, - ), + debugPrintReconstitution + )) ); } while (!unionsDone); if (this._options.combineClasses) { const combinedGraph = this.time("combine classes", () => - combineClasses(this, graph, this._options.alphabetizeProperties, true, false, debugPrintReconstitution), + combineClasses(this, graph, this._options.alphabetizeProperties, true, false, debugPrintReconstitution) ); if (combinedGraph === graph) { graph = combinedGraph; @@ -427,14 +427,14 @@ class Run implements RunContext { this.time( "combine classes cleanup", () => - graph = combineClasses( + (graph = combineClasses( this, combinedGraph, this._options.alphabetizeProperties, false, true, - debugPrintReconstitution, - ), + debugPrintReconstitution + )) ); } } @@ -442,7 +442,7 @@ class Run implements RunContext { if (this._options.inferMaps) { for (;;) { const newGraph = this.time("infer maps", () => - inferMaps(graph, stringTypeMapping, true, debugPrintReconstitution), + inferMaps(graph, stringTypeMapping, true, debugPrintReconstitution) ); if (newGraph === graph) { break; @@ -453,49 +453,49 @@ class Run implements RunContext { } const enumInference = allInputs.needSchemaProcessing ? "all" : this._options.inferEnums ? "infer" : "none"; - this.time("expand strings", () => graph = expandStrings(this, graph, enumInference)); + this.time("expand strings", () => (graph = expandStrings(this, graph, enumInference))); this.time( "flatten unions", () => - [graph, unionsDone] = flattenUnions( + ([graph, unionsDone] = flattenUnions( graph, stringTypeMapping, conflateNumbers, false, - debugPrintReconstitution, - ), + debugPrintReconstitution + )) ); assert(unionsDone, "We should only have to flatten unions once after expanding strings"); if (allInputs.needSchemaProcessing) { this.time( "flatten strings", - () => graph = flattenStrings(graph, stringTypeMapping, debugPrintReconstitution), + () => (graph = flattenStrings(graph, stringTypeMapping, debugPrintReconstitution)) ); } - this.time("none to any", () => graph = noneToAny(graph, stringTypeMapping, debugPrintReconstitution)); + this.time("none to any", () => (graph = noneToAny(graph, stringTypeMapping, debugPrintReconstitution))); if (!targetLanguage.supportsOptionalClassProperties) { this.time( "optional to nullable", - () => graph = optionalToNullable(graph, stringTypeMapping, debugPrintReconstitution), + () => (graph = optionalToNullable(graph, stringTypeMapping, debugPrintReconstitution)) ); } - this.time("fixed point", () => graph = graph.rewriteFixedPoint(false, debugPrintReconstitution)); + this.time("fixed point", () => (graph = graph.rewriteFixedPoint(false, debugPrintReconstitution))); - this.time("make transformations", () => graph = makeTransformations(this, graph, targetLanguage)); + this.time("make transformations", () => (graph = makeTransformations(this, graph, targetLanguage))); this.time( "flatten unions", () => - [graph, unionsDone] = flattenUnions( + ([graph, unionsDone] = flattenUnions( graph, stringTypeMapping, conflateNumbers, false, - debugPrintReconstitution, - ), + debugPrintReconstitution + )) ); assert(unionsDone, "We should only have to flatten unions once after making transformations"); @@ -508,7 +508,7 @@ class Run implements RunContext { // is different from the one we started out with. this.time( "GC", - () => graph = graph.garbageCollect(this._options.alphabetizeProperties, debugPrintReconstitution), + () => (graph = graph.garbageCollect(this._options.alphabetizeProperties, debugPrintReconstitution)) ); if (this._options.debugPrintGraph) { @@ -516,7 +516,7 @@ class Run implements RunContext { } this.time("gather names", () => - gatherNames(graph, !allInputs.needSchemaProcessing, this._options.debugPrintGatherNames), + gatherNames(graph, !allInputs.needSchemaProcessing, this._options.debugPrintGatherNames) ); if (this._options.debugPrintGraph) { graph.printGraph(); @@ -525,14 +525,13 @@ class Run implements RunContext { return graph; } - private makeSimpleTextResult (lines: string[]): MultiFileRenderResult { - return new Map([[this._options.outputFilename, { lines, annotations: [] }]] as Array<[ - string, - SerializedRenderResult - ]>); + private makeSimpleTextResult(lines: string[]): MultiFileRenderResult { + return new Map([[this._options.outputFilename, { lines, annotations: [] }]] as Array< + [string, SerializedRenderResult] + >); } - private preRun (): MultiFileRenderResult | [InputData, TargetLanguage] { + private preRun(): MultiFileRenderResult | [InputData, TargetLanguage] { // FIXME: This makes quicktype not quite reentrant initTypeNames(); @@ -551,7 +550,7 @@ class Run implements RunContext { return [inputData, targetLanguage]; } - async run (): Promise { + public async run(): Promise { const preRunResult = this.preRun(); if (!Array.isArray(preRunResult)) { return preRunResult; @@ -564,7 +563,7 @@ class Run implements RunContext { return this.renderGraph(targetLanguage, graph); } - runSync (): MultiFileRenderResult { + public runSync(): MultiFileRenderResult { const preRunResult = this.preRun(); if (!Array.isArray(preRunResult)) { return preRunResult; @@ -577,7 +576,7 @@ class Run implements RunContext { return this.renderGraph(targetLanguage, graph); } - private renderGraph (targetLanguage: TargetLanguage, graph: TypeGraph): MultiFileRenderResult { + private renderGraph(targetLanguage: TargetLanguage, graph: TypeGraph): MultiFileRenderResult { if (this._options.noRender) { return this.makeSimpleTextResult(["Done.", ""]); } @@ -588,7 +587,7 @@ class Run implements RunContext { this._options.alphabetizeProperties, this._options.leadingComments, this._options.rendererOptions, - this._options.indentation, + this._options.indentation ); } } @@ -599,19 +598,19 @@ class Run implements RunContext { * @param options Partial options. For options that are not defined, the * defaults will be used. */ -export async function quicktypeMultiFile (options: Partial): Promise { +export async function quicktypeMultiFile(options: Partial): Promise { return await new Run(options).run(); } -export function quicktypeMultiFileSync (options: Partial): MultiFileRenderResult { +export function quicktypeMultiFileSync(options: Partial): MultiFileRenderResult { return new Run(options).runSync(); } -function offsetLocation (loc: Location, lineOffset: number): Location { +function offsetLocation(loc: Location, lineOffset: number): Location { return { line: loc.line + lineOffset, column: loc.column }; } -function offsetSpan (span: Span, lineOffset: number): Span { +function offsetSpan(span: Span, lineOffset: number): Span { return { start: offsetLocation(span.start, lineOffset), end: offsetLocation(span.end, lineOffset) }; } @@ -620,7 +619,7 @@ function offsetSpan (span: Span, lineOffset: number): Span { * are concatenated and prefixed with a `//`-style comment giving the * filename. */ -export function combineRenderResults (result: MultiFileRenderResult): SerializedRenderResult { +export function combineRenderResults(result: MultiFileRenderResult): SerializedRenderResult { if (result.size <= 1) { const first = mapFirst(result); if (first === undefined) { @@ -636,7 +635,7 @@ export function combineRenderResults (result: MultiFileRenderResult): Serialized const offset = lines.length + 2; lines = lines.concat([`// ${filename}`, ""], srr.lines); annotations = annotations.concat( - srr.annotations.map(ann => ({ annotation: ann.annotation, span: offsetSpan(ann.span, offset) })), + srr.annotations.map(ann => ({ annotation: ann.annotation, span: offsetSpan(ann.span, offset) })) ); } @@ -651,7 +650,7 @@ export function combineRenderResults (result: MultiFileRenderResult): Serialized * @param options Partial options. For options that are not defined, the * defaults will be used. */ -export async function quicktype (options: Partial): Promise { +export async function quicktype(options: Partial): Promise { const result = await quicktypeMultiFile(options); return combineRenderResults(result); } diff --git a/packages/quicktype-core/src/Source.ts b/packages/quicktype-core/src/Source.ts index 235ac9264..f47360c37 100644 --- a/packages/quicktype-core/src/Source.ts +++ b/packages/quicktype-core/src/Source.ts @@ -21,10 +21,10 @@ export interface TextSource { export interface NewlineSource { // Number of indentation levels (not spaces!) to change -// the rest of the source by. Positive numbers mean -// indent more, negative mean indent less. The most -// common value will be zero, for no change in -// indentation. + // the rest of the source by. Positive numbers mean + // indent more, negative mean indent less. The most + // common value will be zero, for no change in + // indentation. indentationChange: number; kind: "newline"; } @@ -56,7 +56,7 @@ export interface ModifiedSource { source: Source; } -export function newline (): NewlineSource { +export function newline(): NewlineSource { // We're returning a new object instead of using a singleton // here because `Renderer` will modify `indentationChange`. return { kind: "newline", indentationChange: 0 }; @@ -65,11 +65,11 @@ export function newline (): NewlineSource { export type Sourcelike = Source | string | Name | SourcelikeArray; export type SourcelikeArray = Sourcelike[]; -export function sourcelikeToSource (sl: Sourcelike): Source { +export function sourcelikeToSource(sl: Sourcelike): Source { if (sl instanceof Array) { return { kind: "sequence", - sequence: sl.map(sourcelikeToSource), + sequence: sl.map(sourcelikeToSource) }; } @@ -83,8 +83,8 @@ export function sourcelikeToSource (sl: Sourcelike): Source { kind: "sequence", sequence: arrayIntercalate( newline(), - lines.map((l: string) => ({ kind: "text", text: l } as Source)), - ), + lines.map((l: string) => ({ kind: "text", text: l }) as Source) + ) }; } @@ -95,15 +95,15 @@ export function sourcelikeToSource (sl: Sourcelike): Source { return sl; } -export function annotated (annotation: AnnotationData, sl: Sourcelike): Source { +export function annotated(annotation: AnnotationData, sl: Sourcelike): Source { return { kind: "annotated", annotation, - source: sourcelikeToSource(sl), + source: sourcelikeToSource(sl) }; } -export function maybeAnnotated (doAnnotate: boolean, annotation: AnnotationData, sl: Sourcelike): Sourcelike { +export function maybeAnnotated(doAnnotate: boolean, annotation: AnnotationData, sl: Sourcelike): Sourcelike { if (!doAnnotate) { return sl; } @@ -111,11 +111,11 @@ export function maybeAnnotated (doAnnotate: boolean, annotation: AnnotationData, return annotated(annotation, sl); } -export function modifySource (modifier: (serialized: string) => string, sl: Sourcelike): Sourcelike { +export function modifySource(modifier: (serialized: string) => string, sl: Sourcelike): Sourcelike { return { kind: "modified", modifier, - source: sourcelikeToSource(sl), + source: sourcelikeToSource(sl) }; } @@ -140,7 +140,7 @@ export interface SerializedRenderResult { lines: string[]; } -function sourceLineLength (source: Source, names: ReadonlyMap): number { +function sourceLineLength(source: Source, names: ReadonlyMap): number { switch (source.kind) { case "text": return source.text.length; @@ -163,10 +163,10 @@ function sourceLineLength (source: Source, names: ReadonlyMap): nu } } -export function serializeRenderResult ( +export function serializeRenderResult( rootSource: Source, names: ReadonlyMap, - indentation: string, + indentation: string ): SerializedRenderResult { let indent = 0; let indentNeeded = 0; @@ -175,28 +175,28 @@ export function serializeRenderResult ( let currentLine: string[] = []; const annotations: Annotation[] = []; - function indentIfNeeded (): void { + function indentIfNeeded(): void { if (indentNeeded === 0) return; currentLine.push(repeatString(indentation, indentNeeded)); indentNeeded = 0; } - function flattenCurrentLine (): string { + function flattenCurrentLine(): string { const str = currentLine.join(""); currentLine = [str]; return str; } - function currentLocation (): Location { + function currentLocation(): Location { return { line: lines.length, column: flattenCurrentLine().length }; } - function finishLine (): void { + function finishLine(): void { lines.push(flattenCurrentLine()); currentLine = []; } - function serializeToStringArray (source: Source): void { + function serializeToStringArray(source: Source): void { switch (source.kind) { case "text": indentIfNeeded(); @@ -278,11 +278,11 @@ export interface MultiWord { source: Sourcelike; } -export function singleWord (...source: Sourcelike[]): MultiWord { +export function singleWord(...source: Sourcelike[]): MultiWord { return { source, needsParens: false }; } -export function multiWord (separator: Sourcelike, ...words: Sourcelike[]): MultiWord { +export function multiWord(separator: Sourcelike, ...words: Sourcelike[]): MultiWord { assert(words.length > 0, "Zero words is not multiple"); if (words.length === 1) { return singleWord(words[0]); @@ -297,7 +297,7 @@ export function multiWord (separator: Sourcelike, ...words: Sourcelike[]): Multi return { source: items, needsParens: true }; } -export function parenIfNeeded ({ source, needsParens }: MultiWord): Sourcelike { +export function parenIfNeeded({ source, needsParens }: MultiWord): Sourcelike { if (needsParens) { return ["(", source, ")"]; } diff --git a/packages/quicktype-core/src/TargetLanguage.ts b/packages/quicktype-core/src/TargetLanguage.ts index 4d9dbce50..7f41b919e 100644 --- a/packages/quicktype-core/src/TargetLanguage.ts +++ b/packages/quicktype-core/src/TargetLanguage.ts @@ -9,26 +9,26 @@ import { type StringTypeMapping } from "./TypeBuilder"; import { defined } from "./support/Support"; import { type ConvenienceRenderer } from "./ConvenienceRenderer"; import { type Type } from "./Type"; -import { type DateTimeRecognizer} from "./DateTime"; +import { type DateTimeRecognizer } from "./DateTime"; import { DefaultDateTimeRecognizer } from "./DateTime"; import { type Comment } from "./support/Comments"; export type MultiFileRenderResult = ReadonlyMap; export abstract class TargetLanguage { - constructor ( - readonly displayName: string, - readonly names: string[], - readonly extension: string, + public constructor( + public readonly displayName: string, + public readonly names: string[], + public readonly extension: string ) {} - protected abstract getOptions (): Array>; + protected abstract getOptions(): Array>; - get optionDefinitions (): OptionDefinition[] { + public get optionDefinitions(): OptionDefinition[] { return this.getOptions().map(o => o.definition); } - get cliOptionDefinitions (): { actual: OptionDefinition[], display: OptionDefinition[], } { + public get cliOptionDefinitions(): { actual: OptionDefinition[]; display: OptionDefinition[] } { let actual: OptionDefinition[] = []; let display: OptionDefinition[] = []; for (const { cliDefinitions } of this.getOptions()) { @@ -39,19 +39,19 @@ export abstract class TargetLanguage { return { actual, display }; } - get name (): string { + public get name(): string { return defined(this.names[0]); } - protected abstract makeRenderer (renderContext: RenderContext, optionValues: { [name: string]: any, }): Renderer; + protected abstract makeRenderer(renderContext: RenderContext, optionValues: { [name: string]: any }): Renderer; - renderGraphAndSerialize ( + public renderGraphAndSerialize( typeGraph: TypeGraph, givenOutputFilename: string, alphabetizeProperties: boolean, leadingComments: Comment[] | undefined, - rendererOptions: { [name: string]: any, }, - indentation?: string, + rendererOptions: { [name: string]: any }, + indentation?: string ): MultiFileRenderResult { if (indentation === undefined) { indentation = this.defaultIndentation; @@ -67,31 +67,31 @@ export abstract class TargetLanguage { return mapMap(renderResult.sources, s => serializeRenderResult(s, renderResult.names, defined(indentation))); } - protected get defaultIndentation (): string { + protected get defaultIndentation(): string { return " "; } - get stringTypeMapping (): StringTypeMapping { + public get stringTypeMapping(): StringTypeMapping { return new Map(); } - get supportsOptionalClassProperties (): boolean { + public get supportsOptionalClassProperties(): boolean { return false; } - get supportsUnionsWithBothNumberTypes (): boolean { + public get supportsUnionsWithBothNumberTypes(): boolean { return false; } - get supportsFullObjectType (): boolean { + public get supportsFullObjectType(): boolean { return false; } - needsTransformerForType (_t: Type): boolean { + public needsTransformerForType(_t: Type): boolean { return false; } - get dateTimeRecognizer (): DateTimeRecognizer { + public get dateTimeRecognizer(): DateTimeRecognizer { return new DefaultDateTimeRecognizer(); } } diff --git a/packages/quicktype-core/src/Transformers.ts b/packages/quicktype-core/src/Transformers.ts index 0b978b771..3c9b3f9eb 100644 --- a/packages/quicktype-core/src/Transformers.ts +++ b/packages/quicktype-core/src/Transformers.ts @@ -6,7 +6,7 @@ import { addHashCode, definedMapWithDefault, arraySortByInto, - hashString, + hashString } from "collection-utils"; import { type Type, type TypeKind } from "./Type"; @@ -17,7 +17,7 @@ import { type BaseGraphRewriteBuilder } from "./GraphRewriting"; import { type TypeRef, type TypeGraph } from "./TypeGraph"; import { derefTypeRef } from "./TypeGraph"; -function debugStringForType (t: Type): string { +function debugStringForType(t: Type): string { const target = followTargetType(t); if (t === target) { return t.kind; @@ -26,126 +26,140 @@ function debugStringForType (t: Type): string { return `${t.kind} (${target.kind})`; } -function getNumberOfNodes (xfer: Transformer | undefined): number { +function getNumberOfNodes(xfer: Transformer | undefined): number { return definedMapWithDefault(xfer, 0, x => x.getNumberOfNodes()); } export abstract class Transformer { - constructor (readonly kind: string, protected readonly graph: TypeGraph, readonly sourceTypeRef: TypeRef) {} + public constructor( + public readonly kind: string, + protected readonly graph: TypeGraph, + public readonly sourceTypeRef: TypeRef + ) {} - get sourceType (): Type { + public get sourceType(): Type { return derefTypeRef(this.sourceTypeRef, this.graph); } /** This must return a newly constructed set. */ - getChildren (): Set { + public getChildren(): Set { return new Set([this.sourceType]); } - getNumberOfNodes (): number { + public getNumberOfNodes(): number { return 1; } - abstract get canFail (): boolean; + public abstract get canFail(): boolean; - abstract reverse (targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer; + public abstract reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer; - abstract reconstitute(builder: TBuilder): Transformer; + public abstract reconstitute(builder: TBuilder): Transformer; - equals (other: any): boolean { + public equals(other: any): boolean { if (!(other instanceof Transformer)) return false; return this.sourceTypeRef === other.sourceTypeRef; } - hashCode (): number { + public hashCode(): number { return hashCodeOf(this.sourceTypeRef); } - protected debugDescription (): string { + protected debugDescription(): string { return `${debugStringForType(this.sourceType)} -> ${this.kind}`; } - protected debugPrintContinuations (_indent: number): void { + protected debugPrintContinuations(_indent: number): void { return; } - debugPrint (indent: number): void { + public debugPrint(indent: number): void { console.log(indentationString(indent) + this.debugDescription()); this.debugPrintContinuations(indent + 1); } } export abstract class ProducerTransformer extends Transformer { - constructor (kind: string, graph: TypeGraph, sourceTypeRef: TypeRef, readonly consumer: Transformer | undefined) { + public constructor( + kind: string, + graph: TypeGraph, + sourceTypeRef: TypeRef, + public readonly consumer: Transformer | undefined + ) { super(kind, graph, sourceTypeRef); } - getChildren (): Set { + public getChildren(): Set { const children = super.getChildren(); if (this.consumer === undefined) return children; return setUnionInto(children, this.consumer.getChildren()); } - getNumberOfNodes (): number { + public getNumberOfNodes(): number { return super.getNumberOfNodes() + getNumberOfNodes(this.consumer); } - equals (other: any): boolean { + public equals(other: any): boolean { if (!super.equals(other)) return false; if (!(other instanceof ProducerTransformer)) return false; return areEqual(this.consumer, other.consumer); } - hashCode (): number { + public hashCode(): number { const h = super.hashCode(); return addHashCode(h, hashCodeOf(this.consumer)); } - protected debugPrintContinuations (indent: number): void { + protected debugPrintContinuations(indent: number): void { if (this.consumer === undefined) return; this.consumer.debugPrint(indent); } } export abstract class MatchTransformer extends Transformer { - constructor (kind: string, graph: TypeGraph, sourceTypeRef: TypeRef, readonly transformer: Transformer) { + public constructor( + kind: string, + graph: TypeGraph, + sourceTypeRef: TypeRef, + public readonly transformer: Transformer + ) { super(kind, graph, sourceTypeRef); } - getChildren (): Set { + public getChildren(): Set { return setUnionInto(super.getChildren(), this.transformer.getChildren()); } - getNumberOfNodes (): number { + public getNumberOfNodes(): number { return super.getNumberOfNodes() + this.transformer.getNumberOfNodes(); } - equals (other: any): boolean { + public equals(other: any): boolean { if (!super.equals(other)) return false; if (!(other instanceof MatchTransformer)) return false; return this.transformer.equals(other.transformer); } - hashCode (): number { + public hashCode(): number { const h = super.hashCode(); return addHashCode(h, this.transformer.hashCode()); } - protected debugPrintContinuations (indent: number): void { + protected debugPrintContinuations(indent: number): void { this.transformer.debugPrint(indent); } } export class DecodingTransformer extends ProducerTransformer { - constructor (graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined) { + public constructor(graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined) { super("decode", graph, sourceTypeRef, consumer); } - get canFail (): boolean { + public get canFail(): boolean { return false; } - reverse (targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + public reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { if (continuationTransformer !== undefined) { return panic("Reversing a decoding transformer cannot have a continuation"); } @@ -155,43 +169,43 @@ export class DecodingTransformer extends ProducerTransformer { } else { return this.consumer.reverse( targetTypeRef, - new EncodingTransformer(this.graph, this.consumer.sourceTypeRef), + new EncodingTransformer(this.graph, this.consumer.sourceTypeRef) ); } } - reconstitute(builder: TBuilder): Transformer { + public reconstitute(builder: TBuilder): Transformer { return new DecodingTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), - definedMap(this.consumer, xfer => xfer.reconstitute(builder)), + definedMap(this.consumer, xfer => xfer.reconstitute(builder)) ); } - equals (other: any): boolean { + public equals(other: any): boolean { if (!super.equals(other)) return false; return other instanceof DecodingTransformer; } } export class EncodingTransformer extends Transformer { - constructor (graph: TypeGraph, sourceTypeRef: TypeRef) { + public constructor(graph: TypeGraph, sourceTypeRef: TypeRef) { super("encode", graph, sourceTypeRef); } - get canFail (): boolean { + public get canFail(): boolean { return false; } - reverse (_targetTypeRef: TypeRef, _continuationTransformer: Transformer | undefined): Transformer { + public reverse(_targetTypeRef: TypeRef, _continuationTransformer: Transformer | undefined): Transformer { return panic("Can't reverse encoding transformer"); } - reconstitute(builder: TBuilder): Transformer { + public reconstitute(builder: TBuilder): Transformer { return new EncodingTransformer(builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef)); } - equals (other: any): boolean { + public equals(other: any): boolean { if (!super.equals(other)) return false; if (!(other instanceof EncodingTransformer)) return false; return true; @@ -199,35 +213,35 @@ export class EncodingTransformer extends Transformer { } export class ArrayDecodingTransformer extends ProducerTransformer { - constructor ( + public constructor( graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined, private readonly _itemTargetTypeRef: TypeRef, - readonly itemTransformer: Transformer, + public readonly itemTransformer: Transformer ) { super("decode-array", graph, sourceTypeRef, consumer); } - getChildren (): Set { + public getChildren(): Set { const children = super.getChildren(); children.add(this.itemTargetType); return setUnionInto(children, this.itemTransformer.getChildren()); } - getNumberOfNodes (): number { + public getNumberOfNodes(): number { return super.getNumberOfNodes() + this.itemTransformer.getNumberOfNodes(); } - get canFail (): boolean { + public get canFail(): boolean { return false; } - get itemTargetType (): Type { + public get itemTargetType(): Type { return derefTypeRef(this._itemTargetTypeRef, this.graph); } - reverse (targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + public reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { if (continuationTransformer !== undefined) { return panic("Reversing a decoding transformer cannot have a continuation"); } @@ -239,7 +253,7 @@ export class ArrayDecodingTransformer extends ProducerTransformer { this.graph, targetTypeRef, this.itemTransformer.sourceTypeRef, - itemTransformer, + itemTransformer ); } else { return this.consumer.reverse( @@ -248,109 +262,113 @@ export class ArrayDecodingTransformer extends ProducerTransformer { this.graph, this.consumer.sourceTypeRef, this.itemTransformer.sourceTypeRef, - itemTransformer, - ), + itemTransformer + ) ); } } - reconstitute(builder: TBuilder): Transformer { + public reconstitute(builder: TBuilder): Transformer { return new ArrayDecodingTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), definedMap(this.consumer, xfer => xfer.reconstitute(builder)), builder.reconstituteTypeRef(this._itemTargetTypeRef), - this.itemTransformer.reconstitute(builder), + this.itemTransformer.reconstitute(builder) ); } - hashCode (): number { + public hashCode(): number { let h = super.hashCode(); h = addHashCode(h, hashCodeOf(this._itemTargetTypeRef)); h = addHashCode(h, this.itemTransformer.hashCode()); return h; } - equals (other: any): boolean { + public equals(other: any): boolean { if (!super.equals(other)) return false; if (!(other instanceof ArrayDecodingTransformer)) return false; if (!areEqual(this._itemTargetTypeRef, other._itemTargetTypeRef)) return false; return this.itemTransformer.equals(other.itemTransformer); } - protected debugPrintContinuations (indent: number): void { + protected debugPrintContinuations(indent: number): void { this.itemTransformer.debugPrint(indent); super.debugPrintContinuations(indent); } } export class ArrayEncodingTransformer extends Transformer { - constructor ( + public constructor( graph: TypeGraph, sourceTypeRef: TypeRef, private readonly _itemTargetTypeRef: TypeRef, - readonly itemTransformer: Transformer, + public readonly itemTransformer: Transformer ) { super("encode-array", graph, sourceTypeRef); } - getChildren (): Set { + public getChildren(): Set { const children = super.getChildren(); children.add(this.itemTargetType); return setUnionInto(children, this.itemTransformer.getChildren()); } - getNumberOfNodes (): number { + public getNumberOfNodes(): number { return super.getNumberOfNodes() + this.itemTransformer.getNumberOfNodes(); } - get canFail (): boolean { + public get canFail(): boolean { return false; } - get itemTargetType (): Type { + public get itemTargetType(): Type { return derefTypeRef(this._itemTargetTypeRef, this.graph); } - reverse (_targetTypeRef: TypeRef, _continuationTransformer: Transformer | undefined): Transformer { + public reverse(_targetTypeRef: TypeRef, _continuationTransformer: Transformer | undefined): Transformer { return panic("Can't reverse array encoding transformer"); } - reconstitute(builder: TBuilder): Transformer { + public reconstitute(builder: TBuilder): Transformer { return new ArrayEncodingTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), builder.reconstituteTypeRef(this._itemTargetTypeRef), - this.itemTransformer.reconstitute(builder), + this.itemTransformer.reconstitute(builder) ); } - hashCode (): number { + public hashCode(): number { let h = super.hashCode(); h = addHashCode(h, hashCodeOf(this._itemTargetTypeRef)); return addHashCode(h, this.itemTransformer.hashCode()); } - equals (other: any): boolean { + public equals(other: any): boolean { if (!super.equals(other)) return false; if (!(other instanceof ArrayEncodingTransformer)) return false; if (!areEqual(this._itemTargetTypeRef, other._itemTargetTypeRef)) return false; return this.itemTransformer.equals(other.itemTransformer); } - protected debugPrintContinuations (indent: number): void { + protected debugPrintContinuations(indent: number): void { this.itemTransformer.debugPrint(indent); super.debugPrintContinuations(indent); } } export class ChoiceTransformer extends Transformer { - constructor (graph: TypeGraph, sourceTypeRef: TypeRef, public readonly transformers: readonly Transformer[]) { + public constructor( + graph: TypeGraph, + sourceTypeRef: TypeRef, + public readonly transformers: readonly Transformer[] + ) { super("choice", graph, sourceTypeRef); assert(transformers.length > 0, "Choice must have at least one transformer"); } - getChildren (): Set { + public getChildren(): Set { let children = super.getChildren(); for (const xfer of this.transformers) { setUnionInto(children, xfer.getChildren()); @@ -359,7 +377,7 @@ export class ChoiceTransformer extends Transformer { return children; } - getNumberOfNodes (): number { + public getNumberOfNodes(): number { let n = 0; for (const xfer of this.transformers) { n += xfer.getNumberOfNodes(); @@ -368,11 +386,11 @@ export class ChoiceTransformer extends Transformer { return super.getNumberOfNodes() + n; } - get canFail (): boolean { + public get canFail(): boolean { return this.transformers.some(xfer => xfer.canFail); } - reverse (targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + public reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { const transformers = this.transformers.map(xfer => xfer.reverse(targetTypeRef, continuationTransformer)); if (transformers.every(xfer => xfer instanceof UnionMemberMatchTransformer)) { const memberMatchers = transformers as UnionMemberMatchTransformer[]; @@ -383,7 +401,7 @@ export class ChoiceTransformer extends Transformer { this.graph, targetTypeRef, new ChoiceTransformer(this.graph, subTransformers[0].sourceTypeRef, subTransformers), - first.memberTypeRef, + first.memberTypeRef ); } } @@ -391,26 +409,26 @@ export class ChoiceTransformer extends Transformer { return new ChoiceTransformer(this.graph, targetTypeRef, transformers); } - reconstitute(builder: TBuilder): Transformer { + public reconstitute(builder: TBuilder): Transformer { return new ChoiceTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), - this.transformers.map(xfer => xfer.reconstitute(builder)), + this.transformers.map(xfer => xfer.reconstitute(builder)) ); } - equals (other: any): boolean { + public equals(other: any): boolean { if (!super.equals(other)) return false; if (!(other instanceof ChoiceTransformer)) return false; return areEqual(this.transformers, other.transformers); } - hashCode (): number { + public hashCode(): number { const h = super.hashCode(); return addHashCode(h, hashCodeOf(this.transformers)); } - protected debugPrintContinuations (indent: number): void { + protected debugPrintContinuations(indent: number): void { for (const xfer of this.transformers) { xfer.debugPrint(indent); } @@ -418,23 +436,23 @@ export class ChoiceTransformer extends Transformer { } export class DecodingChoiceTransformer extends Transformer { - constructor ( + public constructor( graph: TypeGraph, sourceTypeRef: TypeRef, - readonly nullTransformer: Transformer | undefined, - readonly integerTransformer: Transformer | undefined, - readonly doubleTransformer: Transformer | undefined, - readonly boolTransformer: Transformer | undefined, - readonly stringTransformer: Transformer | undefined, - readonly arrayTransformer: Transformer | undefined, - readonly objectTransformer: Transformer | undefined, + public readonly nullTransformer: Transformer | undefined, + public readonly integerTransformer: Transformer | undefined, + public readonly doubleTransformer: Transformer | undefined, + public readonly boolTransformer: Transformer | undefined, + public readonly stringTransformer: Transformer | undefined, + public readonly arrayTransformer: Transformer | undefined, + public readonly objectTransformer: Transformer | undefined ) { super("decoding-choice", graph, sourceTypeRef); } - get transformers (): readonly Transformer[] { + public get transformers(): readonly Transformer[] { const transformers: Transformer[] = []; - function add (xfer: Transformer | undefined) { + function add(xfer: Transformer | undefined) { if (xfer === undefined) return; transformers.push(xfer); } @@ -450,7 +468,7 @@ export class DecodingChoiceTransformer extends Transformer { return transformers; } - getChildren (): Set { + public getChildren(): Set { let children = super.getChildren(); for (const xfer of this.transformers) { setUnionInto(children, xfer.getChildren()); @@ -459,7 +477,7 @@ export class DecodingChoiceTransformer extends Transformer { return children; } - getNumberOfNodes (): number { + public getNumberOfNodes(): number { let n = super.getNumberOfNodes(); for (const xfer of this.transformers) { n += getNumberOfNodes(xfer); @@ -468,20 +486,20 @@ export class DecodingChoiceTransformer extends Transformer { return n; } - get canFail (): boolean { + public get canFail(): boolean { return false; } - reverse (targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + public reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { assert( continuationTransformer === undefined, - "Reversing a decoding transformer can't have a target transformer", + "Reversing a decoding transformer can't have a target transformer" ); let transformers = new Map(); let memberMatchTransformers = new Map(); - function addCase (reversed: Transformer) { + function addCase(reversed: Transformer) { if (reversed instanceof UnionMemberMatchTransformer) { const memberType = reversed.memberType; let arr = memberMatchTransformers.get(memberType); @@ -503,7 +521,7 @@ export class DecodingChoiceTransformer extends Transformer { } } - function reverseAndAdd (transformer: Transformer) { + function reverseAndAdd(transformer: Transformer) { const reversed = transformer.reverse(targetTypeRef, undefined); let cases: readonly Transformer[] = []; // Flatten nested ChoiceTransformers @@ -525,7 +543,7 @@ export class DecodingChoiceTransformer extends Transformer { // If there are non-failing transformers, we ignore the ones that can fail and // just pick the "simplest" non-failing one, being the one with the least number // of nodes. - function filter (xfers: Transformer[]): Transformer[] { + function filter(xfers: Transformer[]): Transformer[] { assert(xfers.length > 0, "Must have at least one transformer"); const nonfailing = xfers.filter(xfer => { @@ -544,7 +562,7 @@ export class DecodingChoiceTransformer extends Transformer { const smallest = arraySortByInto( nonfailing.map(x => [x.getNumberOfNodes(), x] as [number, Transformer]), - ([c, _]) => c, + ([c, _]) => c )[0][1]; return [smallest]; } @@ -562,8 +580,8 @@ export class DecodingChoiceTransformer extends Transformer { return new ChoiceTransformer(this.graph, targetTypeRef, resultingTransformers); } - reconstitute(builder: TBuilder): Transformer { - function reconstitute (xf: Transformer | undefined) { + public reconstitute(builder: TBuilder): Transformer { + function reconstitute(xf: Transformer | undefined) { if (xf === undefined) return undefined; return xf.reconstitute(builder); } @@ -577,11 +595,11 @@ export class DecodingChoiceTransformer extends Transformer { reconstitute(this.boolTransformer), reconstitute(this.stringTransformer), reconstitute(this.arrayTransformer), - reconstitute(this.objectTransformer), + reconstitute(this.objectTransformer) ); } - equals (other: any): boolean { + public equals(other: any): boolean { if (!super.equals(other)) return false; if (!(other instanceof DecodingChoiceTransformer)) return false; if (!areEqual(this.nullTransformer, other.nullTransformer)) return false; @@ -594,7 +612,7 @@ export class DecodingChoiceTransformer extends Transformer { return true; } - hashCode (): number { + public hashCode(): number { let h = super.hashCode(); h = addHashCode(h, hashCodeOf(this.nullTransformer)); h = addHashCode(h, hashCodeOf(this.integerTransformer)); @@ -606,7 +624,7 @@ export class DecodingChoiceTransformer extends Transformer { return h; } - protected debugPrintContinuations (indent: number): void { + protected debugPrintContinuations(indent: number): void { for (const xfer of this.transformers) { xfer.debugPrint(indent); } @@ -614,11 +632,16 @@ export class DecodingChoiceTransformer extends Transformer { } export class UnionMemberMatchTransformer extends MatchTransformer { - constructor (graph: TypeGraph, sourceTypeRef: TypeRef, transformer: Transformer, readonly memberTypeRef: TypeRef) { + public constructor( + graph: TypeGraph, + sourceTypeRef: TypeRef, + transformer: Transformer, + public readonly memberTypeRef: TypeRef + ) { super("union-member-match", graph, sourceTypeRef, transformer); } - get sourceType (): UnionType { + public get sourceType(): UnionType { const t = derefTypeRef(this.sourceTypeRef, this.graph); if (!(t instanceof UnionType)) { return panic("The source of a union member match transformer must be a union type"); @@ -627,43 +650,43 @@ export class UnionMemberMatchTransformer extends MatchTransformer { return t; } - get canFail (): boolean { + public get canFail(): boolean { return true; } - get memberType (): Type { + public get memberType(): Type { return derefTypeRef(this.memberTypeRef, this.graph); } - getChildren (): Set { + public getChildren(): Set { return super.getChildren().add(this.memberType); } - reverse (_targetTypeRef: TypeRef, _continuationTransformer: Transformer | undefined): Transformer { + public reverse(_targetTypeRef: TypeRef, _continuationTransformer: Transformer | undefined): Transformer { return panic("Can't reverse union member match transformer"); } - reconstitute(builder: TBuilder): Transformer { + public reconstitute(builder: TBuilder): Transformer { return new UnionMemberMatchTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), this.transformer.reconstitute(builder), - builder.reconstituteTypeRef(this.memberTypeRef), + builder.reconstituteTypeRef(this.memberTypeRef) ); } - equals (other: any): boolean { + public equals(other: any): boolean { if (!super.equals(other)) return false; if (!(other instanceof UnionMemberMatchTransformer)) return false; return this.memberTypeRef === other.memberTypeRef; } - hashCode (): number { + public hashCode(): number { const h = super.hashCode(); return addHashCode(h, hashCodeOf(this.memberTypeRef)); } - protected debugDescription (): string { + protected debugDescription(): string { return `${super.debugDescription()} - member: ${debugStringForType(this.memberType)}`; } } @@ -672,11 +695,16 @@ export class UnionMemberMatchTransformer extends MatchTransformer { * This matches strings and enum cases. */ export class StringMatchTransformer extends MatchTransformer { - constructor (graph: TypeGraph, sourceTypeRef: TypeRef, transformer: Transformer, readonly stringCase: string) { + public constructor( + graph: TypeGraph, + sourceTypeRef: TypeRef, + transformer: Transformer, + public readonly stringCase: string + ) { super("string-match", graph, sourceTypeRef, transformer); } - get sourceType (): EnumType | PrimitiveType { + public get sourceType(): EnumType | PrimitiveType { const t = derefTypeRef(this.sourceTypeRef, this.graph); if (!(t instanceof EnumType) && !(t instanceof PrimitiveType && t.kind === "string")) { return panic("The source of a string match transformer must be an enum or string type"); @@ -685,57 +713,57 @@ export class StringMatchTransformer extends MatchTransformer { return t; } - get canFail (): boolean { + public get canFail(): boolean { return true; } - reverse (targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + public reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { return this.transformer.reverse( targetTypeRef, new StringProducerTransformer( this.graph, this.transformer.sourceTypeRef, continuationTransformer, - this.stringCase, - ), + this.stringCase + ) ); } - reconstitute(builder: TBuilder): Transformer { + public reconstitute(builder: TBuilder): Transformer { return new StringMatchTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), this.transformer.reconstitute(builder), - this.stringCase, + this.stringCase ); } - equals (other: any): boolean { + public equals(other: any): boolean { if (!super.equals(other)) return false; if (!(other instanceof StringMatchTransformer)) return false; return this.stringCase !== other.stringCase; } - hashCode (): number { + public hashCode(): number { const h = super.hashCode(); return addHashCode(h, hashString(this.stringCase)); } - protected debugDescription (): string { + protected debugDescription(): string { return `${super.debugDescription()} - case: ${this.stringCase}`; } } export class UnionInstantiationTransformer extends Transformer { - constructor (graph: TypeGraph, sourceTypeRef: TypeRef) { + public constructor(graph: TypeGraph, sourceTypeRef: TypeRef) { super("union-instantiation", graph, sourceTypeRef); } - get canFail (): boolean { + public get canFail(): boolean { return false; } - reverse (targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + public reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { if (continuationTransformer === undefined) { return panic("Union instantiation transformer reverse must have a continuation"); } @@ -743,11 +771,11 @@ export class UnionInstantiationTransformer extends Transformer { return new UnionMemberMatchTransformer(this.graph, targetTypeRef, continuationTransformer, this.sourceTypeRef); } - reconstitute(builder: TBuilder): Transformer { + public reconstitute(builder: TBuilder): Transformer { return new UnionInstantiationTransformer(builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef)); } - equals (other: any): boolean { + public equals(other: any): boolean { if (!super.equals(other)) return false; return other instanceof UnionInstantiationTransformer; } @@ -757,15 +785,20 @@ export class UnionInstantiationTransformer extends Transformer { * Produces a string or an enum case. */ export class StringProducerTransformer extends ProducerTransformer { - constructor (graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined, readonly result: string) { + public constructor( + graph: TypeGraph, + sourceTypeRef: TypeRef, + consumer: Transformer | undefined, + public readonly result: string + ) { super("string-producer", graph, sourceTypeRef, consumer); } - get canFail (): boolean { + public get canFail(): boolean { return false; } - reverse (targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + public reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { if (continuationTransformer === undefined) { return panic("Reversing a string producer transformer must have a continuation"); } @@ -779,128 +812,128 @@ export class StringProducerTransformer extends ProducerTransformer { this.graph, this.consumer.sourceTypeRef, continuationTransformer, - this.result, - ), + this.result + ) ); } } - reconstitute(builder: TBuilder): Transformer { + public reconstitute(builder: TBuilder): Transformer { return new StringProducerTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), definedMap(this.consumer, xfer => xfer.reconstitute(builder)), - this.result, + this.result ); } - equals (other: any): boolean { + public equals(other: any): boolean { if (!super.equals(other)) return false; if (!(other instanceof StringProducerTransformer)) return false; return this.result === other.result; } - hashCode (): number { + public hashCode(): number { const h = super.hashCode(); return addHashCode(h, hashCodeOf(this.consumer)); } - protected debugDescription (): string { + protected debugDescription(): string { return `${super.debugDescription()} - result: ${this.result}`; } } export class ParseStringTransformer extends ProducerTransformer { - constructor (graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined) { + public constructor(graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined) { super("parse-string", graph, sourceTypeRef, consumer); } - get canFail (): boolean { + public get canFail(): boolean { return true; } - reverse (targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + public reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { if (this.consumer === undefined) { return new StringifyTransformer(this.graph, targetTypeRef, continuationTransformer); } else { return this.consumer.reverse( targetTypeRef, - new StringifyTransformer(this.graph, this.consumer.sourceTypeRef, continuationTransformer), + new StringifyTransformer(this.graph, this.consumer.sourceTypeRef, continuationTransformer) ); } } - reconstitute(builder: TBuilder): Transformer { + public reconstitute(builder: TBuilder): Transformer { return new ParseStringTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), - definedMap(this.consumer, xfer => xfer.reconstitute(builder)), + definedMap(this.consumer, xfer => xfer.reconstitute(builder)) ); } - equals (other: any): boolean { + public equals(other: any): boolean { if (!super.equals(other)) return false; return other instanceof ParseStringTransformer; } } export class StringifyTransformer extends ProducerTransformer { - constructor (graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined) { + public constructor(graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined) { super("stringify", graph, sourceTypeRef, consumer); } - get canFail (): boolean { + public get canFail(): boolean { return false; } - reverse (targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + public reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { if (this.consumer === undefined) { return new ParseStringTransformer(this.graph, targetTypeRef, continuationTransformer); } else { return this.consumer.reverse( targetTypeRef, - new ParseStringTransformer(this.graph, this.consumer.sourceTypeRef, continuationTransformer), + new ParseStringTransformer(this.graph, this.consumer.sourceTypeRef, continuationTransformer) ); } } - reconstitute(builder: TBuilder): Transformer { + public reconstitute(builder: TBuilder): Transformer { return new StringifyTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), - definedMap(this.consumer, xfer => xfer.reconstitute(builder)), + definedMap(this.consumer, xfer => xfer.reconstitute(builder)) ); } - equals (other: any): boolean { + public equals(other: any): boolean { if (!super.equals(other)) return false; return other instanceof StringifyTransformer; } } export class MinMaxLengthCheckTransformer extends ProducerTransformer { - constructor ( + public constructor( graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined, - readonly minLength: number | undefined, - readonly maxLength: number | undefined, + public readonly minLength: number | undefined, + public readonly maxLength: number | undefined ) { super("min-max-length-check", graph, sourceTypeRef, consumer); } - get canFail (): boolean { + public get canFail(): boolean { return true; } - reverse (targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + public reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { if (this.consumer === undefined) { return new MinMaxLengthCheckTransformer( this.graph, targetTypeRef, continuationTransformer, this.minLength, - this.maxLength, + this.maxLength ); } else { return this.consumer.reverse( @@ -910,23 +943,23 @@ export class MinMaxLengthCheckTransformer extends ProducerTransformer { this.consumer.sourceTypeRef, continuationTransformer, this.minLength, - this.maxLength, - ), + this.maxLength + ) ); } } - reconstitute(builder: TBuilder): Transformer { + public reconstitute(builder: TBuilder): Transformer { return new MinMaxLengthCheckTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), definedMap(this.consumer, xfer => xfer.reconstitute(builder)), this.minLength, - this.maxLength, + this.maxLength ); } - equals (other: any): boolean { + public equals(other: any): boolean { if (!super.equals(other)) return false; return ( other instanceof MinMaxLengthCheckTransformer && @@ -937,28 +970,28 @@ export class MinMaxLengthCheckTransformer extends ProducerTransformer { } export class MinMaxValueTransformer extends ProducerTransformer { - constructor ( + public constructor( graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined, - readonly minimum: number | undefined, - readonly maximum: number | undefined, + public readonly minimum: number | undefined, + public readonly maximum: number | undefined ) { super("min-max-value-check", graph, sourceTypeRef, consumer); } - get canFail (): boolean { + public get canFail(): boolean { return true; } - reverse (targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + public reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { if (this.consumer === undefined) { return new MinMaxValueTransformer( this.graph, targetTypeRef, continuationTransformer, this.minimum, - this.maximum, + this.maximum ); } else { return this.consumer.reverse( @@ -968,23 +1001,23 @@ export class MinMaxValueTransformer extends ProducerTransformer { this.consumer.sourceTypeRef, continuationTransformer, this.minimum, - this.maximum, - ), + this.maximum + ) ); } } - reconstitute(builder: TBuilder): Transformer { + public reconstitute(builder: TBuilder): Transformer { return new MinMaxValueTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), definedMap(this.consumer, xfer => xfer.reconstitute(builder)), this.minimum, - this.maximum, + this.maximum ); } - equals (other: any): boolean { + public equals(other: any): boolean { if (!super.equals(other)) return false; return ( other instanceof MinMaxValueTransformer && this.minimum === other.minimum && this.maximum === other.maximum @@ -993,90 +1026,93 @@ export class MinMaxValueTransformer extends ProducerTransformer { } export class Transformation { - constructor ( + public constructor( private readonly _graph: TypeGraph, private readonly _targetTypeRef: TypeRef, - readonly transformer: Transformer, + public readonly transformer: Transformer ) {} - get sourceType (): Type { + public get sourceType(): Type { return this.transformer.sourceType; } - get targetType (): Type { + public get targetType(): Type { return derefTypeRef(this._targetTypeRef, this._graph); } - get reverse (): Transformation { + public get reverse(): Transformation { return new Transformation( this._graph, this.transformer.sourceTypeRef, - this.transformer.reverse(this._targetTypeRef, undefined), + this.transformer.reverse(this._targetTypeRef, undefined) ); } - getChildren (): Set { + public getChildren(): Set { return this.transformer.getChildren().add(this.targetType); } - reconstitute(builder: TBuilder): Transformation { + public reconstitute(builder: TBuilder): Transformation { return new Transformation( builder.typeGraph, builder.reconstituteTypeRef(this._targetTypeRef), - this.transformer.reconstitute(builder), + this.transformer.reconstitute(builder) ); } - equals (other: any): boolean { + public equals(other: any): boolean { if (!(other instanceof Transformation)) return false; return this._targetTypeRef === other._targetTypeRef && this.transformer.equals(other.transformer); } - hashCode (): number { + public hashCode(): number { let h = hashCodeOf(this._targetTypeRef); h = addHashCode(h, this.transformer.hashCode()); return h; } - debugPrint (): void { + public debugPrint(): void { this.transformer.debugPrint(0); console.log(`-> ${debugStringForType(this.targetType)}`); } } class TransformationTypeAttributeKind extends TypeAttributeKind { - constructor () { + public constructor() { super("transformation"); } - appliesToTypeKind (_kind: TypeKind): boolean { + public appliesToTypeKind(_kind: TypeKind): boolean { return true; } - get inIdentity (): boolean { + public get inIdentity(): boolean { return true; } - children (xf: Transformation): Set { + public children(xf: Transformation): Set { return xf.getChildren(); } - reconstitute(builder: TBuilder, xf: Transformation): Transformation { + public reconstitute( + builder: TBuilder, + xf: Transformation + ): Transformation { return xf.reconstitute(builder); } - stringify (_: Transformation): string { + public stringify(_: Transformation): string { return "transformation"; } } export const transformationTypeAttributeKind: TypeAttributeKind = new TransformationTypeAttributeKind(); -export function transformationForType (t: Type): Transformation | undefined { +export function transformationForType(t: Type): Transformation | undefined { return transformationTypeAttributeKind.tryGetInAttributes(t.getAttributes()); } -export function followTargetType (t: Type): Type { +export function followTargetType(t: Type): Type { for (;;) { const xf = transformationForType(t); if (xf === undefined) return t; diff --git a/packages/quicktype-core/src/Type.ts b/packages/quicktype-core/src/Type.ts index 6c6542e08..6b50cd7d9 100644 --- a/packages/quicktype-core/src/Type.ts +++ b/packages/quicktype-core/src/Type.ts @@ -18,16 +18,16 @@ import { hashCodeInit, addHashCode, hasOwnProperty, - mapFromObject, + mapFromObject } from "collection-utils"; import { defined, panic, assert } from "./support/Support"; import { type TypeReconstituter, type BaseGraphRewriteBuilder } from "./GraphRewriting"; -import { type TypeNames} from "./attributes/TypeNames"; +import { type TypeNames } from "./attributes/TypeNames"; import { namesTypeAttributeKind } from "./attributes/TypeNames"; import { type TypeAttributes } from "./attributes/TypeAttributes"; import { messageAssert } from "./Messages"; -import { type TypeRef, type TypeGraph} from "./TypeGraph"; +import { type TypeRef, type TypeGraph } from "./TypeGraph"; import { attributesForTypeRef, derefTypeRef, typeRefIndex } from "./TypeGraph"; import { uriInferenceAttributesProducer } from "./attributes/URIAttributes"; @@ -58,13 +58,13 @@ const transformedStringTypeTargetTypeKinds = { uuid: { jsonSchema: "uuid", primitive: undefined }, uri: { jsonSchema: "uri", primitive: undefined, attributesProducer: uriInferenceAttributesProducer }, "integer-string": { jsonSchema: "integer", primitive: "integer" } as TransformedStringTypeTargets, - "bool-string": { jsonSchema: "boolean", primitive: "bool" } as TransformedStringTypeTargets, + "bool-string": { jsonSchema: "boolean", primitive: "bool" } as TransformedStringTypeTargets }; export const transformedStringTypeTargetTypeKindsMap = mapFromObject( transformedStringTypeTargetTypeKinds as { - [kind: string]: TransformedStringTypeTargets, - }, + [kind: string]: TransformedStringTypeTargets; + } ); export type TransformedStringTypeKind = keyof typeof transformedStringTypeTargetTypeKinds; @@ -76,32 +76,32 @@ export type TypeKind = PrimitiveTypeKind | NamedTypeKind | "array" | "object" | export type ObjectTypeKind = "object" | "map" | "class"; export const transformedStringTypeKinds = new Set( - Object.getOwnPropertyNames(transformedStringTypeTargetTypeKinds), + Object.getOwnPropertyNames(transformedStringTypeTargetTypeKinds) ) as ReadonlySet; -export function isPrimitiveStringTypeKind (kind: string): kind is PrimitiveStringTypeKind { +export function isPrimitiveStringTypeKind(kind: string): kind is PrimitiveStringTypeKind { return kind === "string" || hasOwnProperty(transformedStringTypeTargetTypeKinds, kind); } -export function targetTypeKindForTransformedStringTypeKind ( - kind: PrimitiveStringTypeKind, +export function targetTypeKindForTransformedStringTypeKind( + kind: PrimitiveStringTypeKind ): PrimitiveNonStringTypeKind | undefined { const target = transformedStringTypeTargetTypeKindsMap.get(kind); if (target === undefined) return undefined; return target.primitive; } -export function isNumberTypeKind (kind: TypeKind): kind is "integer" | "double" { +export function isNumberTypeKind(kind: TypeKind): kind is "integer" | "double" { return kind === "integer" || kind === "double"; } -export function isPrimitiveTypeKind (kind: TypeKind): kind is PrimitiveTypeKind { +export function isPrimitiveTypeKind(kind: TypeKind): kind is PrimitiveTypeKind { if (isPrimitiveStringTypeKind(kind)) return true; if (isNumberTypeKind(kind)) return true; return kind === "none" || kind === "any" || kind === "null" || kind === "bool"; } -function triviallyStructurallyCompatible (x: Type, y: Type): boolean { +function triviallyStructurallyCompatible(x: Type, y: Type): boolean { if (x.index === y.index) return true; if (x.kind === "none" || y.kind === "none") return true; return false; @@ -110,7 +110,10 @@ function triviallyStructurallyCompatible (x: Type, y: Type): boolean { export class TypeIdentity { private readonly _hashCode: number; - constructor (private readonly _kind: TypeKind, private readonly _components: readonly any[]) { + public constructor( + private readonly _kind: TypeKind, + private readonly _components: readonly any[] + ) { let h = hashCodeInit; h = addHashCode(h, hashCodeOf(this._kind)); for (const c of _components) { @@ -120,7 +123,7 @@ export class TypeIdentity { this._hashCode = h; } - equals (other: any): boolean { + public equals(other: any): boolean { if (!(other instanceof TypeIdentity)) return false; if (this._kind !== other._kind) return false; const n = this._components.length; @@ -132,7 +135,7 @@ export class TypeIdentity { return true; } - hashCode (): number { + public hashCode(): number { return this._hashCode; } } @@ -141,18 +144,21 @@ export class TypeIdentity { export type MaybeTypeIdentity = TypeIdentity | undefined; export abstract class Type { - abstract readonly kind: TypeKind; + public abstract readonly kind: TypeKind; - constructor (readonly typeRef: TypeRef, protected readonly graph: TypeGraph) {} + public constructor( + public readonly typeRef: TypeRef, + protected readonly graph: TypeGraph + ) {} - get index (): number { + public get index(): number { return typeRefIndex(this.typeRef); } // This must return a newly allocated set - abstract getNonAttributeChildren (): Set; + public abstract getNonAttributeChildren(): Set; - getChildren (): ReadonlySet { + public getChildren(): ReadonlySet { let result = this.getNonAttributeChildren(); for (const [k, v] of this.getAttributes()) { if (k.children === undefined) continue; @@ -162,54 +168,54 @@ export abstract class Type { return result; } - getAttributes (): TypeAttributes { + public getAttributes(): TypeAttributes { return attributesForTypeRef(this.typeRef, this.graph); } - get hasNames (): boolean { + public get hasNames(): boolean { return namesTypeAttributeKind.tryGetInAttributes(this.getAttributes()) !== undefined; } - getNames (): TypeNames { + public getNames(): TypeNames { return defined(namesTypeAttributeKind.tryGetInAttributes(this.getAttributes())); } - getCombinedName (): string { + public getCombinedName(): string { return this.getNames().combinedName; } - abstract get isNullable (): boolean; + public abstract get isNullable(): boolean; // FIXME: Remove `isPrimitive` - abstract isPrimitive (): this is PrimitiveType; - abstract get identity (): MaybeTypeIdentity; - abstract reconstitute( + public abstract isPrimitive(): this is PrimitiveType; + public abstract get identity(): MaybeTypeIdentity; + public abstract reconstitute( builder: TypeReconstituter, canonicalOrder: boolean ): void; - get debugPrintKind (): string { + public get debugPrintKind(): string { return this.kind; } - equals (other: any): boolean { + public equals(other: any): boolean { if (!(other instanceof Type)) return false; return this.typeRef === other.typeRef; } - hashCode (): number { + public hashCode(): number { return hashCodeOf(this.typeRef); } // This will only ever be called when `this` and `other` are not // equal, but `this.kind === other.kind`. - protected abstract structuralEqualityStep ( + protected abstract structuralEqualityStep( other: Type, conflateNumbers: boolean, queue: (a: Type, b: Type) => boolean ): boolean; - structurallyCompatible (other: Type, conflateNumbers = false): boolean { - function kindsCompatible (kind1: TypeKind, kind2: TypeKind): boolean { + public structurallyCompatible(other: Type, conflateNumbers = false): boolean { + function kindsCompatible(kind1: TypeKind, kind2: TypeKind): boolean { if (kind1 === kind2) return true; if (!conflateNumbers) return false; if (kind1 === "integer") return kind2 === "double"; @@ -268,11 +274,11 @@ export abstract class Type { return true; } - getParentTypes (): ReadonlySet { + public getParentTypes(): ReadonlySet { return this.graph.getParentsOfType(this); } - getAncestorsNotInSet (set: ReadonlySet): ReadonlySet { + public getAncestorsNotInSet(set: ReadonlySet): ReadonlySet { const workList: Type[] = [this]; const processed = new Set(); const ancestors = new Set(); @@ -299,54 +305,58 @@ export abstract class Type { } } -function hasUniqueIdentityAttributes (attributes: TypeAttributes): boolean { +function hasUniqueIdentityAttributes(attributes: TypeAttributes): boolean { return mapSome(attributes, (v, ta) => ta.requiresUniqueIdentity(v)); } -function identityAttributes (attributes: TypeAttributes): TypeAttributes { +function identityAttributes(attributes: TypeAttributes): TypeAttributes { return mapFilter(attributes, (_, kind) => kind.inIdentity); } -export function primitiveTypeIdentity (kind: PrimitiveTypeKind, attributes: TypeAttributes): MaybeTypeIdentity { +export function primitiveTypeIdentity(kind: PrimitiveTypeKind, attributes: TypeAttributes): MaybeTypeIdentity { if (hasUniqueIdentityAttributes(attributes)) return undefined; return new TypeIdentity(kind, [identityAttributes(attributes)]); } export class PrimitiveType extends Type { - constructor (typeRef: TypeRef, graph: TypeGraph, public readonly kind: PrimitiveTypeKind) { + public constructor( + typeRef: TypeRef, + graph: TypeGraph, + public readonly kind: PrimitiveTypeKind + ) { super(typeRef, graph); } - get isNullable (): boolean { + public get isNullable(): boolean { return this.kind === "null" || this.kind === "any" || this.kind === "none"; } - isPrimitive (): this is PrimitiveType { + public isPrimitive(): this is PrimitiveType { return true; } - getNonAttributeChildren (): Set { + public getNonAttributeChildren(): Set { return new Set(); } - get identity (): MaybeTypeIdentity { + public get identity(): MaybeTypeIdentity { return primitiveTypeIdentity(this.kind, this.getAttributes()); } - reconstitute(builder: TypeReconstituter): void { + public reconstitute(builder: TypeReconstituter): void { builder.getPrimitiveType(this.kind); } - protected structuralEqualityStep ( + protected structuralEqualityStep( _other: Type, _conflateNumbers: boolean, - _queue: (a: Type, b: Type) => boolean, + _queue: (a: Type, b: Type) => boolean ): boolean { return true; } } -export function arrayTypeIdentity (attributes: TypeAttributes, itemsRef: TypeRef): MaybeTypeIdentity { +export function arrayTypeIdentity(attributes: TypeAttributes, itemsRef: TypeRef): MaybeTypeIdentity { if (hasUniqueIdentityAttributes(attributes)) return undefined; return new TypeIdentity("array", [identityAttributes(attributes), itemsRef]); } @@ -354,11 +364,15 @@ export function arrayTypeIdentity (attributes: TypeAttributes, itemsRef: TypeRef export class ArrayType extends Type { public readonly kind = "array"; - constructor (typeRef: TypeRef, graph: TypeGraph, private _itemsRef?: TypeRef) { + public constructor( + typeRef: TypeRef, + graph: TypeGraph, + private _itemsRef?: TypeRef + ) { super(typeRef, graph); } - setItems (itemsRef: TypeRef) { + public setItems(itemsRef: TypeRef) { if (this._itemsRef !== undefined) { return panic("Can only set array items once"); } @@ -366,7 +380,7 @@ export class ArrayType extends Type { this._itemsRef = itemsRef; } - private getItemsRef (): TypeRef { + private getItemsRef(): TypeRef { if (this._itemsRef === undefined) { return panic("Array items accessed before they were set"); } @@ -374,27 +388,27 @@ export class ArrayType extends Type { return this._itemsRef; } - get items (): Type { + public get items(): Type { return derefTypeRef(this.getItemsRef(), this.graph); } - getNonAttributeChildren (): Set { + public getNonAttributeChildren(): Set { return new Set([this.items]); } - get isNullable (): boolean { + public get isNullable(): boolean { return false; } - isPrimitive (): this is PrimitiveType { + public isPrimitive(): this is PrimitiveType { return false; } - get identity (): MaybeTypeIdentity { + public get identity(): MaybeTypeIdentity { return arrayTypeIdentity(this.getAttributes(), this.getItemsRef()); } - reconstitute(builder: TypeReconstituter): void { + public reconstitute(builder: TypeReconstituter): void { const itemsRef = this.getItemsRef(); const maybeItems = builder.lookup(itemsRef); if (maybeItems === undefined) { @@ -405,19 +419,22 @@ export class ArrayType extends Type { } } - protected structuralEqualityStep ( + protected structuralEqualityStep( other: ArrayType, _conflateNumbers: boolean, - queue: (a: Type, b: Type) => boolean, + queue: (a: Type, b: Type) => boolean ): boolean { return queue(this.items, other.items); } } export class GenericClassProperty { - constructor (readonly typeData: T, readonly isOptional: boolean) {} + public constructor( + public readonly typeData: T, + public readonly isOptional: boolean + ) {} - equals (other: any): boolean { + public equals(other: any): boolean { if (!(other instanceof GenericClassProperty)) { return false; } @@ -425,57 +442,61 @@ export class GenericClassProperty { return areEqual(this.typeData, other.typeData) && this.isOptional === other.isOptional; } - hashCode (): number { + public hashCode(): number { return hashCodeOf(this.typeData) + (this.isOptional ? 17 : 23); } } export class ClassProperty extends GenericClassProperty { - constructor (typeRef: TypeRef, readonly graph: TypeGraph, isOptional: boolean) { + public constructor( + typeRef: TypeRef, + public readonly graph: TypeGraph, + isOptional: boolean + ) { super(typeRef, isOptional); } - get typeRef (): TypeRef { + public get typeRef(): TypeRef { return this.typeData; } - get type (): Type { + public get type(): Type { return derefTypeRef(this.typeRef, this.graph); } } -function objectTypeIdentify ( +function objectTypeIdentify( kind: ObjectTypeKind, attributes: TypeAttributes, properties: ReadonlyMap, - additionalPropertiesRef: TypeRef | undefined, + additionalPropertiesRef: TypeRef | undefined ): MaybeTypeIdentity { if (hasUniqueIdentityAttributes(attributes)) return undefined; return new TypeIdentity(kind, [identityAttributes(attributes), properties, additionalPropertiesRef]); } -export function classTypeIdentity ( +export function classTypeIdentity( attributes: TypeAttributes, - properties: ReadonlyMap, + properties: ReadonlyMap ): MaybeTypeIdentity { return objectTypeIdentify("class", attributes, properties, undefined); } -export function mapTypeIdentify ( +export function mapTypeIdentify( attributes: TypeAttributes, - additionalPropertiesRef: TypeRef | undefined, + additionalPropertiesRef: TypeRef | undefined ): MaybeTypeIdentity { return objectTypeIdentify("map", attributes, new Map(), additionalPropertiesRef); } export class ObjectType extends Type { - constructor ( + public constructor( typeRef: TypeRef, graph: TypeGraph, public readonly kind: ObjectTypeKind, - readonly isFixed: boolean, + public readonly isFixed: boolean, private _properties: ReadonlyMap | undefined, - private _additionalPropertiesRef: TypeRef | undefined, + private _additionalPropertiesRef: TypeRef | undefined ) { super(typeRef, graph); @@ -492,7 +513,7 @@ export class ObjectType extends Type { } } - setProperties (properties: ReadonlyMap, additionalPropertiesRef: TypeRef | undefined) { + public setProperties(properties: ReadonlyMap, additionalPropertiesRef: TypeRef | undefined) { assert(this._properties === undefined, "Tried to set object properties twice"); if (this instanceof MapType) { @@ -507,26 +528,26 @@ export class ObjectType extends Type { this._additionalPropertiesRef = additionalPropertiesRef; } - getProperties (): ReadonlyMap { + public getProperties(): ReadonlyMap { return defined(this._properties); } - getSortedProperties (): ReadonlyMap { + public getSortedProperties(): ReadonlyMap { return mapSortByKey(this.getProperties()); } - private getAdditionalPropertiesRef (): TypeRef | undefined { + private getAdditionalPropertiesRef(): TypeRef | undefined { assert(this._properties !== undefined, "Properties are not set yet"); return this._additionalPropertiesRef; } - getAdditionalProperties (): Type | undefined { + public getAdditionalProperties(): Type | undefined { const tref = this.getAdditionalPropertiesRef(); if (tref === undefined) return undefined; return derefTypeRef(tref, this.graph); } - getNonAttributeChildren (): Set { + public getNonAttributeChildren(): Set { const types = mapSortToArray(this.getProperties(), (_, k) => k).map(([_, p]) => p.type); const additionalProperties = this.getAdditionalProperties(); if (additionalProperties !== undefined) { @@ -536,25 +557,28 @@ export class ObjectType extends Type { return new Set(types); } - get isNullable (): boolean { + public get isNullable(): boolean { return false; } - isPrimitive (): this is PrimitiveType { + public isPrimitive(): this is PrimitiveType { return false; } - get identity (): MaybeTypeIdentity { + public get identity(): MaybeTypeIdentity { if (this.isFixed) return undefined; return objectTypeIdentify( this.kind, this.getAttributes(), this.getProperties(), - this.getAdditionalPropertiesRef(), + this.getAdditionalPropertiesRef() ); } - reconstitute(builder: TypeReconstituter, canonicalOrder: boolean): void { + public reconstitute( + builder: TypeReconstituter, + canonicalOrder: boolean + ): void { const sortedProperties = this.getSortedProperties(); const propertiesInNewOrder = canonicalOrder ? sortedProperties : this.getProperties(); const maybePropertyTypes = builder.lookupMap(mapMap(sortedProperties, cp => cp.typeRef)); @@ -565,7 +589,7 @@ export class ObjectType extends Type { (maybeAdditionalProperties !== undefined || this._additionalPropertiesRef === undefined) ) { const properties = mapMap(propertiesInNewOrder, (cp, n) => - builder.makeClassProperty(defined(maybePropertyTypes.get(n)), cp.isOptional), + builder.makeClassProperty(defined(maybePropertyTypes.get(n)), cp.isOptional) ); switch (this.kind) { @@ -605,17 +629,17 @@ export class ObjectType extends Type { const reconstitutedTypes = mapMap(sortedProperties, cp => builder.reconstitute(cp.typeRef)); const properties = mapMap(propertiesInNewOrder, (cp, n) => - builder.makeClassProperty(defined(reconstitutedTypes.get(n)), cp.isOptional), + builder.makeClassProperty(defined(reconstitutedTypes.get(n)), cp.isOptional) ); const additionalProperties = definedMap(this._additionalPropertiesRef, r => builder.reconstitute(r)); builder.setObjectProperties(properties, additionalProperties); } } - protected structuralEqualityStep ( + protected structuralEqualityStep( other: ObjectType, _conflateNumbers: boolean, - queue: (a: Type, b: Type) => boolean, + queue: (a: Type, b: Type) => boolean ): boolean { const pa = this.getProperties(); const pb = other.getProperties(); @@ -633,42 +657,42 @@ export class ObjectType extends Type { const thisAdditionalProperties = this.getAdditionalProperties(); const otherAdditionalProperties = other.getAdditionalProperties(); - if (thisAdditionalProperties === undefined !== (otherAdditionalProperties === undefined)) return false; + if ((thisAdditionalProperties === undefined) !== (otherAdditionalProperties === undefined)) return false; if (thisAdditionalProperties === undefined || otherAdditionalProperties === undefined) return true; return queue(thisAdditionalProperties, otherAdditionalProperties); } } export class ClassType extends ObjectType { - constructor ( + public constructor( typeRef: TypeRef, graph: TypeGraph, isFixed: boolean, - properties: ReadonlyMap | undefined, + properties: ReadonlyMap | undefined ) { super(typeRef, graph, "class", isFixed, properties, undefined); } } export class MapType extends ObjectType { - constructor (typeRef: TypeRef, graph: TypeGraph, valuesRef: TypeRef | undefined) { + public constructor(typeRef: TypeRef, graph: TypeGraph, valuesRef: TypeRef | undefined) { super( typeRef, graph, "map", false, definedMap(valuesRef, () => new Map()), - valuesRef, + valuesRef ); } // FIXME: Remove and use `getAdditionalProperties()` instead. - get values (): Type { + public get values(): Type { return defined(this.getAdditionalProperties()); } } -export function enumTypeIdentity (attributes: TypeAttributes, cases: ReadonlySet): MaybeTypeIdentity { +export function enumTypeIdentity(attributes: TypeAttributes, cases: ReadonlySet): MaybeTypeIdentity { if (hasUniqueIdentityAttributes(attributes)) return undefined; return new TypeIdentity("enum", [identityAttributes(attributes), cases]); } @@ -676,44 +700,48 @@ export function enumTypeIdentity (attributes: TypeAttributes, cases: ReadonlySet export class EnumType extends Type { public readonly kind = "enum"; - constructor (typeRef: TypeRef, graph: TypeGraph, readonly cases: ReadonlySet) { + public constructor( + typeRef: TypeRef, + graph: TypeGraph, + public readonly cases: ReadonlySet + ) { super(typeRef, graph); } - get isNullable (): boolean { + public get isNullable(): boolean { return false; } - isPrimitive (): this is PrimitiveType { + public isPrimitive(): this is PrimitiveType { return false; } - get identity (): MaybeTypeIdentity { + public get identity(): MaybeTypeIdentity { return enumTypeIdentity(this.getAttributes(), this.cases); } - getNonAttributeChildren (): Set { + public getNonAttributeChildren(): Set { return new Set(); } - reconstitute(builder: TypeReconstituter): void { + public reconstitute(builder: TypeReconstituter): void { builder.getEnumType(this.cases); } - protected structuralEqualityStep ( + protected structuralEqualityStep( other: EnumType, _conflateNumbers: boolean, - _queue: (a: Type, b: Type) => void, + _queue: (a: Type, b: Type) => void ): boolean { return areEqual(this.cases, other.cases); } } -export function setOperationCasesEqual ( +export function setOperationCasesEqual( typesA: Iterable, typesB: Iterable, conflateNumbers: boolean, - membersEqual: (a: Type, b: Type) => boolean, + membersEqual: (a: Type, b: Type) => boolean ): boolean { const ma = toReadonlySet(typesA); const mb = toReadonlySet(typesB); @@ -733,37 +761,37 @@ export function setOperationCasesEqual ( }); } -export function setOperationTypeIdentity ( +export function setOperationTypeIdentity( kind: TypeKind, attributes: TypeAttributes, - memberRefs: ReadonlySet, + memberRefs: ReadonlySet ): MaybeTypeIdentity { if (hasUniqueIdentityAttributes(attributes)) return undefined; return new TypeIdentity(kind, [identityAttributes(attributes), memberRefs]); } -export function unionTypeIdentity (attributes: TypeAttributes, memberRefs: ReadonlySet): MaybeTypeIdentity { +export function unionTypeIdentity(attributes: TypeAttributes, memberRefs: ReadonlySet): MaybeTypeIdentity { return setOperationTypeIdentity("union", attributes, memberRefs); } -export function intersectionTypeIdentity ( +export function intersectionTypeIdentity( attributes: TypeAttributes, - memberRefs: ReadonlySet, + memberRefs: ReadonlySet ): MaybeTypeIdentity { return setOperationTypeIdentity("intersection", attributes, memberRefs); } export abstract class SetOperationType extends Type { - constructor ( + public constructor( typeRef: TypeRef, graph: TypeGraph, public readonly kind: TypeKind, - private _memberRefs?: ReadonlySet, + private _memberRefs?: ReadonlySet ) { super(typeRef, graph); } - setMembers (memberRefs: ReadonlySet): void { + public setMembers(memberRefs: ReadonlySet): void { if (this._memberRefs !== undefined) { return panic("Can only set map members once"); } @@ -771,7 +799,7 @@ export abstract class SetOperationType extends Type { this._memberRefs = memberRefs; } - protected getMemberRefs (): ReadonlySet { + protected getMemberRefs(): ReadonlySet { if (this._memberRefs === undefined) { return panic("Map members accessed before they were set"); } @@ -779,31 +807,31 @@ export abstract class SetOperationType extends Type { return this._memberRefs; } - get members (): ReadonlySet { + public get members(): ReadonlySet { return setMap(this.getMemberRefs(), tref => derefTypeRef(tref, this.graph)); } - get sortedMembers (): ReadonlySet { + public get sortedMembers(): ReadonlySet { return this.getNonAttributeChildren(); } - getNonAttributeChildren (): Set { + public getNonAttributeChildren(): Set { // FIXME: We're assuming no two members of the same kind. return setSortBy(this.members, t => t.kind); } - isPrimitive (): this is PrimitiveType { + public isPrimitive(): this is PrimitiveType { return false; } - get identity (): MaybeTypeIdentity { + public get identity(): MaybeTypeIdentity { return setOperationTypeIdentity(this.kind, this.getAttributes(), this.getMemberRefs()); } protected reconstituteSetOperation( builder: TypeReconstituter, canonicalOrder: boolean, - getType: (members: ReadonlySet | undefined) => void, + getType: (members: ReadonlySet | undefined) => void ): void { const sortedMemberRefs = mapMap(this.sortedMembers.entries(), t => t.typeRef); const membersInOrder = canonicalOrder ? this.sortedMembers : this.members; @@ -817,25 +845,28 @@ export abstract class SetOperationType extends Type { } } - protected structuralEqualityStep ( + protected structuralEqualityStep( other: SetOperationType, conflateNumbers: boolean, - queue: (a: Type, b: Type) => boolean, + queue: (a: Type, b: Type) => boolean ): boolean { return setOperationCasesEqual(this.members, other.members, conflateNumbers, queue); } } export class IntersectionType extends SetOperationType { - constructor (typeRef: TypeRef, graph: TypeGraph, memberRefs?: ReadonlySet) { + public constructor(typeRef: TypeRef, graph: TypeGraph, memberRefs?: ReadonlySet) { super(typeRef, graph, "intersection", memberRefs); } - get isNullable (): boolean { + public get isNullable(): boolean { return panic("isNullable not implemented for IntersectionType"); } - reconstitute(builder: TypeReconstituter, canonicalOrder: boolean): void { + public reconstitute( + builder: TypeReconstituter, + canonicalOrder: boolean + ): void { this.reconstituteSetOperation(builder, canonicalOrder, members => { if (members === undefined) { builder.getUniqueIntersectionType(); @@ -847,31 +878,31 @@ export class IntersectionType extends SetOperationType { } export class UnionType extends SetOperationType { - constructor (typeRef: TypeRef, graph: TypeGraph, memberRefs?: ReadonlySet) { + public constructor(typeRef: TypeRef, graph: TypeGraph, memberRefs?: ReadonlySet) { super(typeRef, graph, "union", memberRefs); if (memberRefs !== undefined) { messageAssert(memberRefs.size > 0, "IRNoEmptyUnions", {}); } } - setMembers (memberRefs: ReadonlySet): void { + public setMembers(memberRefs: ReadonlySet): void { messageAssert(memberRefs.size > 0, "IRNoEmptyUnions", {}); super.setMembers(memberRefs); } - get stringTypeMembers (): ReadonlySet { + public get stringTypeMembers(): ReadonlySet { return setFilter(this.members, t => isPrimitiveStringTypeKind(t.kind) || t.kind === "enum"); } - findMember (kind: TypeKind): Type | undefined { + public findMember(kind: TypeKind): Type | undefined { return iterableFind(this.members, t => t.kind === kind); } - get isNullable (): boolean { + public get isNullable(): boolean { return this.findMember("null") !== undefined; } - get isCanonical (): boolean { + public get isCanonical(): boolean { const members = this.members; if (members.size <= 1) return false; const kinds = setMap(members, t => t.kind); @@ -889,7 +920,10 @@ export class UnionType extends SetOperationType { return true; } - reconstitute(builder: TypeReconstituter, canonicalOrder: boolean): void { + public reconstitute( + builder: TypeReconstituter, + canonicalOrder: boolean + ): void { this.reconstituteSetOperation(builder, canonicalOrder, members => { if (members === undefined) { builder.getUniqueUnionType(); diff --git a/packages/quicktype-core/src/TypeBuilder.ts b/packages/quicktype-core/src/TypeBuilder.ts index 55d521857..d9a8b17ef 100644 --- a/packages/quicktype-core/src/TypeBuilder.ts +++ b/packages/quicktype-core/src/TypeBuilder.ts @@ -8,7 +8,7 @@ import { areEqual, setUnionManyInto, definedMap, - withDefault, + withDefault } from "collection-utils"; import { @@ -18,7 +18,7 @@ import { type MaybeTypeIdentity, type TypeIdentity, type TransformedStringTypeKind, - type TypeKind, + type TypeKind } from "./Type"; import { PrimitiveType, @@ -38,40 +38,35 @@ import { unionTypeIdentity, intersectionTypeIdentity, isPrimitiveStringTypeKind, - transformedStringTypeKinds, + transformedStringTypeKinds } from "./Type"; -import { type TypeRef} from "./TypeGraph"; +import { type TypeRef } from "./TypeGraph"; import { TypeGraph, makeTypeRef, derefTypeRef, typeRefIndex, assertTypeRefGraph } from "./TypeGraph"; -import { - type TypeAttributes} from "./attributes/TypeAttributes"; -import { - combineTypeAttributes, - TypeAttributeKind, - emptyTypeAttributes, -} from "./attributes/TypeAttributes"; +import { type TypeAttributes } from "./attributes/TypeAttributes"; +import { combineTypeAttributes, TypeAttributeKind, emptyTypeAttributes } from "./attributes/TypeAttributes"; import { defined, assert, panic } from "./support/Support"; import { stringTypesTypeAttributeKind, StringTypes } from "./attributes/StringTypes"; // FIXME: Don't infer provenance. All original types should be present in // non-inferred form in the final graph. class ProvenanceTypeAttributeKind extends TypeAttributeKind> { - constructor () { + public constructor() { super("provenance"); } - appliesToTypeKind (_kind: TypeKind): boolean { + public appliesToTypeKind(_kind: TypeKind): boolean { return true; } - combine (arr: Array>): Set { + public combine(arr: Array>): Set { return setUnionManyInto(new Set(), arr); } - makeInferred (p: Set): Set { + public makeInferred(p: Set): Set { return p; } - stringify (p: Set): string { + public stringify(p: Set): string { return Array.from(p) .sort() .map(i => i.toString()) @@ -83,7 +78,7 @@ export const provenanceTypeAttributeKind: TypeAttributeKind> = new P export type StringTypeMapping = ReadonlyMap; -export function stringTypeMappingGet (stm: StringTypeMapping, kind: TransformedStringTypeKind): PrimitiveStringTypeKind { +export function stringTypeMappingGet(stm: StringTypeMapping, kind: TransformedStringTypeKind): PrimitiveStringTypeKind { const mapped = stm.get(kind); if (mapped === undefined) return "string"; return mapped; @@ -91,12 +86,12 @@ export function stringTypeMappingGet (stm: StringTypeMapping, kind: TransformedS let noStringTypeMapping: StringTypeMapping | undefined; -export function getNoStringTypeMapping (): StringTypeMapping { +export function getNoStringTypeMapping(): StringTypeMapping { if (noStringTypeMapping === undefined) { noStringTypeMapping = new Map( Array.from(transformedStringTypeKinds).map( - k => [k, k] as [TransformedStringTypeKind, PrimitiveStringTypeKind], - ), + k => [k, k] as [TransformedStringTypeKind, PrimitiveStringTypeKind] + ) ); } @@ -104,7 +99,7 @@ export function getNoStringTypeMapping (): StringTypeMapping { } export class TypeBuilder { - readonly typeGraph: TypeGraph; + public readonly typeGraph: TypeGraph; protected readonly topLevels: Map = new Map(); @@ -114,32 +109,32 @@ export class TypeBuilder { private _addedForwardingIntersection = false; - constructor ( + public constructor( typeGraphSerial: number, private readonly _stringTypeMapping: StringTypeMapping, - readonly canonicalOrder: boolean, + public readonly canonicalOrder: boolean, private readonly _allPropertiesOptional: boolean, private readonly _addProvenanceAttributes: boolean, - inheritsProvenanceAttributes: boolean, + inheritsProvenanceAttributes: boolean ) { assert( !_addProvenanceAttributes || !inheritsProvenanceAttributes, - "We can't both inherit as well as add provenance", + "We can't both inherit as well as add provenance" ); this.typeGraph = new TypeGraph(this, typeGraphSerial, _addProvenanceAttributes || inheritsProvenanceAttributes); } - addTopLevel (name: string, tref: TypeRef): void { + public addTopLevel(name: string, tref: TypeRef): void { // assert(t.typeGraph === this.typeGraph, "Adding top-level to wrong type graph"); assert(!this.topLevels.has(name), "Trying to add top-level with existing name"); assert( this.types[typeRefIndex(tref)] !== undefined, - "Trying to add a top-level type that doesn't exist (yet?)", + "Trying to add a top-level type that doesn't exist (yet?)" ); this.topLevels.set(name, tref); } - reserveTypeRef (): TypeRef { + public reserveTypeRef(): TypeRef { const index = this.types.length; // console.log(`reserving ${index}`); this.types.push(undefined); @@ -151,17 +146,17 @@ export class TypeBuilder { return tref; } - private assertTypeRefGraph (tref: TypeRef | undefined): void { + private assertTypeRefGraph(tref: TypeRef | undefined): void { if (tref === undefined) return; assertTypeRefGraph(tref, this.typeGraph); } - private assertTypeRefSetGraph (trefs: ReadonlySet | undefined): void { + private assertTypeRefSetGraph(trefs: ReadonlySet | undefined): void { if (trefs === undefined) return; trefs.forEach(tref => this.assertTypeRefGraph(tref)); } - private filterTypeAttributes (t: Type, attributes: TypeAttributes): TypeAttributes { + private filterTypeAttributes(t: Type, attributes: TypeAttributes): TypeAttributes { const filtered = mapFilter(attributes, (_, k) => k.appliesToTypeKind(t.kind)); if (attributes.size !== filtered.size) { this.setLostTypeAttributes(); @@ -170,7 +165,7 @@ export class TypeBuilder { return filtered; } - private commitType (tref: TypeRef, t: Type): void { + private commitType(tref: TypeRef, t: Type): void { this.assertTypeRefGraph(tref); const index = typeRefIndex(tref); // const name = names !== undefined ? ` ${names.combinedName}` : ""; @@ -183,7 +178,7 @@ export class TypeBuilder { protected addType( forwardingRef: TypeRef | undefined, creator: (tref: TypeRef) => T, - attributes: TypeAttributes | undefined, + attributes: TypeAttributes | undefined ): TypeRef { if (forwardingRef !== undefined) { this.assertTypeRefGraph(forwardingRef); @@ -201,7 +196,7 @@ export class TypeBuilder { return tref; } - typeAtIndex (index: number): Type { + public typeAtIndex(index: number): Type { const maybeType = this.types[index]; if (maybeType === undefined) { return panic("Trying to deref an undefined type in a type builder"); @@ -210,13 +205,13 @@ export class TypeBuilder { return maybeType; } - atIndex (index: number): [Type, TypeAttributes] { + public atIndex(index: number): [Type, TypeAttributes] { const t = this.typeAtIndex(index); const attribtues = this.typeAttributes[index]; return [t, attribtues]; } - addAttributes (tref: TypeRef, attributes: TypeAttributes): void { + public addAttributes(tref: TypeRef, attributes: TypeAttributes): void { this.assertTypeRefGraph(tref); const index = typeRefIndex(tref); const existingAttributes = this.typeAttributes[index]; @@ -227,7 +222,7 @@ export class TypeBuilder { if (existing === undefined) return false; return areEqual(existing, v); }), - "Can't add different identity type attributes to an existing type", + "Can't add different identity type attributes to an existing type" ); const maybeType = this.types[index]; if (maybeType !== undefined) { @@ -238,46 +233,46 @@ export class TypeBuilder { this.typeAttributes[index] = combineTypeAttributes("union", existingAttributes, nonIdentityAttributes); } - finish (): TypeGraph { + public finish(): TypeGraph { this.typeGraph.freeze(this.topLevels, this.types.map(defined), this.typeAttributes); return this.typeGraph; } - protected addForwardingIntersection (forwardingRef: TypeRef, tref: TypeRef): TypeRef { + protected addForwardingIntersection(forwardingRef: TypeRef, tref: TypeRef): TypeRef { this.assertTypeRefGraph(tref); this._addedForwardingIntersection = true; return this.addType(forwardingRef, tr => new IntersectionType(tr, this.typeGraph, new Set([tref])), undefined); } - protected forwardIfNecessary (forwardingRef: TypeRef | undefined, tref: undefined): undefined; - protected forwardIfNecessary (forwardingRef: TypeRef | undefined, tref: TypeRef): TypeRef; - protected forwardIfNecessary (forwardingRef: TypeRef | undefined, tref: TypeRef | undefined): TypeRef | undefined; - protected forwardIfNecessary (forwardingRef: TypeRef | undefined, tref: TypeRef | undefined): TypeRef | undefined { + protected forwardIfNecessary(forwardingRef: TypeRef | undefined, tref: undefined): undefined; + protected forwardIfNecessary(forwardingRef: TypeRef | undefined, tref: TypeRef): TypeRef; + protected forwardIfNecessary(forwardingRef: TypeRef | undefined, tref: TypeRef | undefined): TypeRef | undefined; + protected forwardIfNecessary(forwardingRef: TypeRef | undefined, tref: TypeRef | undefined): TypeRef | undefined { if (tref === undefined) return undefined; if (forwardingRef === undefined) return tref; return this.addForwardingIntersection(forwardingRef, tref); } - get didAddForwardingIntersection (): boolean { + public get didAddForwardingIntersection(): boolean { return this._addedForwardingIntersection; } private readonly _typeForIdentity: EqualityMap = new EqualityMap(); - private registerTypeForIdentity (identity: MaybeTypeIdentity, tref: TypeRef): void { + private registerTypeForIdentity(identity: MaybeTypeIdentity, tref: TypeRef): void { if (identity === undefined) return; this._typeForIdentity.set(identity, tref); } - protected makeIdentity (maker: () => MaybeTypeIdentity): MaybeTypeIdentity { + protected makeIdentity(maker: () => MaybeTypeIdentity): MaybeTypeIdentity { return maker(); } - private getOrAddType ( + private getOrAddType( identityMaker: () => MaybeTypeIdentity, creator: (tr: TypeRef) => Type, attributes: TypeAttributes | undefined, - forwardingRef: TypeRef | undefined, + forwardingRef: TypeRef | undefined ): TypeRef { const identity = this.makeIdentity(identityMaker); let maybeTypeRef: TypeRef | undefined; @@ -296,7 +291,7 @@ export class TypeBuilder { // asserts that no identity attributes are added later. this.addAttributes( result, - mapFilter(attributes, (_, k) => !k.inIdentity), + mapFilter(attributes, (_, k) => !k.inIdentity) ); } @@ -308,11 +303,15 @@ export class TypeBuilder { return tref; } - private registerType (t: Type): void { + private registerType(t: Type): void { this.registerTypeForIdentity(t.identity, t.typeRef); } - getPrimitiveType (kind: PrimitiveTypeKind, maybeAttributes?: TypeAttributes, forwardingRef?: TypeRef): TypeRef { + public getPrimitiveType( + kind: PrimitiveTypeKind, + maybeAttributes?: TypeAttributes, + forwardingRef?: TypeRef + ): TypeRef { const attributes = withDefault(maybeAttributes, emptyTypeAttributes); // FIXME: Why do date/time types need a StringTypes attribute? // FIXME: Remove this from here and put it into flattenStrings @@ -329,21 +328,25 @@ export class TypeBuilder { () => primitiveTypeIdentity(kind, attributes), tr => new PrimitiveType(tr, this.typeGraph, kind), attributes, - forwardingRef, + forwardingRef ); } - getStringType (attributes: TypeAttributes, stringTypes: StringTypes | undefined, forwardingRef?: TypeRef): TypeRef { + public getStringType( + attributes: TypeAttributes, + stringTypes: StringTypes | undefined, + forwardingRef?: TypeRef + ): TypeRef { const existingStringTypes = mapFind(attributes, (_, k) => k === stringTypesTypeAttributeKind); assert( - stringTypes === undefined !== (existingStringTypes === undefined), - "Must instantiate string type with one enum case attribute", + (stringTypes === undefined) !== (existingStringTypes === undefined), + "Must instantiate string type with one enum case attribute" ); if (existingStringTypes === undefined) { attributes = combineTypeAttributes( "union", attributes, - stringTypesTypeAttributeKind.makeAttributes(defined(stringTypes)), + stringTypesTypeAttributeKind.makeAttributes(defined(stringTypes)) ); } @@ -351,28 +354,28 @@ export class TypeBuilder { () => primitiveTypeIdentity("string", attributes), tr => new PrimitiveType(tr, this.typeGraph, "string"), attributes, - forwardingRef, + forwardingRef ); } - getEnumType (attributes: TypeAttributes, cases: ReadonlySet, forwardingRef?: TypeRef): TypeRef { + public getEnumType(attributes: TypeAttributes, cases: ReadonlySet, forwardingRef?: TypeRef): TypeRef { return this.getOrAddType( () => enumTypeIdentity(attributes, cases), tr => new EnumType(tr, this.typeGraph, cases), attributes, - forwardingRef, + forwardingRef ); } - makeClassProperty (tref: TypeRef, isOptional: boolean): ClassProperty { + public makeClassProperty(tref: TypeRef, isOptional: boolean): ClassProperty { return new ClassProperty(tref, this.typeGraph, isOptional); } - getUniqueObjectType ( + public getUniqueObjectType( attributes: TypeAttributes, properties: ReadonlyMap | undefined, additionalProperties: TypeRef | undefined, - forwardingRef?: TypeRef, + forwardingRef?: TypeRef ): TypeRef { this.assertTypeRefGraph(additionalProperties); @@ -380,29 +383,29 @@ export class TypeBuilder { return this.addType( forwardingRef, tref => new ObjectType(tref, this.typeGraph, "object", true, properties, additionalProperties), - attributes, + attributes ); } - getUniqueMapType (forwardingRef?: TypeRef): TypeRef { + public getUniqueMapType(forwardingRef?: TypeRef): TypeRef { return this.addType(forwardingRef, tr => new MapType(tr, this.typeGraph, undefined), undefined); } - getMapType (attributes: TypeAttributes, values: TypeRef, forwardingRef?: TypeRef): TypeRef { + public getMapType(attributes: TypeAttributes, values: TypeRef, forwardingRef?: TypeRef): TypeRef { this.assertTypeRefGraph(values); return this.getOrAddType( () => mapTypeIdentify(attributes, values), tr => new MapType(tr, this.typeGraph, values), attributes, - forwardingRef, + forwardingRef ); } - setObjectProperties ( + public setObjectProperties( ref: TypeRef, properties: ReadonlyMap, - additionalProperties: TypeRef | undefined, + additionalProperties: TypeRef | undefined ): void { this.assertTypeRefGraph(additionalProperties); @@ -415,22 +418,22 @@ export class TypeBuilder { this.registerType(type); } - getUniqueArrayType (forwardingRef?: TypeRef): TypeRef { + public getUniqueArrayType(forwardingRef?: TypeRef): TypeRef { return this.addType(forwardingRef, tr => new ArrayType(tr, this.typeGraph, undefined), undefined); } - getArrayType (attributes: TypeAttributes, items: TypeRef, forwardingRef?: TypeRef): TypeRef { + public getArrayType(attributes: TypeAttributes, items: TypeRef, forwardingRef?: TypeRef): TypeRef { this.assertTypeRefGraph(items); return this.getOrAddType( () => arrayTypeIdentity(attributes, items), tr => new ArrayType(tr, this.typeGraph, items), attributes, - forwardingRef, + forwardingRef ); } - setArrayItems (ref: TypeRef, items: TypeRef): void { + public setArrayItems(ref: TypeRef, items: TypeRef): void { this.assertTypeRefGraph(items); const type = derefTypeRef(ref, this.typeGraph); @@ -442,7 +445,9 @@ export class TypeBuilder { this.registerType(type); } - modifyPropertiesIfNecessary (properties: ReadonlyMap): ReadonlyMap { + public modifyPropertiesIfNecessary( + properties: ReadonlyMap + ): ReadonlyMap { properties.forEach(p => this.assertTypeRefGraph(p.typeRef)); if (this.canonicalOrder) { @@ -456,81 +461,85 @@ export class TypeBuilder { return properties; } - getClassType ( + public getClassType( attributes: TypeAttributes, properties: ReadonlyMap, - forwardingRef?: TypeRef, + forwardingRef?: TypeRef ): TypeRef { properties = this.modifyPropertiesIfNecessary(properties); return this.getOrAddType( () => classTypeIdentity(attributes, properties), tr => new ClassType(tr, this.typeGraph, false, properties), attributes, - forwardingRef, + forwardingRef ); } // FIXME: Maybe just distinguish between this and `getClassType` // via a flag? That would make `ClassType.map` simpler. - getUniqueClassType ( + public getUniqueClassType( attributes: TypeAttributes, isFixed: boolean, properties: ReadonlyMap | undefined, - forwardingRef?: TypeRef, + forwardingRef?: TypeRef ): TypeRef { properties = definedMap(properties, p => this.modifyPropertiesIfNecessary(p)); return this.addType( forwardingRef, tref => new ClassType(tref, this.typeGraph, isFixed, properties), - attributes, + attributes ); } - getUnionType (attributes: TypeAttributes, members: ReadonlySet, forwardingRef?: TypeRef): TypeRef { + public getUnionType(attributes: TypeAttributes, members: ReadonlySet, forwardingRef?: TypeRef): TypeRef { this.assertTypeRefSetGraph(members); return this.getOrAddType( () => unionTypeIdentity(attributes, members), tr => new UnionType(tr, this.typeGraph, members), attributes, - forwardingRef, + forwardingRef ); } // FIXME: why do we sometimes call this with defined members??? - getUniqueUnionType ( + public getUniqueUnionType( attributes: TypeAttributes, members: ReadonlySet | undefined, - forwardingRef?: TypeRef, + forwardingRef?: TypeRef ): TypeRef { this.assertTypeRefSetGraph(members); return this.addType(forwardingRef, tref => new UnionType(tref, this.typeGraph, members), attributes); } - getIntersectionType (attributes: TypeAttributes, members: ReadonlySet, forwardingRef?: TypeRef): TypeRef { + public getIntersectionType( + attributes: TypeAttributes, + members: ReadonlySet, + forwardingRef?: TypeRef + ): TypeRef { this.assertTypeRefSetGraph(members); return this.getOrAddType( () => intersectionTypeIdentity(attributes, members), tr => new IntersectionType(tr, this.typeGraph, members), attributes, - forwardingRef, + forwardingRef ); } // FIXME: why do we sometimes call this with defined members??? - getUniqueIntersectionType ( + public getUniqueIntersectionType( attributes: TypeAttributes, members: ReadonlySet | undefined, - forwardingRef?: TypeRef, + forwardingRef?: TypeRef ): TypeRef { this.assertTypeRefSetGraph(members); return this.addType(forwardingRef, tref => new IntersectionType(tref, this.typeGraph, members), attributes); } - setSetOperationMembers (ref: TypeRef, members: ReadonlySet): void { + public setSetOperationMembers(ref: TypeRef, members: ReadonlySet): void { this.assertTypeRefSetGraph(members); const type = derefTypeRef(ref, this.typeGraph); @@ -542,7 +551,7 @@ export class TypeBuilder { this.registerType(type); } - setLostTypeAttributes (): void { + public setLostTypeAttributes(): void { return; } } diff --git a/packages/quicktype-core/src/TypeGraph.ts b/packages/quicktype-core/src/TypeGraph.ts index 5ffa13a48..2e5ddb1c4 100644 --- a/packages/quicktype-core/src/TypeGraph.ts +++ b/packages/quicktype-core/src/TypeGraph.ts @@ -1,17 +1,17 @@ import { iterableFirst, setFilter, setUnionManyInto, setSubtract, mapMap, mapSome, setMap } from "collection-utils"; -import { type Type} from "./Type"; +import { type Type } from "./Type"; import { ClassType, UnionType, IntersectionType } from "./Type"; -import { type SeparatedNamedTypes} from "./TypeUtils"; +import { type SeparatedNamedTypes } from "./TypeUtils"; import { separateNamedTypes, isNamedType, combineTypeAttributesOfTypes } from "./TypeUtils"; import { defined, assert, panic, mustNotHappen } from "./support/Support"; -import { type TypeBuilder, type StringTypeMapping} from "./TypeBuilder"; +import { type TypeBuilder, type StringTypeMapping } from "./TypeBuilder"; import { getNoStringTypeMapping, provenanceTypeAttributeKind } from "./TypeBuilder"; import { type BaseGraphRewriteBuilder } from "./GraphRewriting"; import { GraphRewriteBuilder, GraphRemapBuilder } from "./GraphRewriting"; import { TypeNames, namesTypeAttributeKind } from "./attributes/TypeNames"; import { Graph } from "./Graph"; -import { type TypeAttributeKind, type TypeAttributes} from "./attributes/TypeAttributes"; +import { type TypeAttributeKind, type TypeAttributes } from "./attributes/TypeAttributes"; import { emptyTypeAttributes } from "./attributes/TypeAttributes"; import { messageError } from "./Messages"; @@ -22,49 +22,49 @@ const indexMask = (1 << indexBits) - 1; const serialBits = 31 - indexBits; const serialMask = (1 << serialBits) - 1; -export function isTypeRef (x: any): x is TypeRef { +export function isTypeRef(x: any): x is TypeRef { return typeof x === "number"; } -export function makeTypeRef (graph: TypeGraph, index: number): TypeRef { +export function makeTypeRef(graph: TypeGraph, index: number): TypeRef { assert(index <= indexMask, "Too many types in graph"); - return (graph.serial & serialMask) << indexBits | index; + return ((graph.serial & serialMask) << indexBits) | index; } -export function typeRefIndex (tref: TypeRef): number { +export function typeRefIndex(tref: TypeRef): number { return tref & indexMask; } -export function assertTypeRefGraph (tref: TypeRef, graph: TypeGraph): void { +export function assertTypeRefGraph(tref: TypeRef, graph: TypeGraph): void { assert( - (tref >> indexBits & serialMask) === (graph.serial & serialMask), - "Mixing the wrong type reference and graph", + ((tref >> indexBits) & serialMask) === (graph.serial & serialMask), + "Mixing the wrong type reference and graph" ); } -function getGraph (graphOrBuilder: TypeGraph | BaseGraphRewriteBuilder): TypeGraph { +function getGraph(graphOrBuilder: TypeGraph | BaseGraphRewriteBuilder): TypeGraph { if (graphOrBuilder instanceof TypeGraph) return graphOrBuilder; return graphOrBuilder.originalGraph; } -export function derefTypeRef (tref: TypeRef, graphOrBuilder: TypeGraph | BaseGraphRewriteBuilder): Type { +export function derefTypeRef(tref: TypeRef, graphOrBuilder: TypeGraph | BaseGraphRewriteBuilder): Type { const graph = getGraph(graphOrBuilder); assertTypeRefGraph(tref, graph); return graph.typeAtIndex(typeRefIndex(tref)); } -export function attributesForTypeRef ( +export function attributesForTypeRef( tref: TypeRef, - graphOrBuilder: TypeGraph | BaseGraphRewriteBuilder, + graphOrBuilder: TypeGraph | BaseGraphRewriteBuilder ): TypeAttributes { const graph = getGraph(graphOrBuilder); assertTypeRefGraph(tref, graph); return graph.atIndex(typeRefIndex(tref))[1]; } -export function typeAndAttributesForTypeRef ( +export function typeAndAttributesForTypeRef( tref: TypeRef, - graphOrBuilder: TypeGraph | BaseGraphRewriteBuilder, + graphOrBuilder: TypeGraph | BaseGraphRewriteBuilder ): [Type, TypeAttributes] { const graph = getGraph(graphOrBuilder); assertTypeRefGraph(tref, graph); @@ -74,15 +74,18 @@ export function typeAndAttributesForTypeRef ( export class TypeAttributeStore { private readonly _topLevelValues: Map = new Map(); - constructor (private readonly _typeGraph: TypeGraph, private _values: Array) {} + public constructor( + private readonly _typeGraph: TypeGraph, + private _values: Array + ) {} - private getTypeIndex (t: Type): number { + private getTypeIndex(t: Type): number { const tref = t.typeRef; assertTypeRefGraph(tref, this._typeGraph); return typeRefIndex(tref); } - attributesForType (t: Type): TypeAttributes { + public attributesForType(t: Type): TypeAttributes { const index = this.getTypeIndex(t); const maybeAttributes = this._values[index]; if (maybeAttributes !== undefined) { @@ -92,7 +95,7 @@ export class TypeAttributeStore { return emptyTypeAttributes; } - attributesForTopLevel (name: string): TypeAttributes { + public attributesForTopLevel(name: string): TypeAttributes { const maybeAttributes = this._topLevelValues.get(name); if (maybeAttributes !== undefined) { return maybeAttributes; @@ -101,12 +104,12 @@ export class TypeAttributeStore { return emptyTypeAttributes; } - private setInMap(attributes: TypeAttributes, kind: TypeAttributeKind, value: T): TypeAttributes { + public setInMap(attributes: TypeAttributes, kind: TypeAttributeKind, value: T): TypeAttributes { // FIXME: This is potentially super slow return new Map(attributes).set(kind, value); } - set(kind: TypeAttributeKind, t: Type, value: T): void { + public set(kind: TypeAttributeKind, t: Type, value: T): void { const index = this.getTypeIndex(t); while (index >= this._values.length) { this._values.push(undefined); @@ -115,50 +118,50 @@ export class TypeAttributeStore { this._values[index] = this.setInMap(this.attributesForType(t), kind, value); } - setForTopLevel(kind: TypeAttributeKind, topLevelName: string, value: T): void { + public setForTopLevel(kind: TypeAttributeKind, topLevelName: string, value: T): void { this._topLevelValues.set(topLevelName, this.setInMap(this.attributesForTopLevel(topLevelName), kind, value)); } - private tryGetInMap(attributes: TypeAttributes, kind: TypeAttributeKind): T | undefined { + public tryGetInMap(attributes: TypeAttributes, kind: TypeAttributeKind): T | undefined { return attributes.get(kind); } - tryGet(kind: TypeAttributeKind, t: Type): T | undefined { + public tryGet(kind: TypeAttributeKind, t: Type): T | undefined { return this.tryGetInMap(this.attributesForType(t), kind); } - tryGetForTopLevel(kind: TypeAttributeKind, topLevelName: string): T | undefined { + public tryGetForTopLevel(kind: TypeAttributeKind, topLevelName: string): T | undefined { return this.tryGetInMap(this.attributesForTopLevel(topLevelName), kind); } } export class TypeAttributeStoreView { - constructor ( + public constructor( private readonly _attributeStore: TypeAttributeStore, - private readonly _definition: TypeAttributeKind, + private readonly _definition: TypeAttributeKind ) {} - set (t: Type, value: T): void { + public set(t: Type, value: T): void { this._attributeStore.set(this._definition, t, value); } - setForTopLevel (name: string, value: T): void { + public setForTopLevel(name: string, value: T): void { this._attributeStore.setForTopLevel(this._definition, name, value); } - tryGet (t: Type): T | undefined { + public tryGet(t: Type): T | undefined { return this._attributeStore.tryGet(this._definition, t); } - get (t: Type): T { + public get(t: Type): T { return defined(this.tryGet(t)); } - tryGetForTopLevel (name: string): T | undefined { + public tryGetForTopLevel(name: string): T | undefined { return this._attributeStore.tryGetForTopLevel(this._definition, name); } - getForTopLevel (name: string): T { + public getForTopLevel(name: string): T { return defined(this.tryGetForTopLevel(name)); } } @@ -178,26 +181,26 @@ export class TypeGraph { private _printOnRewrite = false; - constructor ( + public constructor( typeBuilder: TypeBuilder, - readonly serial: number, - private readonly _haveProvenanceAttributes: boolean, + public readonly serial: number, + private readonly _haveProvenanceAttributes: boolean ) { this._typeBuilder = typeBuilder; } - private get isFrozen (): boolean { + private get isFrozen(): boolean { return this._typeBuilder === undefined; } - get attributeStore (): TypeAttributeStore { + public get attributeStore(): TypeAttributeStore { return defined(this._attributeStore); } - freeze ( + public freeze( topLevels: ReadonlyMap, types: Type[], - typeAttributes: Array, + typeAttributes: Array ): void { assert(!this.isFrozen, "Tried to freeze TypeGraph a second time"); for (const t of types) { @@ -215,12 +218,12 @@ export class TypeGraph { this._topLevels = mapMap(topLevels, tref => derefTypeRef(tref, this)); } - get topLevels (): ReadonlyMap { + public get topLevels(): ReadonlyMap { assert(this.isFrozen, "Cannot get top-levels from a non-frozen graph"); return this._topLevels; } - typeAtIndex (index: number): Type { + public typeAtIndex(index: number): Type { if (this._typeBuilder !== undefined) { return this._typeBuilder.typeAtIndex(index); } @@ -228,7 +231,7 @@ export class TypeGraph { return defined(this._types)[index]; } - atIndex (index: number): [Type, TypeAttributes] { + public atIndex(index: number): [Type, TypeAttributes] { if (this._typeBuilder !== undefined) { return this._typeBuilder.atIndex(index); } @@ -237,11 +240,11 @@ export class TypeGraph { return [t, defined(this._attributeStore).attributesForType(t)]; } - private filterTypes (predicate: ((t: Type) => boolean) | undefined): ReadonlySet { + private filterTypes(predicate: ((t: Type) => boolean) | undefined): ReadonlySet { const seen = new Set(); let types: Type[] = []; - function addFromType (t: Type): void { + function addFromType(t: Type): void { if (seen.has(t)) return; seen.add(t); @@ -263,16 +266,16 @@ export class TypeGraph { return new Set(types); } - allNamedTypes (): ReadonlySet { + public allNamedTypes(): ReadonlySet { return this.filterTypes(isNamedType); } - allNamedTypesSeparated (): SeparatedNamedTypes { + public allNamedTypesSeparated(): SeparatedNamedTypes { const types = this.allNamedTypes(); return separateNamedTypes(types); } - private allProvenance (): ReadonlySet { + private allProvenance(): ReadonlySet { assert(this._haveProvenanceAttributes); const view = new TypeAttributeStoreView(this.attributeStore, provenanceTypeAttributeKind); @@ -286,11 +289,11 @@ export class TypeGraph { return result; } - setPrintOnRewrite (): void { + private setPrintOnRewrite(): void { this._printOnRewrite = true; } - private checkLostTypeAttributes (builder: BaseGraphRewriteBuilder, newGraph: TypeGraph): void { + private checkLostTypeAttributes(builder: BaseGraphRewriteBuilder, newGraph: TypeGraph): void { if (!this._haveProvenanceAttributes || builder.lostTypeAttributes) return; const oldProvenance = this.allProvenance(); @@ -302,7 +305,7 @@ export class TypeGraph { } } - private printRewrite (title: string): void { + private printRewrite(title: string): void { if (!this._printOnRewrite) return; console.log(`\n# ${title}`); @@ -314,14 +317,14 @@ export class TypeGraph { // That particular TypeBuilder will have to take as inputs types in the old // graph, but return types in the new graph. Recursive types must be handled // carefully. - rewrite( + public rewrite( title: string, stringTypeMapping: StringTypeMapping, alphabetizeProperties: boolean, replacementGroups: T[][], debugPrintReconstitution: boolean, replacer: (typesToReplace: ReadonlySet, builder: GraphRewriteBuilder, forwardingRef: TypeRef) => TypeRef, - force = false, + force = false ): TypeGraph { this.printRewrite(title); @@ -334,7 +337,7 @@ export class TypeGraph { this._haveProvenanceAttributes, replacementGroups, debugPrintReconstitution, - replacer, + replacer ); const newGraph = builder.finish(); @@ -350,13 +353,13 @@ export class TypeGraph { return removeIndirectionIntersections(newGraph, stringTypeMapping, debugPrintReconstitution); } - remap ( + public remap( title: string, stringTypeMapping: StringTypeMapping, alphabetizeProperties: boolean, map: ReadonlyMap, debugPrintRemapping: boolean, - force = false, + force = false ): TypeGraph { this.printRewrite(title); @@ -368,7 +371,7 @@ export class TypeGraph { alphabetizeProperties, this._haveProvenanceAttributes, map, - debugPrintRemapping, + debugPrintRemapping ); const newGraph = builder.finish(); @@ -384,19 +387,19 @@ export class TypeGraph { return newGraph; } - garbageCollect (alphabetizeProperties: boolean, debugPrintReconstitution: boolean): TypeGraph { + public garbageCollect(alphabetizeProperties: boolean, debugPrintReconstitution: boolean): TypeGraph { const newGraph = this.remap( "GC", getNoStringTypeMapping(), alphabetizeProperties, new Map(), debugPrintReconstitution, - true, + true ); return newGraph; } - rewriteFixedPoint (alphabetizeProperties: boolean, debugPrintReconstitution: boolean): TypeGraph { + public rewriteFixedPoint(alphabetizeProperties: boolean, debugPrintReconstitution: boolean): TypeGraph { let graph: TypeGraph = this; for (;;) { const newGraph = this.rewrite( @@ -406,7 +409,7 @@ export class TypeGraph { [], debugPrintReconstitution, mustNotHappen, - true, + true ); if (graph.allTypesUnordered().size === newGraph.allTypesUnordered().size) { return graph; @@ -416,16 +419,16 @@ export class TypeGraph { } } - allTypesUnordered (): ReadonlySet { + public allTypesUnordered(): ReadonlySet { assert(this.isFrozen, "Tried to get all graph types before it was frozen"); return new Set(defined(this._types)); } - makeGraph (invertDirection: boolean, childrenOfType: (t: Type) => ReadonlySet): Graph { + public makeGraph(invertDirection: boolean, childrenOfType: (t: Type) => ReadonlySet): Graph { return new Graph(defined(this._types), invertDirection, childrenOfType); } - getParentsOfType (t: Type): Set { + public getParentsOfType(t: Type): Set { assertTypeRefGraph(t.typeRef, this); if (this._parents === undefined) { const parents = defined(this._types).map(_ => new Set()); @@ -442,7 +445,7 @@ export class TypeGraph { return this._parents[t.index]; } - printGraph (): void { + private printGraph(): void { const types = defined(this._types); for (let i = 0; i < types.length; i++) { const t = types[i]; @@ -453,7 +456,7 @@ export class TypeGraph { parts.push( `children ${Array.from(children) .map(c => c.index) - .join(",")}`, + .join(",")}` ); } @@ -469,10 +472,10 @@ export class TypeGraph { } } -export function noneToAny ( +export function noneToAny( graph: TypeGraph, stringTypeMapping: StringTypeMapping, - debugPrintReconstitution: boolean, + debugPrintReconstitution: boolean ): TypeGraph { const noneTypes = setFilter(graph.allTypesUnordered(), t => t.kind === "none"); if (noneTypes.size === 0) { @@ -490,16 +493,16 @@ export function noneToAny ( const attributes = combineTypeAttributesOfTypes("union", types); const tref = builder.getPrimitiveType("any", attributes, forwardingRef); return tref; - }, + } ); } -export function optionalToNullable ( +export function optionalToNullable( graph: TypeGraph, stringTypeMapping: StringTypeMapping, - debugPrintReconstitution: boolean, + debugPrintReconstitution: boolean ): TypeGraph { - function rewriteClass (c: ClassType, builder: GraphRewriteBuilder, forwardingRef: TypeRef): TypeRef { + function rewriteClass(c: ClassType, builder: GraphRewriteBuilder, forwardingRef: TypeRef): TypeRef { const properties = mapMap(c.getProperties(), (p, name) => { const t = p.type; let ref: TypeRef; @@ -515,7 +518,7 @@ export function optionalToNullable ( } const attributes = namesTypeAttributeKind.setDefaultInAttributes(t.getAttributes(), () => - TypeNames.make(new Set([name]), new Set(), true), + TypeNames.make(new Set([name]), new Set(), true) ); ref = builder.getUnionType(attributes, members); } @@ -531,7 +534,7 @@ export function optionalToNullable ( const classesWithOptional = setFilter( graph.allTypesUnordered(), - t => t instanceof ClassType && mapSome(t.getProperties(), p => p.isOptional), + t => t instanceof ClassType && mapSome(t.getProperties(), p => p.isOptional) ); const replacementGroups = Array.from(classesWithOptional).map(c => [c as ClassType]); if (classesWithOptional.size === 0) { @@ -548,14 +551,14 @@ export function optionalToNullable ( assert(setOfClass.size === 1); const c = defined(iterableFirst(setOfClass)); return rewriteClass(c, builder, forwardingRef); - }, + } ); } -export function removeIndirectionIntersections ( +export function removeIndirectionIntersections( graph: TypeGraph, stringTypeMapping: StringTypeMapping, - debugPrintRemapping: boolean, + debugPrintRemapping: boolean ): TypeGraph { const map: Array<[Type, Type]> = []; diff --git a/packages/quicktype-core/src/TypeUtils.ts b/packages/quicktype-core/src/TypeUtils.ts index f85767fef..7a39c450a 100644 --- a/packages/quicktype-core/src/TypeUtils.ts +++ b/packages/quicktype-core/src/TypeUtils.ts @@ -1,32 +1,14 @@ import { setFilter, setSortBy, iterableFirst, setUnion, EqualityMap } from "collection-utils"; import { defined, panic, assert, assertNever } from "./support/Support"; -import { - type TypeAttributes, - type CombinationKind, -} from "./attributes/TypeAttributes"; -import { - combineTypeAttributes, - emptyTypeAttributes, -} from "./attributes/TypeAttributes"; -import { - type Type, - type PrimitiveType, - type ClassProperty, - type SetOperationType} from "./Type"; -import { - ArrayType, - EnumType, - ObjectType, - MapType, - ClassType, - UnionType, - isPrimitiveStringTypeKind, -} from "./Type"; +import { type TypeAttributes, type CombinationKind } from "./attributes/TypeAttributes"; +import { combineTypeAttributes, emptyTypeAttributes } from "./attributes/TypeAttributes"; +import { type Type, type PrimitiveType, type ClassProperty, type SetOperationType } from "./Type"; +import { ArrayType, EnumType, ObjectType, MapType, ClassType, UnionType, isPrimitiveStringTypeKind } from "./Type"; import { type StringTypes } from "./attributes/StringTypes"; import { stringTypesTypeAttributeKind } from "./attributes/StringTypes"; -export function assertIsObject (t: Type): ObjectType { +export function assertIsObject(t: Type): ObjectType { if (t instanceof ObjectType) { return t; } @@ -34,7 +16,7 @@ export function assertIsObject (t: Type): ObjectType { return panic("Supposed object type is not an object type"); } -export function assertIsClass (t: Type): ClassType { +export function assertIsClass(t: Type): ClassType { if (!(t instanceof ClassType)) { return panic("Supposed class type is not a class type"); } @@ -42,17 +24,17 @@ export function assertIsClass (t: Type): ClassType { return t; } -export function setOperationMembersRecursively ( +export function setOperationMembersRecursively( setOperation: T, combinationKind: CombinationKind | undefined ): [ReadonlySet, TypeAttributes]; -export function setOperationMembersRecursively ( +export function setOperationMembersRecursively( setOperations: T[], combinationKind: CombinationKind | undefined ): [ReadonlySet, TypeAttributes]; -export function setOperationMembersRecursively ( +export function setOperationMembersRecursively( oneOrMany: T | T[], - combinationKind: CombinationKind | undefined, + combinationKind: CombinationKind | undefined ): [ReadonlySet, TypeAttributes] { const setOperations = Array.isArray(oneOrMany) ? oneOrMany : [oneOrMany]; const kind = setOperations[0].kind; @@ -61,7 +43,7 @@ export function setOperationMembersRecursively ( const members = new Set(); let attributes = emptyTypeAttributes; - function process (t: Type): void { + function process(t: Type): void { if (t.kind === kind) { const so = t as T; if (processedSetOperations.has(so)) return; @@ -89,9 +71,9 @@ export function setOperationMembersRecursively ( return [members, attributes]; } -export function makeGroupsToFlatten ( +export function makeGroupsToFlatten( setOperations: Iterable, - include: ((members: ReadonlySet) => boolean) | undefined, + include: ((members: ReadonlySet) => boolean) | undefined ): Type[][] { const typeGroups = new EqualityMap, Set>(); for (const u of setOperations) { @@ -118,25 +100,25 @@ export function makeGroupsToFlatten ( return Array.from(typeGroups.values()).map(ts => Array.from(ts)); } -export function combineTypeAttributesOfTypes (combinationKind: CombinationKind, types: Iterable): TypeAttributes { +export function combineTypeAttributesOfTypes(combinationKind: CombinationKind, types: Iterable): TypeAttributes { return combineTypeAttributes( combinationKind, - Array.from(types).map(t => t.getAttributes()), + Array.from(types).map(t => t.getAttributes()) ); } -export function isAnyOrNull (t: Type): boolean { +export function isAnyOrNull(t: Type): boolean { return t.kind === "any" || t.kind === "null"; } // FIXME: We shouldn't have to sort here. This is just because we're not getting // back the right order from JSON Schema, due to the changes the intersection types // introduced. -export function removeNullFromUnion ( +export function removeNullFromUnion( t: UnionType, - sortBy: boolean | ((t: Type) => any) = false, + sortBy: boolean | ((t: Type) => any) = false ): [PrimitiveType | null, ReadonlySet] { - function sort (s: ReadonlySet): ReadonlySet { + function sort(s: ReadonlySet): ReadonlySet { if (sortBy === false) return s; if (sortBy === true) return setSortBy(s, m => m.kind); return setSortBy(s, sortBy); @@ -150,7 +132,7 @@ export function removeNullFromUnion ( return [nullType as PrimitiveType, sort(setFilter(t.members, m => m.kind !== "null"))]; } -export function removeNullFromType (t: Type): [PrimitiveType | null, ReadonlySet] { +export function removeNullFromType(t: Type): [PrimitiveType | null, ReadonlySet] { if (t.kind === "null") { return [t as PrimitiveType, new Set()]; } @@ -162,18 +144,18 @@ export function removeNullFromType (t: Type): [PrimitiveType | null, ReadonlySet return removeNullFromUnion(t); } -export function nullableFromUnion (t: UnionType): Type | null { +export function nullableFromUnion(t: UnionType): Type | null { const [hasNull, nonNulls] = removeNullFromUnion(t); if (hasNull === null) return null; if (nonNulls.size !== 1) return null; return defined(iterableFirst(nonNulls)); } -export function nonNullTypeCases (t: Type): ReadonlySet { +export function nonNullTypeCases(t: Type): ReadonlySet { return removeNullFromType(t)[1]; } -export function getNullAsOptional (cp: ClassProperty): [boolean, ReadonlySet] { +export function getNullAsOptional(cp: ClassProperty): [boolean, ReadonlySet] { const [maybeNull, nonNulls] = removeNullFromType(cp.type); if (cp.isOptional) { return [true, nonNulls]; @@ -184,7 +166,7 @@ export function getNullAsOptional (cp: ClassProperty): [boolean, ReadonlySet; } -export function separateNamedTypes (types: Iterable): SeparatedNamedTypes { +export function separateNamedTypes(types: Iterable): SeparatedNamedTypes { const objects = setFilter( types, - t => t.kind === "object" || t.kind === "class", + t => t.kind === "object" || t.kind === "class" ) as Set as ReadonlySet; const enums = setFilter(types, t => t instanceof EnumType) as Set as ReadonlySet; const unions = setFilter(types, t => t instanceof UnionType) as Set as ReadonlySet; @@ -205,17 +187,17 @@ export function separateNamedTypes (types: Iterable): SeparatedNamedTypes return { objects, enums, unions }; } -export function directlyReachableTypes (t: Type, setForType: (t: Type) => ReadonlySet | null): ReadonlySet { +export function directlyReachableTypes(t: Type, setForType: (t: Type) => ReadonlySet | null): ReadonlySet { const set = setForType(t); if (set !== null) return set; return setUnion(...Array.from(t.getNonAttributeChildren()).map(c => directlyReachableTypes(c, setForType))); } -export function directlyReachableSingleNamedType (type: Type): Type | undefined { +export function directlyReachableSingleNamedType(type: Type): Type | undefined { const definedTypes = directlyReachableTypes(type, t => { if ( - !(t instanceof UnionType) && isNamedType(t) || - t instanceof UnionType && nullableFromUnion(t) === null + (!(t instanceof UnionType) && isNamedType(t)) || + (t instanceof UnionType && nullableFromUnion(t) === null) ) { return new Set([t]); } @@ -226,7 +208,7 @@ export function directlyReachableSingleNamedType (type: Type): Type | undefined return iterableFirst(definedTypes); } -export function stringTypesForType (t: PrimitiveType): StringTypes { +export function stringTypesForType(t: PrimitiveType): StringTypes { assert(t.kind === "string", "Only strings can have string types"); const stringTypes = stringTypesTypeAttributeKind.tryGetInAttributes(t.getAttributes()); if (stringTypes === undefined) { @@ -242,7 +224,7 @@ export interface StringTypeMatchers { timeType?: (timeType: PrimitiveType) => U; } -export function matchTypeExhaustive ( +export function matchTypeExhaustive( t: Type, noneType: (noneType: PrimitiveType) => U, anyType: (anyType: PrimitiveType) => U, @@ -257,7 +239,7 @@ export function matchTypeExhaustive ( objectType: (objectType: ObjectType) => U, enumType: (enumType: EnumType) => U, unionType: (unionType: UnionType) => U, - transformedStringType: (transformedStringType: PrimitiveType) => U, + transformedStringType: (transformedStringType: PrimitiveType) => U ): U { if (t.isPrimitive()) { if (isPrimitiveStringTypeKind(t.kind)) { @@ -275,7 +257,7 @@ export function matchTypeExhaustive ( null: nullType, bool: boolType, integer: integerType, - double: doubleType, + double: doubleType }[kind]; if (f !== undefined) return f(t); return assertNever(f); @@ -288,7 +270,7 @@ export function matchTypeExhaustive ( return panic(`Unknown type ${t.kind}`); } -export function matchType ( +export function matchType( type: Type, anyType: (anyType: PrimitiveType) => U, nullType: (nullType: PrimitiveType) => U, @@ -301,9 +283,9 @@ export function matchType ( mapType: (mapType: MapType) => U, enumType: (enumType: EnumType) => U, unionType: (unionType: UnionType) => U, - transformedStringType?: (transformedStringType: PrimitiveType) => U, + transformedStringType?: (transformedStringType: PrimitiveType) => U ): U { - function typeNotSupported (t: Type) { + function typeNotSupported(t: Type) { return panic(`Unsupported type ${t.kind} in non-exhaustive match`); } @@ -322,19 +304,19 @@ export function matchType ( typeNotSupported, enumType, unionType, - transformedStringType || typeNotSupported, + transformedStringType || typeNotSupported ); } -export function matchCompoundType ( +export function matchCompoundType( t: Type, arrayType: (arrayType: ArrayType) => void, classType: (classType: ClassType) => void, mapType: (mapType: MapType) => void, objectType: (objectType: ObjectType) => void, - unionType: (unionType: UnionType) => void, + unionType: (unionType: UnionType) => void ): void { - function ignore (_: T): void { + function ignore(_: T): void { return; } @@ -353,6 +335,6 @@ export function matchCompoundType ( objectType, ignore, unionType, - ignore, + ignore ); } diff --git a/packages/quicktype-core/src/UnifyClasses.ts b/packages/quicktype-core/src/UnifyClasses.ts index b94bec7ad..dbf5fa4b2 100644 --- a/packages/quicktype-core/src/UnifyClasses.ts +++ b/packages/quicktype-core/src/UnifyClasses.ts @@ -7,15 +7,15 @@ import { type TypeBuilder } from "./TypeBuilder"; import { type TypeLookerUp, type GraphRewriteBuilder, type BaseGraphRewriteBuilder } from "./GraphRewriting"; import { UnionBuilder, TypeRefUnionAccumulator } from "./UnionBuilder"; import { panic, assert, defined } from "./support/Support"; -import { type TypeAttributes} from "./attributes/TypeAttributes"; +import { type TypeAttributes } from "./attributes/TypeAttributes"; import { combineTypeAttributes, emptyTypeAttributes } from "./attributes/TypeAttributes"; -import { type TypeRef} from "./TypeGraph"; +import { type TypeRef } from "./TypeGraph"; import { derefTypeRef } from "./TypeGraph"; -function getCliqueProperties ( +function getCliqueProperties( clique: ObjectType[], builder: TypeBuilder, - makePropertyType: (types: ReadonlySet) => TypeRef, + makePropertyType: (types: ReadonlySet) => TypeRef ): [ReadonlyMap, TypeRef | undefined, boolean] { let lostTypeAttributes = false; let propertyNames = new Set(); @@ -68,10 +68,10 @@ function getCliqueProperties ( return [unifiedProperties, unifiedAdditionalProperties, lostTypeAttributes]; } -function countProperties (clique: ObjectType[]): { - hasAdditionalProperties: boolean, - hasNonAnyAdditionalProperties: boolean, - hasProperties: boolean, +function countProperties(clique: ObjectType[]): { + hasAdditionalProperties: boolean; + hasNonAnyAdditionalProperties: boolean; + hasProperties: boolean; } { let hasProperties = false; let hasAdditionalProperties = false; @@ -94,25 +94,25 @@ function countProperties (clique: ObjectType[]): { } export class UnifyUnionBuilder extends UnionBuilder { - constructor ( + public constructor( typeBuilder: BaseGraphRewriteBuilder, private readonly _makeObjectTypes: boolean, private readonly _makeClassesFixed: boolean, - private readonly _unifyTypes: (typesToUnify: TypeRef[]) => TypeRef, + private readonly _unifyTypes: (typesToUnify: TypeRef[]) => TypeRef ) { super(typeBuilder); } - protected makeObject ( + protected makeObject( objectRefs: TypeRef[], typeAttributes: TypeAttributes, - forwardingRef: TypeRef | undefined, + forwardingRef: TypeRef | undefined ): TypeRef { const maybeTypeRef = this.typeBuilder.lookupTypeRefs(objectRefs, forwardingRef); if (maybeTypeRef !== undefined) { assert( forwardingRef === undefined || maybeTypeRef === forwardingRef, - "The forwarding ref must be consumed", + "The forwarding ref must be consumed" ); this.typeBuilder.addAttributes(maybeTypeRef, typeAttributes); return maybeTypeRef; @@ -125,19 +125,19 @@ export class UnifyUnionBuilder extends UnionBuilder assertIsObject(derefTypeRef(r, this.typeBuilder))); const { hasProperties, hasAdditionalProperties, hasNonAnyAdditionalProperties } = countProperties(objectTypes); - if (!this._makeObjectTypes && (hasNonAnyAdditionalProperties || !hasProperties && hasAdditionalProperties)) { + if (!this._makeObjectTypes && (hasNonAnyAdditionalProperties || (!hasProperties && hasAdditionalProperties))) { const propertyTypes = new Set(); for (const o of objectTypes) { setUnionInto( propertyTypes, - Array.from(o.getProperties().values()).map(cp => cp.typeRef), + Array.from(o.getProperties().values()).map(cp => cp.typeRef) ); } const additionalPropertyTypes = new Set( objectTypes .filter(o => o.getAdditionalProperties() !== undefined) - .map(o => defined(o.getAdditionalProperties()).typeRef), + .map(o => defined(o.getAdditionalProperties()).typeRef) ); setUnionInto(propertyTypes, additionalPropertyTypes); return this.typeBuilder.getMapType(typeAttributes, this._unifyTypes(Array.from(propertyTypes))); @@ -148,7 +148,7 @@ export class UnifyUnionBuilder extends UnionBuilder { assert(types.size > 0, "Property has no type"); return this._unifyTypes(Array.from(types).map(t => t.typeRef)); - }, + } ); if (lostTypeAttributes) { this.typeBuilder.setLostTypeAttributes(); @@ -159,7 +159,7 @@ export class UnifyUnionBuilder extends UnionBuilder ( +export function unionBuilderForUnification( typeBuilder: GraphRewriteBuilder, makeObjectTypes: boolean, makeClassesFixed: boolean, - conflateNumbers: boolean, + conflateNumbers: boolean ): UnionBuilder { return new UnifyUnionBuilder(typeBuilder, makeObjectTypes, makeClassesFixed, trefs => unifyTypes( @@ -195,20 +195,20 @@ export function unionBuilderForUnification ( emptyTypeAttributes, typeBuilder, unionBuilderForUnification(typeBuilder, makeObjectTypes, makeClassesFixed, conflateNumbers), - conflateNumbers, - ), + conflateNumbers + ) ); } // typeAttributes must not be reconstituted yet. // FIXME: The UnionBuilder might end up not being used. -export function unifyTypes ( +export function unifyTypes( types: ReadonlySet, typeAttributes: TypeAttributes, typeBuilder: GraphRewriteBuilder, unionBuilder: UnionBuilder, conflateNumbers: boolean, - maybeForwardingRef?: TypeRef, + maybeForwardingRef?: TypeRef ): TypeRef { typeAttributes = typeBuilder.reconstituteTypeAttributes(typeAttributes); if (types.size === 0) { diff --git a/packages/quicktype-core/src/UnionBuilder.ts b/packages/quicktype-core/src/UnionBuilder.ts index e3840144a..0573b18b7 100644 --- a/packages/quicktype-core/src/UnionBuilder.ts +++ b/packages/quicktype-core/src/UnionBuilder.ts @@ -1,15 +1,14 @@ import { mapMerge, mapUpdateInto, mapMap, setUnionInto } from "collection-utils"; -import { type TypeKind, type PrimitiveStringTypeKind, type Type, type PrimitiveTypeKind} from "./Type"; +import { type TypeKind, type PrimitiveStringTypeKind, type Type, type PrimitiveTypeKind } from "./Type"; import { UnionType, isPrimitiveTypeKind } from "./Type"; import { matchTypeExhaustive } from "./TypeUtils"; -import { - type TypeAttributes} from "./attributes/TypeAttributes"; +import { type TypeAttributes } from "./attributes/TypeAttributes"; import { combineTypeAttributes, emptyTypeAttributes, makeTypeAttributesInferred, - increaseTypeAttributesDistance, + increaseTypeAttributesDistance } from "./attributes/TypeAttributes"; import { defined, assert, panic, assertNever } from "./support/Support"; import { type TypeBuilder } from "./TypeBuilder"; @@ -37,26 +36,26 @@ export type TypeAttributeMap = Map; type TypeAttributeMapBuilder = Map; -function addAttributes ( +function addAttributes( accumulatorAttributes: TypeAttributes | undefined, - newAttributes: TypeAttributes, + newAttributes: TypeAttributes ): TypeAttributes { if (accumulatorAttributes === undefined) return newAttributes; return combineTypeAttributes("union", accumulatorAttributes, newAttributes); } -function setAttributes ( +function setAttributes( attributeMap: TypeAttributeMap, kind: T, - newAttributes: TypeAttributes, + newAttributes: TypeAttributes ): void { attributeMap.set(kind, addAttributes(attributeMap.get(kind), newAttributes)); } -function addAttributesToBuilder ( +function addAttributesToBuilder( builder: TypeAttributeMapBuilder, kind: T, - newAttributes: TypeAttributes, + newAttributes: TypeAttributes ): void { let arr = builder.get(kind); if (arr === undefined) { @@ -67,11 +66,11 @@ function addAttributesToBuilder ( arr.push(newAttributes); } -function buildTypeAttributeMap (builder: TypeAttributeMapBuilder): TypeAttributeMap { +function buildTypeAttributeMap(builder: TypeAttributeMapBuilder): TypeAttributeMap { return mapMap(builder, arr => combineTypeAttributes("union", arr)); } -function moveAttributes (map: TypeAttributeMap, fromKind: T, toKind: T): void { +function moveAttributes(map: TypeAttributeMap, fromKind: T, toKind: T): void { const fromAttributes = defined(map.get(fromKind)); map.delete(fromKind); setAttributes(map, toKind, fromAttributes); @@ -82,40 +81,40 @@ export class UnionAccumulator implements UnionTypeProvider = new Map(); - readonly arrayData: TArray[] = []; + public readonly arrayData: TArray[] = []; - readonly objectData: TObject[] = []; + public readonly objectData: TObject[] = []; private readonly _enumCases: Set = new Set(); private _lostTypeAttributes = false; - constructor (private readonly _conflateNumbers: boolean) {} + public constructor(private readonly _conflateNumbers: boolean) {} - private have (kind: TypeKind): boolean { + private have(kind: TypeKind): boolean { return ( this._nonStringTypeAttributes.has(kind) || this._stringTypeAttributes.has(kind as PrimitiveStringTypeKind) ); } - addNone (_attributes: TypeAttributes): void { + public addNone(_attributes: TypeAttributes): void { // FIXME: Add them to all members? Or add them to the union, which means we'd have // to change getMemberKinds() to also return the attributes for the union itself, // or add a new method that does that. this._lostTypeAttributes = true; } - addAny (attributes: TypeAttributes): void { + public addAny(attributes: TypeAttributes): void { addAttributesToBuilder(this._nonStringTypeAttributes, "any", attributes); this._lostTypeAttributes = true; } - addPrimitive (kind: PrimitiveTypeKind, attributes: TypeAttributes): void { + public addPrimitive(kind: PrimitiveTypeKind, attributes: TypeAttributes): void { assert(kind !== "any", "any must be added with addAny"); addAttributesToBuilder(this._nonStringTypeAttributes, kind, attributes); } - protected addFullStringType (attributes: TypeAttributes, stringTypes: StringTypes | undefined): void { + protected addFullStringType(attributes: TypeAttributes, stringTypes: StringTypes | undefined): void { let stringTypesAttributes: TypeAttributes | undefined = undefined; if (stringTypes === undefined) { stringTypes = stringTypesTypeAttributeKind.tryGetInAttributes(attributes); @@ -132,7 +131,7 @@ export class UnionAccumulator implements UnionTypeProvider implements UnionTypeProvider implements UnionTypeProvider, attributes: TypeAttributes): void { + public addEnum(cases: ReadonlySet, attributes: TypeAttributes): void { const maybeStringAttributes = this._stringTypeAttributes.get("string"); if (maybeStringAttributes !== undefined) { addAttributesToBuilder(this._stringTypeAttributes, "string", attributes); @@ -179,24 +178,24 @@ export class UnionAccumulator implements UnionTypeProvider { + public get enumCases(): ReadonlySet { return this._enumCases; } - getMemberKinds (): TypeAttributeMap { + public getMemberKinds(): TypeAttributeMap { assert(!(this.have("enum") && this.have("string")), "We can't have both strings and enums in the same union"); let merged = mapMerge( buildTypeAttributeMap(this._nonStringTypeAttributes), - buildTypeAttributeMap(this._stringTypeAttributes), + buildTypeAttributeMap(this._stringTypeAttributes) ); if (merged.size === 0) { @@ -221,20 +220,20 @@ export class UnionAccumulator implements UnionTypeProvider): [ReadonlyMap, TypeAttributes] { +function attributesForTypes(types: Iterable): [ReadonlyMap, TypeAttributes] { // These two maps are the reverse of each other. unionsForType is all the unions // that are ancestors of that type, when going from one of the given types, only // following unions. @@ -246,7 +245,7 @@ function attributesForTypes (types: Iterable): [ReadonlyMap = new Set(); - function traverse (t: Type, path: UnionOrFaux[], isEquivalentToRoot: boolean): void { + function traverse(t: Type, path: UnionOrFaux[], isEquivalentToRoot: boolean): void { if (t instanceof UnionType) { unions.add(t); if (isEquivalentToRoot) { @@ -261,9 +260,9 @@ function attributesForTypes (types: Iterable): [ReadonlyMap s === undefined ? new Set(path) : setUnionInto(s, path)); + mapUpdateInto(unionsForType, t, s => (s === undefined ? new Set(path) : setUnionInto(s, path))); for (const u of path) { - mapUpdateInto(typesForUnion, u, s => s === undefined ? new Set([t]) : s.add(t)); + mapUpdateInto(typesForUnion, u, s => (s === undefined ? new Set([t]) : s.add(t))); } } } @@ -278,7 +277,7 @@ function attributesForTypes (types: Iterable): [ReadonlyMap defined(typesForUnion.get(u)).size === 1); assert( singleAncestors.every(u => defined(typesForUnion.get(u)).has(t)), - "We messed up bookkeeping", + "We messed up bookkeeping" ); const inheritedAttributes = singleAncestors.map(u => u.getAttributes()); return combineTypeAttributes("union", [t.getAttributes()].concat(inheritedAttributes)); @@ -303,7 +302,7 @@ function attributesForTypes (types: Iterable): [ReadonlyMap { // There is a method analogous to this in the IntersectionAccumulator. It might // make sense to find a common interface. - private addType (t: Type, attributes: TypeAttributes): void { + private addType(t: Type, attributes: TypeAttributes): void { matchTypeExhaustive( t, _noneType => this.addNone(attributes), @@ -325,11 +324,11 @@ export class TypeRefUnionAccumulator extends UnionAccumulator return panic("The unions should have been eliminated in attributesForTypesInUnion"); }, transformedStringType => - this.addStringType(transformedStringType.kind as PrimitiveStringTypeKind, attributes), + this.addStringType(transformedStringType.kind as PrimitiveStringTypeKind, attributes) ); } - addTypes (types: Iterable): TypeAttributes { + public addTypes(types: Iterable): TypeAttributes { const [attributesMap, unionAttributes] = attributesForTypes(types); for (const [t, attributes] of attributesMap) { this.addType(t, attributes); @@ -340,24 +339,24 @@ export class TypeRefUnionAccumulator extends UnionAccumulator } export abstract class UnionBuilder { - constructor (protected readonly typeBuilder: TBuilder) {} + public constructor(protected readonly typeBuilder: TBuilder) {} - protected abstract makeObject ( + protected abstract makeObject( objects: TObjectData, typeAttributes: TypeAttributes, forwardingRef: TypeRef | undefined ): TypeRef; - protected abstract makeArray ( + protected abstract makeArray( arrays: TArrayData, typeAttributes: TypeAttributes, forwardingRef: TypeRef | undefined ): TypeRef; - private makeTypeOfKind ( + private makeTypeOfKind( typeProvider: UnionTypeProvider, kind: TypeKind, typeAttributes: TypeAttributes, - forwardingRef: TypeRef | undefined, + forwardingRef: TypeRef | undefined ): TypeRef { switch (kind) { case "string": @@ -381,11 +380,11 @@ export abstract class UnionBuilder, unique: boolean, typeAttributes: TypeAttributes, - forwardingRef?: TypeRef, + forwardingRef?: TypeRef ): TypeRef { const kinds = typeProvider.getMemberKinds(); @@ -402,7 +401,7 @@ export abstract class UnionBuilder; export type AccessorNames = Map; class AccessorNamesTypeAttributeKind extends TypeAttributeKind { - constructor () { + public constructor() { super("accessorNames"); } - makeInferred (_: AccessorNames): undefined { + public makeInferred(_: AccessorNames): undefined { return undefined; } } @@ -32,7 +32,7 @@ class AccessorNamesTypeAttributeKind extends TypeAttributeKind { export const accessorNamesTypeAttributeKind: TypeAttributeKind = new AccessorNamesTypeAttributeKind(); // Returns [name, isFixed]. -function getFromEntry (entry: AccessorEntry, language: string): [string, boolean] | undefined { +function getFromEntry(entry: AccessorEntry, language: string): [string, boolean] | undefined { if (typeof entry === "string") return [entry, false]; const maybeForLanguage = entry.get(language); @@ -44,28 +44,28 @@ function getFromEntry (entry: AccessorEntry, language: string): [string, boolean return undefined; } -export function lookupKey (accessors: AccessorNames, key: string, language: string): [string, boolean] | undefined { +export function lookupKey(accessors: AccessorNames, key: string, language: string): [string, boolean] | undefined { const entry = accessors.get(key); if (entry === undefined) return undefined; return getFromEntry(entry, language); } -export function objectPropertyNames (o: ObjectType, language: string): Map { +export function objectPropertyNames(o: ObjectType, language: string): Map { const accessors = accessorNamesTypeAttributeKind.tryGetInAttributes(o.getAttributes()); const map = o.getProperties(); if (accessors === undefined) return mapMap(map, _ => undefined); return mapMap(map, (_cp, n) => lookupKey(accessors, n, language)); } -export function enumCaseNames (e: EnumType, language: string): Map { +export function enumCaseNames(e: EnumType, language: string): Map { const accessors = accessorNamesTypeAttributeKind.tryGetInAttributes(e.getAttributes()); if (accessors === undefined) return mapMap(e.cases.entries(), _ => undefined); return mapMap(e.cases.entries(), c => lookupKey(accessors, c, language)); } -export function getAccessorName ( +export function getAccessorName( names: Map, - original: string, + original: string ): [string | undefined, boolean] { const maybeName = names.get(original); if (maybeName === undefined) return [undefined, false]; @@ -80,15 +80,15 @@ export function getAccessorName ( // up its union's identifier(s), and then look up the member's accessor entries for that // identifier. Of course we might find more than one, potentially conflicting. class UnionIdentifierTypeAttributeKind extends TypeAttributeKind> { - constructor () { + public constructor() { super("unionIdentifier"); } - combine (arr: Array>): ReadonlySet { + public combine(arr: Array>): ReadonlySet { return setUnionManyInto(new Set(), arr); } - makeInferred (_: ReadonlySet): ReadonlySet { + public makeInferred(_: ReadonlySet): ReadonlySet { return new Set(); } } @@ -98,18 +98,18 @@ export const unionIdentifierTypeAttributeKind: TypeAttributeKind> { - constructor () { + public constructor() { super("unionMemberNames"); } - combine (arr: Array>): Map { + public combine(arr: Array>): Map { const result = new Map(); for (const m of arr) { mapMergeInto(result, m); @@ -122,13 +122,13 @@ class UnionMemberNamesTypeAttributeKind extends TypeAttributeKind> = new UnionMemberNamesTypeAttributeKind(); -export function makeUnionMemberNamesAttribute (unionAttributes: TypeAttributes, entry: AccessorEntry): TypeAttributes { +export function makeUnionMemberNamesAttribute(unionAttributes: TypeAttributes, entry: AccessorEntry): TypeAttributes { const identifiers = defined(unionIdentifierTypeAttributeKind.tryGetInAttributes(unionAttributes)); const map = mapFromIterable(identifiers, _ => entry); return unionMemberNamesTypeAttributeKind.makeAttributes(map); } -export function unionMemberName (u: UnionType, member: Type, language: string): [string | undefined, boolean] { +export function unionMemberName(u: UnionType, member: Type, language: string): [string | undefined, boolean] { const identifiers = unionIdentifierTypeAttributeKind.tryGetInAttributes(u.getAttributes()); if (identifiers === undefined) return [undefined, false]; @@ -168,7 +168,7 @@ export function unionMemberName (u: UnionType, member: Type, language: string): return [first, isFixed]; } -function isAccessorEntry (x: any): x is string | { [language: string]: string, } { +function isAccessorEntry(x: any): x is string | { [language: string]: string } { if (typeof x === "string") { return true; } @@ -176,22 +176,22 @@ function isAccessorEntry (x: any): x is string | { [language: string]: string, } return isStringMap(x, (v: any): v is string => typeof v === "string"); } -function makeAccessorEntry (ae: string | { [language: string]: string, }): AccessorEntry { +function makeAccessorEntry(ae: string | { [language: string]: string }): AccessorEntry { if (typeof ae === "string") return ae; return mapFromObject(ae); } -export function makeAccessorNames (x: any): AccessorNames { +export function makeAccessorNames(x: any): AccessorNames { // FIXME: Do proper error reporting const stringMap = checkStringMap(x, isAccessorEntry); return mapMap(mapFromObject(stringMap), makeAccessorEntry); } -export function accessorNamesAttributeProducer ( +export function accessorNamesAttributeProducer( schema: JSONSchema, canonicalRef: Ref, _types: Set, - cases: JSONSchema[] | undefined, + cases: JSONSchema[] | undefined ): JSONSchemaAttributes | undefined { if (typeof schema !== "object") return undefined; const maybeAccessors = schema["qt-accessors"]; @@ -205,10 +205,10 @@ export function accessorNamesAttributeProducer ( const accessors = checkArray(maybeAccessors, isAccessorEntry); messageAssert(cases.length === accessors.length, "SchemaWrongAccessorEntryArrayLength", { operation: "oneOf", - ref: canonicalRef.push("oneOf"), + ref: canonicalRef.push("oneOf") }); const caseAttributes = accessors.map(accessor => - makeUnionMemberNamesAttribute(identifierAttribute, makeAccessorEntry(accessor)), + makeUnionMemberNamesAttribute(identifierAttribute, makeAccessorEntry(accessor)) ); return { forUnion: identifierAttribute, forCases: caseAttributes }; } diff --git a/packages/quicktype-core/src/attributes/Constraints.ts b/packages/quicktype-core/src/attributes/Constraints.ts index d63442f26..1bb66e2cf 100644 --- a/packages/quicktype-core/src/attributes/Constraints.ts +++ b/packages/quicktype-core/src/attributes/Constraints.ts @@ -10,7 +10,7 @@ import { type JSONSchema } from "../input/JSONSchemaStore"; // `areEqual`, `hashCodeOf`. export type MinMaxConstraint = [number | undefined, number | undefined]; -function checkMinMaxConstraint (minmax: MinMaxConstraint): MinMaxConstraint | undefined { +function checkMinMaxConstraint(minmax: MinMaxConstraint): MinMaxConstraint | undefined { const [min, max] = minmax; if (typeof min === "number" && typeof max === "number" && min > max) { return messageError("MiscInvalidMinMaxConstraint", { min, max }); @@ -24,20 +24,20 @@ function checkMinMaxConstraint (minmax: MinMaxConstraint): MinMaxConstraint | un } export class MinMaxConstraintTypeAttributeKind extends TypeAttributeKind { - constructor ( + public constructor( name: string, private readonly _typeKinds: Set, private _minSchemaProperty: string, - private _maxSchemaProperty: string, + private _maxSchemaProperty: string ) { super(name); } - get inIdentity (): boolean { + public get inIdentity(): boolean { return true; } - combine (arr: MinMaxConstraint[]): MinMaxConstraint | undefined { + public combine(arr: MinMaxConstraint[]): MinMaxConstraint | undefined { assert(arr.length > 0); let [min, max] = arr[0]; @@ -59,7 +59,7 @@ export class MinMaxConstraintTypeAttributeKind extends TypeAttributeKind 0); let [min, max] = arr[0]; @@ -81,11 +81,11 @@ export class MinMaxConstraintTypeAttributeKind extends TypeAttributeKind = new "minMax", new Set(["integer", "double"]), "minimum", - "maximum", + "maximum" ); export const minMaxLengthTypeAttributeKind: TypeAttributeKind = new MinMaxConstraintTypeAttributeKind( "minMaxLength", new Set(["string"]), "minLength", - "maxLength", + "maxLength" ); -function producer (schema: JSONSchema, minProperty: string, maxProperty: string): MinMaxConstraint | undefined { +function producer(schema: JSONSchema, minProperty: string, maxProperty: string): MinMaxConstraint | undefined { if (!(typeof schema === "object")) return undefined; let min: number | undefined = undefined; @@ -135,10 +135,10 @@ function producer (schema: JSONSchema, minProperty: string, maxProperty: string) return [min, max]; } -export function minMaxAttributeProducer ( +export function minMaxAttributeProducer( schema: JSONSchema, _ref: Ref, - types: Set, + types: Set ): JSONSchemaAttributes | undefined { if (!types.has("number") && !types.has("integer")) return undefined; @@ -147,10 +147,10 @@ export function minMaxAttributeProducer ( return { forNumber: minMaxTypeAttributeKind.makeAttributes(maybeMinMax) }; } -export function minMaxLengthAttributeProducer ( +export function minMaxLengthAttributeProducer( schema: JSONSchema, _ref: Ref, - types: Set, + types: Set ): JSONSchemaAttributes | undefined { if (!types.has("string")) return undefined; @@ -159,38 +159,38 @@ export function minMaxLengthAttributeProducer ( return { forString: minMaxLengthTypeAttributeKind.makeAttributes(maybeMinMaxLength) }; } -export function minMaxValueForType (t: Type): MinMaxConstraint | undefined { +export function minMaxValueForType(t: Type): MinMaxConstraint | undefined { return minMaxTypeAttributeKind.tryGetInAttributes(t.getAttributes()); } -export function minMaxLengthForType (t: Type): MinMaxConstraint | undefined { +export function minMaxLengthForType(t: Type): MinMaxConstraint | undefined { return minMaxLengthTypeAttributeKind.tryGetInAttributes(t.getAttributes()); } export class PatternTypeAttributeKind extends TypeAttributeKind { - constructor () { + public constructor() { super("pattern"); } - get inIdentity (): boolean { + public get inIdentity(): boolean { return true; } - combine (arr: string[]): string { + public combine(arr: string[]): string { assert(arr.length > 0); return arr.map(p => `(${p})`).join("|"); } - intersect (_arr: string[]): string | undefined { + public intersect(_arr: string[]): string | undefined { /** FIXME!!! what is the intersection of regexps? */ return undefined; } - makeInferred (_: string): undefined { + public makeInferred(_: string): undefined { return undefined; } - addToSchema (schema: { [name: string]: unknown, }, t: Type, attr: string): void { + public addToSchema(schema: { [name: string]: unknown }, t: Type, attr: string): void { if (t.kind !== "string") return; schema.pattern = attr; } @@ -198,10 +198,10 @@ export class PatternTypeAttributeKind extends TypeAttributeKind { export const patternTypeAttributeKind: TypeAttributeKind = new PatternTypeAttributeKind(); -export function patternAttributeProducer ( +export function patternAttributeProducer( schema: JSONSchema, _ref: Ref, - types: Set, + types: Set ): JSONSchemaAttributes | undefined { if (!(typeof schema === "object")) return undefined; if (!types.has("string")) return undefined; @@ -211,6 +211,6 @@ export function patternAttributeProducer ( return { forString: patternTypeAttributeKind.makeAttributes(patt) }; } -export function patternForType (t: Type): string | undefined { +export function patternForType(t: Type): string | undefined { return patternTypeAttributeKind.tryGetInAttributes(t.getAttributes()); } diff --git a/packages/quicktype-core/src/attributes/Description.ts b/packages/quicktype-core/src/attributes/Description.ts index 34bc6151c..9bf1d6588 100644 --- a/packages/quicktype-core/src/attributes/Description.ts +++ b/packages/quicktype-core/src/attributes/Description.ts @@ -5,7 +5,7 @@ import { iterableFirst, setUnionManyInto, mapMergeWithInto, - setSubtract, + setSubtract } from "collection-utils"; // There's a cyclic import here. Ignoring now because it requires a large refactor. @@ -17,32 +17,32 @@ import { PathElementKind } from "../input/JSONSchemaInput"; import { type JSONSchema } from "../input/JSONSchemaStore"; import { type Type } from "../Type"; -export function addDescriptionToSchema ( - schema: { [name: string]: unknown, }, - description: Iterable | undefined, +export function addDescriptionToSchema( + schema: { [name: string]: unknown }, + description: Iterable | undefined ): void { if (description === undefined) return; schema.description = Array.from(description).join("\n"); } class DescriptionTypeAttributeKind extends TypeAttributeKind> { - constructor () { + public constructor() { super("description"); } - combine (attrs: Array>): ReadonlySet { + public combine(attrs: Array>): ReadonlySet { return setUnionManyInto(new Set(), attrs); } - makeInferred (_: ReadonlySet): undefined { + public makeInferred(_: ReadonlySet): undefined { return undefined; } - addToSchema (schema: { [name: string]: unknown, }, _t: Type, attrs: ReadonlySet): void { + public addToSchema(schema: { [name: string]: unknown }, _t: Type, attrs: ReadonlySet): void { addDescriptionToSchema(schema, attrs); } - stringify (descriptions: ReadonlySet): string | undefined { + public stringify(descriptions: ReadonlySet): string | undefined { let result = iterableFirst(descriptions); if (result === undefined) return undefined; if (result.length > 5 + 3) { @@ -60,11 +60,11 @@ class DescriptionTypeAttributeKind extends TypeAttributeKind export const descriptionTypeAttributeKind: TypeAttributeKind> = new DescriptionTypeAttributeKind(); class PropertyDescriptionsTypeAttributeKind extends TypeAttributeKind>> { - constructor () { + public constructor() { super("propertyDescriptions"); } - combine (attrs: Array>>): Map> { + public combine(attrs: Array>>): Map> { // FIXME: Implement this with mutable sets const result = new Map>(); for (const attr of attrs) { @@ -74,11 +74,11 @@ class PropertyDescriptionsTypeAttributeKind extends TypeAttributeKind>): undefined { + public makeInferred(_: Map>): undefined { return undefined; } - stringify (propertyDescriptions: Map>): string | undefined { + public stringify(propertyDescriptions: Map>): string | undefined { if (propertyDescriptions.size === 0) return undefined; return `prop descs: ${propertyDescriptions.size}`; } @@ -87,14 +87,14 @@ class PropertyDescriptionsTypeAttributeKind extends TypeAttributeKind>> = new PropertyDescriptionsTypeAttributeKind(); -function isPropertiesKey (el: PathElement): boolean { +function isPropertiesKey(el: PathElement): boolean { return el.kind === PathElementKind.KeyOrIndex && el.key === "properties"; } -export function descriptionAttributeProducer ( +export function descriptionAttributeProducer( schema: JSONSchema, ref: Ref, - types: Set, + types: Set ): JSONSchemaAttributes | undefined { if (!(typeof schema === "object")) return undefined; diff --git a/packages/quicktype-core/src/attributes/EnumValues.ts b/packages/quicktype-core/src/attributes/EnumValues.ts index ccb3a6a24..38ac38542 100644 --- a/packages/quicktype-core/src/attributes/EnumValues.ts +++ b/packages/quicktype-core/src/attributes/EnumValues.ts @@ -1,6 +1,6 @@ import { mapMap } from "collection-utils"; -import { type AccessorNames} from "./AccessorNames"; +import { type AccessorNames } from "./AccessorNames"; import { lookupKey, makeAccessorNames } from "./AccessorNames"; import { type EnumType } from "../Type"; import { TypeAttributeKind } from "./TypeAttributes"; @@ -8,27 +8,27 @@ import { type JSONSchema } from "../input/JSONSchemaStore"; import { type Ref, type JSONSchemaType, type JSONSchemaAttributes } from "../input/JSONSchemaInput"; class EnumValuesTypeAttributeKind extends TypeAttributeKind { - constructor () { + public constructor() { super("enumValues"); } - makeInferred (_: AccessorNames) { + public makeInferred(_: AccessorNames) { return undefined; } } export const enumValuesTypeAttributeKind: TypeAttributeKind = new EnumValuesTypeAttributeKind(); -export function enumCaseValues (e: EnumType, language: string): Map { +export function enumCaseValues(e: EnumType, language: string): Map { const enumValues = enumValuesTypeAttributeKind.tryGetInAttributes(e.getAttributes()); if (enumValues === undefined) return mapMap(e.cases.entries(), _ => undefined); return mapMap(e.cases.entries(), c => lookupKey(enumValues, c, language)); } -export function enumValuesAttributeProducer ( +export function enumValuesAttributeProducer( schema: JSONSchema, _canonicalRef: Ref | undefined, - _types: Set, + _types: Set ): JSONSchemaAttributes | undefined { if (typeof schema !== "object") return undefined; diff --git a/packages/quicktype-core/src/attributes/StringTypes.ts b/packages/quicktype-core/src/attributes/StringTypes.ts index 555301d80..4c0083e82 100644 --- a/packages/quicktype-core/src/attributes/StringTypes.ts +++ b/packages/quicktype-core/src/attributes/StringTypes.ts @@ -7,27 +7,27 @@ import { mapMergeWithInto, definedMap, addHashCode, - setUnionInto, + setUnionInto } from "collection-utils"; import { TypeAttributeKind } from "./TypeAttributes"; import { defined, assert } from "../support/Support"; -import { type StringTypeMapping} from "../TypeBuilder"; +import { type StringTypeMapping } from "../TypeBuilder"; import { stringTypeMappingGet } from "../TypeBuilder"; import { type TransformedStringTypeKind } from "../Type"; import { type DateTimeRecognizer } from "../DateTime"; export class StringTypes { - static readonly unrestricted: StringTypes = new StringTypes(undefined, new Set()); + public static readonly unrestricted: StringTypes = new StringTypes(undefined, new Set()); - static fromCase (s: string, count: number): StringTypes { - const caseMap: { [name: string]: number, } = {}; + public static fromCase(s: string, count: number): StringTypes { + const caseMap: { [name: string]: number } = {}; caseMap[s] = count; return new StringTypes(new Map([[s, count] as [string, number]]), new Set()); } - static fromCases (cases: string[]): StringTypes { - const caseMap: { [name: string]: number, } = {}; + public static fromCases(cases: string[]): StringTypes { + const caseMap: { [name: string]: number } = {}; for (const s of cases) { caseMap[s] = 1; } @@ -36,20 +36,20 @@ export class StringTypes { } // undefined means no restrictions - constructor ( - readonly cases: ReadonlyMap | undefined, - readonly transformations: ReadonlySet, + public constructor( + public readonly cases: ReadonlyMap | undefined, + public readonly transformations: ReadonlySet ) { if (cases === undefined) { assert(transformations.size === 0, "We can't have an unrestricted string that also allows transformations"); } } - get isRestricted (): boolean { + public get isRestricted(): boolean { return this.cases !== undefined; } - union (othersArray: StringTypes[], startIndex: number): StringTypes { + public union(othersArray: StringTypes[], startIndex: number): StringTypes { if (this.cases === undefined) return this; const cases = new Map(this.cases); @@ -67,7 +67,7 @@ export class StringTypes { return new StringTypes(cases, transformations); } - intersect (othersArray: StringTypes[], startIndex: number): StringTypes { + public intersect(othersArray: StringTypes[], startIndex: number): StringTypes { let cases = this.cases; let transformations = this.transformations; @@ -95,7 +95,7 @@ export class StringTypes { return new StringTypes(cases, transformations); } - applyStringTypeMapping (mapping: StringTypeMapping): StringTypes { + public applyStringTypeMapping(mapping: StringTypeMapping): StringTypes { if (!this.isRestricted) return this; const kinds = new Set(); @@ -108,18 +108,18 @@ export class StringTypes { return new StringTypes(this.cases, new Set(kinds)); } - equals (other: any): boolean { + public equals(other: any): boolean { if (!(other instanceof StringTypes)) return false; return areEqual(this.cases, other.cases) && areEqual(this.transformations, other.transformations); } - hashCode (): number { + public hashCode(): number { let h = hashCodeOf(this.cases); h = addHashCode(h, hashCodeOf(this.transformations)); return h; } - toString (): string { + public toString(): string { const parts: string[] = []; const enumCases = this.cases; @@ -139,33 +139,33 @@ export class StringTypes { } class StringTypesTypeAttributeKind extends TypeAttributeKind { - constructor () { + public constructor() { super("stringTypes"); } - get inIdentity (): boolean { + public get inIdentity(): boolean { return true; } - requiresUniqueIdentity (st: StringTypes): boolean { + public requiresUniqueIdentity(st: StringTypes): boolean { return st.cases !== undefined && st.cases.size > 0; } - combine (arr: StringTypes[]): StringTypes { + public combine(arr: StringTypes[]): StringTypes { assert(arr.length > 0); return arr[0].union(arr, 1); } - intersect (arr: StringTypes[]): StringTypes { + public intersect(arr: StringTypes[]): StringTypes { assert(arr.length > 0); return arr[0].intersect(arr, 1); } - makeInferred (_: StringTypes): undefined { + public makeInferred(_: StringTypes): undefined { return undefined; } - stringify (st: StringTypes): string { + public stringify(st: StringTypes): string { return st.toString(); } } @@ -178,7 +178,7 @@ const INTEGER_STRING = /^(0|-?[1-9]\d*)$/; const MIN_INTEGER_STRING = 1 << 31; const MAX_INTEGER_STRING = -(MIN_INTEGER_STRING + 1); -function isIntegerString (s: string): boolean { +function isIntegerString(s: string): boolean { if (INTEGER_STRING.exec(s) === null) { return false; } @@ -189,7 +189,7 @@ function isIntegerString (s: string): boolean { const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/; -function isUUID (s: string): boolean { +function isUUID(s: string): boolean { return UUID.exec(s) !== null; } @@ -198,7 +198,7 @@ function isUUID (s: string): boolean { // with those characters which ajv refuses to accept as `uri`. const URI = /^(https?|ftp):\/\/[^{}]+$/; -function isURI (s: string): boolean { +function isURI(s: string): boolean { return URI.exec(s) !== null; } @@ -209,9 +209,9 @@ function isURI (s: string): boolean { * * @param s The string for which to determine the transformed string type kind. */ -export function inferTransformedStringTypeKindForString ( +export function inferTransformedStringTypeKindForString( s: string, - recognizer: DateTimeRecognizer, + recognizer: DateTimeRecognizer ): TransformedStringTypeKind | undefined { if (s.length === 0 || !"0123456789-abcdefth".includes(s[0])) return undefined; diff --git a/packages/quicktype-core/src/attributes/TypeAttributes.ts b/packages/quicktype-core/src/attributes/TypeAttributes.ts index 2077e0ca1..bf5a35d5b 100644 --- a/packages/quicktype-core/src/attributes/TypeAttributes.ts +++ b/packages/quicktype-core/src/attributes/TypeAttributes.ts @@ -5,67 +5,67 @@ import { type Type, type TypeKind } from "../Type"; import { type BaseGraphRewriteBuilder } from "../GraphRewriting"; export class TypeAttributeKind { - constructor (readonly name: string) {} + public constructor(public readonly name: string) {} - appliesToTypeKind (kind: TypeKind): boolean { + public appliesToTypeKind(kind: TypeKind): boolean { return kind !== "any"; } - combine (_attrs: T[]): T | undefined { + public combine(_attrs: T[]): T | undefined { return panic(`Cannot combine type attribute ${this.name}`); } - intersect (attrs: T[]): T | undefined { + public intersect(attrs: T[]): T | undefined { return this.combine(attrs); } - makeInferred (_: T): T | undefined { + public makeInferred(_: T): T | undefined { return panic(`Cannot make type attribute ${this.name} inferred`); } - increaseDistance (attrs: T): T | undefined { + public increaseDistance(attrs: T): T | undefined { return attrs; } - addToSchema (_schema: { [name: string]: unknown, }, _t: Type, _attrs: T): void { + public addToSchema(_schema: { [name: string]: unknown }, _t: Type, _attrs: T): void { return; } - children (_: T): ReadonlySet { + public children(_: T): ReadonlySet { return new Set(); } - stringify (_: T): string | undefined { + public stringify(_: T): string | undefined { return undefined; } - get inIdentity (): boolean { + public get inIdentity(): boolean { return false; } - requiresUniqueIdentity (_: T): boolean { + public requiresUniqueIdentity(_: T): boolean { return false; } - reconstitute(_builder: TBuilder, a: T): T { + public reconstitute(_builder: TBuilder, a: T): T { return a; } - makeAttributes (value: T): TypeAttributes { + public makeAttributes(value: T): TypeAttributes { const kvps: Array<[this, T]> = [[this, value]]; return new Map(kvps); } - tryGetInAttributes (a: TypeAttributes): T | undefined { + public tryGetInAttributes(a: TypeAttributes): T | undefined { return a.get(this); } - private setInAttributes (a: TypeAttributes, value: T): TypeAttributes { + private setInAttributes(a: TypeAttributes, value: T): TypeAttributes { // FIXME: This is potentially super slow return new Map(a).set(this, value); } - modifyInAttributes (a: TypeAttributes, modify: (value: T | undefined) => T | undefined): TypeAttributes { + public modifyInAttributes(a: TypeAttributes, modify: (value: T | undefined) => T | undefined): TypeAttributes { const modified = modify(this.tryGetInAttributes(a)); if (modified === undefined) { // FIXME: This is potentially super slow @@ -77,16 +77,16 @@ export class TypeAttributeKind { return this.setInAttributes(a, modified); } - setDefaultInAttributes (a: TypeAttributes, makeDefault: () => T): TypeAttributes { + public setDefaultInAttributes(a: TypeAttributes, makeDefault: () => T): TypeAttributes { if (this.tryGetInAttributes(a) !== undefined) return a; return this.modifyInAttributes(a, makeDefault); } - removeInAttributes (a: TypeAttributes): TypeAttributes { + public removeInAttributes(a: TypeAttributes): TypeAttributes { return mapFilter(a, (_, k) => k !== this); } - equals (other: any): boolean { + public equals(other: any): boolean { if (!(other instanceof TypeAttributeKind)) { return false; } @@ -94,7 +94,7 @@ export class TypeAttributeKind { return this.name === other.name; } - hashCode (): number { + public hashCode(): number { return hashString(this.name); } } @@ -105,12 +105,12 @@ export const emptyTypeAttributes: TypeAttributes = new Map(); export type CombinationKind = "union" | "intersect"; -export function combineTypeAttributes (kind: CombinationKind, attributeArray: TypeAttributes[]): TypeAttributes; -export function combineTypeAttributes (kind: CombinationKind, a: TypeAttributes, b: TypeAttributes): TypeAttributes; -export function combineTypeAttributes ( +export function combineTypeAttributes(kind: CombinationKind, attributeArray: TypeAttributes[]): TypeAttributes; +export function combineTypeAttributes(kind: CombinationKind, a: TypeAttributes, b: TypeAttributes): TypeAttributes; +export function combineTypeAttributes( combinationKind: CombinationKind, firstOrArray: TypeAttributes[] | TypeAttributes, - second?: TypeAttributes, + second?: TypeAttributes ): TypeAttributes { const union = combinationKind === "union"; let attributeArray: TypeAttributes[]; @@ -126,7 +126,7 @@ export function combineTypeAttributes ( const attributesByKind = mapTranspose(attributeArray); - function combine (attrs: any[], kind: TypeAttributeKind): any { + function combine(attrs: any[], kind: TypeAttributeKind): any { assert(attrs.length > 0, "Cannot combine zero type attributes"); if (attrs.length === 1) return attrs[0]; if (union) { @@ -139,10 +139,10 @@ export function combineTypeAttributes ( return mapFilterMap(attributesByKind, combine); } -export function makeTypeAttributesInferred (attr: TypeAttributes): TypeAttributes { +export function makeTypeAttributesInferred(attr: TypeAttributes): TypeAttributes { return mapFilterMap(attr, (value, kind) => kind.makeInferred(value)); } -export function increaseTypeAttributesDistance (attr: TypeAttributes): TypeAttributes { +export function increaseTypeAttributesDistance(attr: TypeAttributes): TypeAttributes { return mapFilterMap(attr, (value, kind) => kind.increaseDistance(value)); } diff --git a/packages/quicktype-core/src/attributes/TypeNames.ts b/packages/quicktype-core/src/attributes/TypeNames.ts index 119ebec14..a1be97d07 100644 --- a/packages/quicktype-core/src/attributes/TypeNames.ts +++ b/packages/quicktype-core/src/attributes/TypeNames.ts @@ -10,14 +10,14 @@ import { Chance } from "../support/Chance"; let chance: Chance; let usedRandomNames: Set; -export function initTypeNames (): void { +export function initTypeNames(): void { chance = new Chance(31415); usedRandomNames = new Set(); } initTypeNames(); -function makeRandomName (): string { +function makeRandomName(): string { for (;;) { const name = `${chance.city()} ${chance.animal()}`; if (usedRandomNames.has(name)) continue; @@ -32,7 +32,7 @@ export type NameOrNames = string | TypeNames; // produce a name that includes the overlap twice. For example, for // the names "aaa" and "aaaa" we have the common prefix "aaa" and the // common suffix "aaa", so we will produce the combined name "aaaaaa". -function combineNames (names: ReadonlySet): string { +function combineNames(names: ReadonlySet): string { let originalFirst = iterableFirst(names); if (originalFirst === undefined) { return panic("Named type has no names"); @@ -45,7 +45,7 @@ function combineNames (names: ReadonlySet): string { const namesSet = setMap(names, s => splitIntoWords(s) .map(w => w.word.toLowerCase()) - .join("_"), + .join("_") ); const first = defined(iterableFirst(namesSet)); if (namesSet.size === 1) { @@ -85,10 +85,10 @@ function combineNames (names: ReadonlySet): string { export const tooManyNamesThreshold = 1000; export abstract class TypeNames { - static makeWithDistance ( + public static makeWithDistance( names: ReadonlySet, alternativeNames: ReadonlySet | undefined, - distance: number, + distance: number ): TypeNames { if (names.size >= tooManyNamesThreshold) { return new TooManyTypeNames(distance); @@ -101,41 +101,41 @@ export abstract class TypeNames { return new RegularTypeNames(names, alternativeNames, distance); } - static make ( + public static make( names: ReadonlySet, alternativeNames: ReadonlySet | undefined, - areInferred: boolean, + areInferred: boolean ): TypeNames { return TypeNames.makeWithDistance(names, alternativeNames, areInferred ? 1 : 0); } - constructor (readonly distance: number) {} + public constructor(public readonly distance: number) {} - get areInferred (): boolean { + public get areInferred(): boolean { return this.distance > 0; } - abstract get names (): ReadonlySet; - abstract get combinedName (): string; - abstract get proposedNames (): ReadonlySet; + public abstract get names(): ReadonlySet; + public abstract get combinedName(): string; + public abstract get proposedNames(): ReadonlySet; - abstract add (namesArray: TypeNames[], startIndex?: number): TypeNames; - abstract clearInferred (): TypeNames; - abstract makeInferred (): TypeNames; - abstract singularize (): TypeNames; - abstract toString (): string; + public abstract add(namesArray: TypeNames[], startIndex?: number): TypeNames; + public abstract clearInferred(): TypeNames; + public abstract makeInferred(): TypeNames; + public abstract singularize(): TypeNames; + public abstract toString(): string; } export class RegularTypeNames extends TypeNames { - constructor ( - readonly names: ReadonlySet, + public constructor( + public readonly names: ReadonlySet, private readonly _alternativeNames: ReadonlySet | undefined, - distance: number, + distance: number ) { super(distance); } - add (namesArray: TypeNames[], startIndex = 0): TypeNames { + public add(namesArray: TypeNames[], startIndex = 0): TypeNames { let newNames = new Set(this.names); let newDistance = this.distance; let newAlternativeNames = definedMap(this._alternativeNames, s => new Set(s)); @@ -174,16 +174,16 @@ export class RegularTypeNames extends TypeNames { return TypeNames.makeWithDistance(newNames, newAlternativeNames, newDistance); } - clearInferred (): TypeNames { + public clearInferred(): TypeNames { const newNames = this.areInferred ? new Set() : this.names; return TypeNames.makeWithDistance(newNames, new Set(), this.distance); } - get combinedName (): string { + public get combinedName(): string { return combineNames(this.names); } - get proposedNames (): ReadonlySet { + public get proposedNames(): ReadonlySet { const set = new Set([this.combinedName]); if (this._alternativeNames === undefined) { return set; @@ -193,19 +193,19 @@ export class RegularTypeNames extends TypeNames { return set; } - makeInferred (): TypeNames { + public makeInferred(): TypeNames { return TypeNames.makeWithDistance(this.names, this._alternativeNames, this.distance + 1); } - singularize (): TypeNames { + public singularize(): TypeNames { return TypeNames.makeWithDistance( setMap(this.names, pluralize.singular), definedMap(this._alternativeNames, an => setMap(an, pluralize.singular)), - this.distance + 1, + this.distance + 1 ); } - toString (): string { + public toString(): string { const inferred = this.areInferred ? `distance ${this.distance}` : "given"; const names = `${inferred} ${Array.from(this.names).join(",")}`; if (this._alternativeNames === undefined) { @@ -217,9 +217,9 @@ export class RegularTypeNames extends TypeNames { } export class TooManyTypeNames extends TypeNames { - readonly names: ReadonlySet; + public readonly names: ReadonlySet; - constructor (distance: number, name?: string) { + public constructor(distance: number, name?: string) { super(distance); if (name === undefined) { @@ -229,15 +229,15 @@ export class TooManyTypeNames extends TypeNames { this.names = new Set([name]); } - get combinedName (): string { + public get combinedName(): string { return defined(iterableFirst(this.names)); } - get proposedNames (): ReadonlySet { + public get proposedNames(): ReadonlySet { return this.names; } - add (namesArray: TypeNames[], startIndex = 0): TypeNames { + public add(namesArray: TypeNames[], startIndex = 0): TypeNames { if (!this.areInferred) return this; for (let i = startIndex; i < namesArray.length; i++) { @@ -250,7 +250,7 @@ export class TooManyTypeNames extends TypeNames { return this; } - clearInferred (): TypeNames { + public clearInferred(): TypeNames { if (!this.areInferred) { return this; } @@ -258,60 +258,60 @@ export class TooManyTypeNames extends TypeNames { return TypeNames.makeWithDistance(new Set(), new Set(), this.distance); } - makeInferred (): TypeNames { + public makeInferred(): TypeNames { return new TooManyTypeNames(this.distance + 1, iterableFirst(this.names)); } - singularize (): TypeNames { + public singularize(): TypeNames { return this; } - toString (): string { + public toString(): string { return `too many ${this.combinedName}`; } } class TypeNamesTypeAttributeKind extends TypeAttributeKind { - constructor () { + public constructor() { super("names"); } - combine (namesArray: TypeNames[]): TypeNames { + public combine(namesArray: TypeNames[]): TypeNames { assert(namesArray.length > 0, "Can't combine zero type names"); return namesArray[0].add(namesArray, 1); } - makeInferred (tn: TypeNames): TypeNames { + public makeInferred(tn: TypeNames): TypeNames { return tn.makeInferred(); } - increaseDistance (tn: TypeNames): TypeNames { + public increaseDistance(tn: TypeNames): TypeNames { return tn.makeInferred(); } - stringify (tn: TypeNames): string { + public stringify(tn: TypeNames): string { return tn.toString(); } } export const namesTypeAttributeKind: TypeAttributeKind = new TypeNamesTypeAttributeKind(); -export function modifyTypeNames ( +export function modifyTypeNames( attributes: TypeAttributes, - modifier: (tn: TypeNames | undefined) => TypeNames | undefined, + modifier: (tn: TypeNames | undefined) => TypeNames | undefined ): TypeAttributes { return namesTypeAttributeKind.modifyInAttributes(attributes, modifier); } -export function singularizeTypeNames (attributes: TypeAttributes): TypeAttributes { +export function singularizeTypeNames(attributes: TypeAttributes): TypeAttributes { return modifyTypeNames(attributes, maybeNames => { if (maybeNames === undefined) return undefined; return maybeNames.singularize(); }); } -export function makeNamesTypeAttributes (nameOrNames: NameOrNames, areNamesInferred?: boolean): TypeAttributes { +export function makeNamesTypeAttributes(nameOrNames: NameOrNames, areNamesInferred?: boolean): TypeAttributes { let typeNames: TypeNames; if (typeof nameOrNames === "string") { typeNames = TypeNames.make(new Set([nameOrNames]), new Set(), defined(areNamesInferred)); diff --git a/packages/quicktype-core/src/attributes/URIAttributes.ts b/packages/quicktype-core/src/attributes/URIAttributes.ts index 3213a389c..78e2fcc68 100644 --- a/packages/quicktype-core/src/attributes/URIAttributes.ts +++ b/packages/quicktype-core/src/attributes/URIAttributes.ts @@ -1,6 +1,6 @@ import URI from "urijs"; -import { type TypeAttributes} from "./TypeAttributes"; +import { type TypeAttributes } from "./TypeAttributes"; import { TypeAttributeKind, emptyTypeAttributes } from "./TypeAttributes"; import { setUnionManyInto } from "collection-utils"; import { type JSONSchemaType, type JSONSchemaAttributes, type Ref } from "../input/JSONSchemaInput"; @@ -15,25 +15,25 @@ const extensionsSchemaProperty = "qt-uri-extensions"; type URIAttributes = [ReadonlySet, ReadonlySet]; class URITypeAttributeKind extends TypeAttributeKind { - constructor () { + public constructor() { super("uriAttributes"); } - get inIdentity (): boolean { + public get inIdentity(): boolean { return true; } - combine (attrs: URIAttributes[]): URIAttributes { + public combine(attrs: URIAttributes[]): URIAttributes { const protocolSets = attrs.map(a => a[0]); const extensionSets = attrs.map(a => a[1]); return [setUnionManyInto(new Set(), protocolSets), setUnionManyInto(new Set(), extensionSets)]; } - makeInferred (_: URIAttributes): undefined { + public makeInferred(_: URIAttributes): undefined { return undefined; } - addToSchema (schema: { [name: string]: unknown, }, t: Type, attrs: URIAttributes): void { + public addToSchema(schema: { [name: string]: unknown }, t: Type, attrs: URIAttributes): void { if (t.kind !== "string" && t.kind !== "uri") return; const [protocols, extensions] = attrs; @@ -51,13 +51,13 @@ export const uriTypeAttributeKind: TypeAttributeKind = new URITyp const extensionRegex = /^.+(\.[^./\\]+)$/; -function pathExtension (path: string): string | undefined { +function pathExtension(path: string): string | undefined { const matches = extensionRegex.exec(path); if (matches === null) return undefined; return matches[1]; } -export function uriInferenceAttributesProducer (s: string): TypeAttributes { +export function uriInferenceAttributesProducer(s: string): TypeAttributes { try { const uri = URI(s); const extension = pathExtension(uri.path()); @@ -68,10 +68,10 @@ export function uriInferenceAttributesProducer (s: string): TypeAttributes { } } -export function uriSchemaAttributesProducer ( +export function uriSchemaAttributesProducer( schema: JSONSchema, _ref: Ref, - types: Set, + types: Set ): JSONSchemaAttributes | undefined { if (!(typeof schema === "object")) return undefined; if (!types.has("string")) return undefined; diff --git a/packages/quicktype-core/src/input/CompressedJSON.ts b/packages/quicktype-core/src/input/CompressedJSON.ts index 069834913..cb3909e0d 100644 --- a/packages/quicktype-core/src/input/CompressedJSON.ts +++ b/packages/quicktype-core/src/input/CompressedJSON.ts @@ -60,32 +60,32 @@ export abstract class CompressedJSON { private _arrays: Value[][] = []; - constructor( - readonly dateTimeRecognizer: DateTimeRecognizer, - readonly handleRefs: boolean + public constructor( + public readonly dateTimeRecognizer: DateTimeRecognizer, + public readonly handleRefs: boolean ) {} - abstract parse(input: T): Promise; + public abstract parse(input: T): Promise; - parseSync(_input: T): Value { + public parseSync(_input: T): Value { return panic("parseSync not implemented in CompressedJSON"); } - getStringForValue(v: Value): string { + public getStringForValue(v: Value): string { const tag = valueTag(v); assert(tag === Tag.InternedString || tag === Tag.TransformedString); return this._strings[getIndex(v, tag)]; } - getObjectForValue = (v: Value): Value[] => { + public getObjectForValue = (v: Value): Value[] => { return this._objects[getIndex(v, Tag.Object)]; }; - getArrayForValue = (v: Value): Value[] => { + public getArrayForValue = (v: Value): Value[] => { return this._arrays[getIndex(v, Tag.Array)]; }; - getStringFormatTypeKind(v: Value): TransformedStringTypeKind { + public getStringFormatTypeKind(v: Value): TransformedStringTypeKind { const kind = this._strings[getIndex(v, Tag.StringFormat)]; if (!isPrimitiveStringTypeKind(kind) || kind === "string") { return panic("Not a transformed string type kind"); @@ -252,11 +252,11 @@ export abstract class CompressedJSON { this._ctx = this._contextStack.pop(); } - equals(other: any): boolean { + public equals(other: any): boolean { return this === other; } - hashCode(): number { + public hashCode(): number { let hashAccumulator = hashCodeInit; for (const s of this._strings) { hashAccumulator = addHashCode(hashAccumulator, hashString(s)); @@ -284,11 +284,11 @@ export abstract class CompressedJSON { } export class CompressedJSONFromString extends CompressedJSON { - async parse(input: string): Promise { + public async parse(input: string): Promise { return this.parseSync(input); } - parseSync(input: string): Value { + public parseSync(input: string): Value { const json = JSON.parse(input); this.process(json); return this.finish(); diff --git a/packages/quicktype-core/src/input/FetchingJSONSchemaStore.ts b/packages/quicktype-core/src/input/FetchingJSONSchemaStore.ts index 113baf372..edd9a8824 100644 --- a/packages/quicktype-core/src/input/FetchingJSONSchemaStore.ts +++ b/packages/quicktype-core/src/input/FetchingJSONSchemaStore.ts @@ -1,14 +1,14 @@ -import { type JSONSchema} from "./JSONSchemaStore"; +import { type JSONSchema } from "./JSONSchemaStore"; import { JSONSchemaStore } from "./JSONSchemaStore"; import { parseJSON } from ".."; import { readFromFileOrURL } from "./io/NodeIO"; export class FetchingJSONSchemaStore extends JSONSchemaStore { - constructor (private readonly _httpHeaders?: string[]) { + public constructor(private readonly _httpHeaders?: string[]) { super(); } - async fetch (address: string): Promise { + public async fetch(address: string): Promise { // console.log(`Fetching ${address}`); return parseJSON(await readFromFileOrURL(address, this._httpHeaders), "JSON Schema", address); } diff --git a/packages/quicktype-core/src/input/Inference.ts b/packages/quicktype-core/src/input/Inference.ts index 272c15d61..07c1c52d3 100644 --- a/packages/quicktype-core/src/input/Inference.ts +++ b/packages/quicktype-core/src/input/Inference.ts @@ -3,19 +3,12 @@ import { Tag, valueTag } from "./CompressedJSON"; import { assertNever, defined, panic, assert } from "../support/Support"; import { type TypeBuilder } from "../TypeBuilder"; import { UnionBuilder, UnionAccumulator } from "../UnionBuilder"; -import { - type ClassProperty} from "../Type"; -import { - transformedStringTypeTargetTypeKindsMap, - UnionType, - ClassType, - MapType, - ArrayType, -} from "../Type"; -import { type TypeAttributes} from "../attributes/TypeAttributes"; +import { type ClassProperty } from "../Type"; +import { transformedStringTypeTargetTypeKindsMap, UnionType, ClassType, MapType, ArrayType } from "../Type"; +import { type TypeAttributes } from "../attributes/TypeAttributes"; import { emptyTypeAttributes } from "../attributes/TypeAttributes"; import { StringTypes, inferTransformedStringTypeKindForString } from "../attributes/StringTypes"; -import { type TypeRef} from "../TypeGraph"; +import { type TypeRef } from "../TypeGraph"; import { derefTypeRef } from "../TypeGraph"; import { messageError } from "../Messages"; import { nullableFromUnion } from "../TypeUtils"; @@ -23,9 +16,10 @@ import { nullableFromUnion } from "../TypeUtils"; // This should be the recursive type // Value[] | NestedValueArray[] // but TypeScript doesn't support that. -export type NestedValueArray = any; +// FIXME +export type NestedValueArray = Value[]; -function forEachArrayInNestedValueArray (va: NestedValueArray, f: (va: Value[]) => void): void { +function forEachArrayInNestedValueArray(va: NestedValueArray, f: (va: Value[]) => void): void { if (va.length === 0) { return; } @@ -39,7 +33,7 @@ function forEachArrayInNestedValueArray (va: NestedValueArray, f: (va: Value[]) } } -function forEachValueInNestedValueArray (va: NestedValueArray, f: (v: Value) => void): void { +function forEachValueInNestedValueArray(va: NestedValueArray, f: (v: Value) => void): void { forEachArrayInNestedValueArray(va, a => { for (const x of a) { f(x); @@ -48,35 +42,35 @@ function forEachValueInNestedValueArray (va: NestedValueArray, f: (v: Value) => } class InferenceUnionBuilder extends UnionBuilder { - constructor ( + public constructor( typeBuilder: TypeBuilder, private readonly _typeInference: TypeInference, - private readonly _fixed: boolean, + private readonly _fixed: boolean ) { super(typeBuilder); } - protected makeObject ( + protected makeObject( objects: NestedValueArray, typeAttributes: TypeAttributes, - forwardingRef: TypeRef | undefined, + forwardingRef: TypeRef | undefined ): TypeRef { return this._typeInference.inferClassType(typeAttributes, objects, this._fixed, forwardingRef); } - protected makeArray ( + protected makeArray( arrays: NestedValueArray, typeAttributes: TypeAttributes, - forwardingRef: TypeRef | undefined, + forwardingRef: TypeRef | undefined ): TypeRef { return this.typeBuilder.getArrayType( typeAttributes, - this._typeInference.inferType(emptyTypeAttributes, arrays, this._fixed, forwardingRef), + this._typeInference.inferType(emptyTypeAttributes, arrays, this._fixed, forwardingRef) ); } } -function canBeEnumCase (_s: string): boolean { +function canBeEnumCase(_s: string): boolean { return true; } @@ -85,14 +79,14 @@ export type Accumulator = UnionAccumulator; export class TypeInference { private _refIntersections: Array<[TypeRef, string[]]> | undefined; - constructor ( + public constructor( private readonly _cjson: CompressedJSON, private readonly _typeBuilder: TypeBuilder, private readonly _inferMaps: boolean, - private readonly _inferEnums: boolean, + private readonly _inferEnums: boolean ) {} - addValuesToAccumulator (valueArray: NestedValueArray, accumulator: Accumulator): void { + private addValuesToAccumulator(valueArray: NestedValueArray, accumulator: Accumulator): void { forEachValueInNestedValueArray(valueArray, value => { const t = valueTag(value); switch (t) { @@ -136,7 +130,7 @@ export class TypeInference { accumulator.addStringType( "string", emptyTypeAttributes, - new StringTypes(new Map(), new Set([kind])), + new StringTypes(new Map(), new Set([kind])) ); break; } @@ -163,17 +157,17 @@ export class TypeInference { }); } - inferType ( + public inferType( typeAttributes: TypeAttributes, valueArray: NestedValueArray, fixed: boolean, - forwardingRef?: TypeRef, + forwardingRef?: TypeRef ): TypeRef { const accumulator = this.accumulatorForArray(valueArray); return this.makeTypeFromAccumulator(accumulator, typeAttributes, fixed, forwardingRef); } - private resolveRef (ref: string, topLevel: TypeRef): TypeRef { + private resolveRef(ref: string, topLevel: TypeRef): TypeRef { if (!ref.startsWith("#/")) { return messageError("InferenceJSONReferenceNotRooted", { reference: ref }); } @@ -216,7 +210,7 @@ export class TypeInference { return tref; } - inferTopLevelType (typeAttributes: TypeAttributes, valueArray: NestedValueArray, fixed: boolean): TypeRef { + public inferTopLevelType(typeAttributes: TypeAttributes, valueArray: NestedValueArray, fixed: boolean): TypeRef { assert(this._refIntersections === undefined, "Didn't reset ref intersections - nested invocations?"); if (this._cjson.handleRefs) { this._refIntersections = []; @@ -235,30 +229,30 @@ export class TypeInference { return topLevel; } - accumulatorForArray (valueArray: NestedValueArray): Accumulator { + private accumulatorForArray(valueArray: NestedValueArray): Accumulator { const accumulator = new UnionAccumulator(true); this.addValuesToAccumulator(valueArray, accumulator); return accumulator; } - makeTypeFromAccumulator ( + private makeTypeFromAccumulator( accumulator: Accumulator, typeAttributes: TypeAttributes, fixed: boolean, - forwardingRef?: TypeRef, + forwardingRef?: TypeRef ): TypeRef { const unionBuilder = new InferenceUnionBuilder(this._typeBuilder, this, fixed); return unionBuilder.buildUnion(accumulator, false, typeAttributes, forwardingRef); } - inferClassType ( + public inferClassType( typeAttributes: TypeAttributes, objects: NestedValueArray, fixed: boolean, - forwardingRef?: TypeRef, + forwardingRef?: TypeRef ): TypeRef { const propertyNames: string[] = []; - const propertyValues: { [name: string]: Value[], } = {}; + const propertyValues: { [name: string]: Value[] } = {}; forEachArrayInNestedValueArray(objects, arr => { for (let i = 0; i < arr.length; i += 2) { diff --git a/packages/quicktype-core/src/input/Inputs.ts b/packages/quicktype-core/src/input/Inputs.ts index 4d9ebc1de..5f57ac684 100644 --- a/packages/quicktype-core/src/input/Inputs.ts +++ b/packages/quicktype-core/src/input/Inputs.ts @@ -1,6 +1,6 @@ import { iterableFirst, iterableFind, iterableSome, setFilterMap, withDefault, arrayMapSync } from "collection-utils"; -import { type Value, type CompressedJSON} from "./CompressedJSON"; +import { type Value, type CompressedJSON } from "./CompressedJSON"; import { CompressedJSONFromString } from "./CompressedJSON"; import { panic, errorMessage, defined } from "../support/Support"; import { messageError } from "../Messages"; @@ -39,7 +39,8 @@ export interface Input { } interface JSONTopLevel { - description: string | undefined; samples: Value[]; + description: string | undefined; + samples: Value[]; } export interface JSONSourceData { @@ -48,26 +49,26 @@ export interface JSONSourceData { samples: T[]; } -function messageParseError (name: string, description: string | undefined, e: unknown): never { +function messageParseError(name: string, description: string | undefined, e: unknown): never { return messageError("MiscJSONParseError", { description: withDefault(description, "input"), address: name, - message: errorMessage(e), + message: errorMessage(e) }); } export class JSONInput implements Input> { - readonly kind: string = "json"; + public readonly kind: string = "json"; - readonly needIR: boolean = true; + public readonly needIR: boolean = true; - readonly needSchemaProcessing: boolean = false; + public readonly needSchemaProcessing: boolean = false; private readonly _topLevels: Map = new Map(); - constructor (private readonly _compressedJSON: CompressedJSON) {} + public constructor(private readonly _compressedJSON: CompressedJSON) {} - private addSample (topLevelName: string, sample: Value): void { + private addSample(topLevelName: string, sample: Value): void { let topLevel = this._topLevels.get(topLevelName); if (topLevel === undefined) { topLevel = { samples: [], description: undefined }; @@ -77,7 +78,7 @@ export class JSONInput implements Input> { topLevel.samples.push(sample); } - private setDescription (topLevelName: string, description: string): void { + private setDescription(topLevelName: string, description: string): void { let topLevel = this._topLevels.get(topLevelName); if (topLevel === undefined) { return panic("Trying to set description for a top-level that doesn't exist"); @@ -86,7 +87,7 @@ export class JSONInput implements Input> { topLevel.description = description; } - private addSamples (name: string, values: Value[], description: string | undefined): void { + private addSamples(name: string, values: Value[], description: string | undefined): void { for (const value of values) { this.addSample(name, value); if (description !== undefined) { @@ -95,7 +96,7 @@ export class JSONInput implements Input> { } } - async addSource (source: JSONSourceData): Promise { + public async addSource(source: JSONSourceData): Promise { const { name, samples, description } = source; try { const values = await arrayMapSync(samples, async s => await this._compressedJSON.parse(s)); @@ -105,7 +106,7 @@ export class JSONInput implements Input> { } } - addSourceSync (source: JSONSourceData): void { + public addSourceSync(source: JSONSourceData): void { const { name, samples, description } = source; try { const values = samples.map(s => this._compressedJSON.parseSync(s)); @@ -115,26 +116,26 @@ export class JSONInput implements Input> { } } - singleStringSchemaSource (): undefined { + public singleStringSchemaSource(): undefined { return undefined; } - async addTypes ( + public async addTypes( ctx: RunContext, typeBuilder: TypeBuilder, inferMaps: boolean, inferEnums: boolean, - fixedTopLevels: boolean, + fixedTopLevels: boolean ): Promise { this.addTypesSync(ctx, typeBuilder, inferMaps, inferEnums, fixedTopLevels); } - addTypesSync ( + public addTypesSync( _ctx: RunContext, typeBuilder: TypeBuilder, inferMaps: boolean, inferEnums: boolean, - fixedTopLevels: boolean, + fixedTopLevels: boolean ): void { const inference = new TypeInference(this._compressedJSON, typeBuilder, inferMaps, inferEnums); @@ -149,10 +150,10 @@ export class JSONInput implements Input> { } } -export function jsonInputForTargetLanguage ( +export function jsonInputForTargetLanguage( targetLanguage: string | TargetLanguage, languages?: TargetLanguage[], - handleJSONRefs = false, + handleJSONRefs = false ): JSONInput { if (typeof targetLanguage === "string") { targetLanguage = defined(languageNamed(targetLanguage, languages)); @@ -166,7 +167,7 @@ export class InputData { // FIXME: Make into a Map, indexed by kind. private _inputs: Set> = new Set(); - addInput(input: Input): void { + protected addInput(input: Input): void { this._inputs = this._inputs.add(input); } @@ -180,49 +181,49 @@ export class InputData { return input; } - async addSource(kind: string, source: T, makeInput: () => Input): Promise { + public async addSource(kind: string, source: T, makeInput: () => Input): Promise { const input = this.getOrAddInput(kind, makeInput); await input.addSource(source); } - addSourceSync(kind: string, source: T, makeInput: () => Input): void { + public addSourceSync(kind: string, source: T, makeInput: () => Input): void { const input = this.getOrAddInput(kind, makeInput); input.addSourceSync(source); } - async addTypes ( + public async addTypes( ctx: RunContext, typeBuilder: TypeBuilder, inferMaps: boolean, inferEnums: boolean, - fixedTopLevels: boolean, + fixedTopLevels: boolean ): Promise { for (const input of this._inputs) { await input.addTypes(ctx, typeBuilder, inferMaps, inferEnums, fixedTopLevels); } } - addTypesSync ( + public addTypesSync( ctx: RunContext, typeBuilder: TypeBuilder, inferMaps: boolean, inferEnums: boolean, - fixedTopLevels: boolean, + fixedTopLevels: boolean ): void { for (const input of this._inputs) { input.addTypesSync(ctx, typeBuilder, inferMaps, inferEnums, fixedTopLevels); } } - get needIR (): boolean { + public get needIR(): boolean { return iterableSome(this._inputs, i => i.needIR); } - get needSchemaProcessing (): boolean { + public get needSchemaProcessing(): boolean { return iterableSome(this._inputs, i => i.needSchemaProcessing); } - singleStringSchemaSource (): string | undefined { + public singleStringSchemaSource(): string | undefined { const schemaStrings = setFilterMap(this._inputs, i => i.singleStringSchemaSource()); if (schemaStrings.size > 1) { return panic("We have more than one input with a string schema source"); diff --git a/packages/quicktype-core/src/input/JSONSchemaInput.ts b/packages/quicktype-core/src/input/JSONSchemaInput.ts index d3226c949..427e74d75 100644 --- a/packages/quicktype-core/src/input/JSONSchemaInput.ts +++ b/packages/quicktype-core/src/input/JSONSchemaInput.ts @@ -125,7 +125,7 @@ function normalizeURI(uri: string | URI): URI { } export class Ref { - static root(address: string | undefined): Ref { + public static root(address: string | undefined): Ref { const uri = definedMap(address, a => new URI(a)); return new Ref(uri, []); } @@ -146,7 +146,7 @@ export class Ref { return elements; } - static parseURI(uri: URI, destroyURI = false): Ref { + public static parseURI(uri: URI, destroyURI = false): Ref { if (!destroyURI) { uri = uri.clone(); } @@ -161,15 +161,15 @@ export class Ref { return new Ref(uri, elements); } - static parse(ref: string): Ref { + public static parse(ref: string): Ref { return Ref.parseURI(new URI(ref), true); } public addressURI: URI | undefined; - constructor( + public constructor( addressURI: URI | undefined, - readonly path: readonly PathElement[] + public readonly path: readonly PathElement[] ) { if (addressURI !== undefined) { assert(addressURI.fragment() === "", `Ref URI with fragment is not allowed: ${addressURI.toString()}`); @@ -179,15 +179,15 @@ export class Ref { } } - get hasAddress(): boolean { + public get hasAddress(): boolean { return this.addressURI !== undefined; } - get address(): string { + public get address(): string { return defined(this.addressURI).toString(); } - get isRoot(): boolean { + public get isRoot(): boolean { return this.path.length === 1 && this.path[0].kind === PathElementKind.Root; } @@ -197,7 +197,7 @@ export class Ref { return new Ref(this.addressURI, newPath); } - push(...keys: string[]): Ref { + public push(...keys: string[]): Ref { let ref: Ref = this; for (const key of keys) { ref = ref.pushElement({ kind: PathElementKind.KeyOrIndex, key }); @@ -206,15 +206,15 @@ export class Ref { return ref; } - pushObject(): Ref { + public pushObject(): Ref { return this.pushElement({ kind: PathElementKind.Object }); } - pushType(index: number): Ref { + public pushType(index: number): Ref { return this.pushElement({ kind: PathElementKind.Type, index }); } - resolveAgainst(base: Ref | undefined): Ref { + public resolveAgainst(base: Ref | undefined): Ref { let addressURI = this.addressURI; if (base?.addressURI !== undefined) { addressURI = addressURI === undefined ? base.addressURI : addressURI.absoluteTo(base.addressURI); @@ -223,7 +223,7 @@ export class Ref { return new Ref(addressURI, this.path); } - get name(): string { + public get name(): string { const path = Array.from(this.path); for (;;) { @@ -258,14 +258,14 @@ export class Ref { } } - get definitionName(): string | undefined { + public get definitionName(): string | undefined { const pe = arrayGetFromEnd(this.path, 2); if (pe === undefined) return undefined; if (keyOrIndex(pe) === "definitions") return keyOrIndex(defined(arrayLast(this.path))); return undefined; } - toString(): string { + public toString(): string { function elementToString(e: PathElement): string { switch (e.kind) { case PathElementKind.Root: @@ -326,11 +326,11 @@ export class Ref { } } - lookupRef(root: JSONSchema): JSONSchema { + public lookupRef(root: JSONSchema): JSONSchema { return this.lookup(root, this.path, root); } - equals(other: any): boolean { + public equals(other: any): boolean { if (!(other instanceof Ref)) return false; if (this.addressURI !== undefined && other.addressURI !== undefined) { if (!this.addressURI.equals(other.addressURI)) return false; @@ -347,7 +347,7 @@ export class Ref { return true; } - hashCode(): number { + public hashCode(): number { let acc = hashCodeOf(definedMap(this.addressURI, u => u.toString())); for (const pe of this.path) { acc = addHashCode(acc, pe.kind); @@ -372,16 +372,16 @@ class Location { public readonly virtualRef: Ref; - constructor( + public constructor( canonicalRef: Ref, virtualRef?: Ref, - readonly haveID: boolean = false + public readonly haveID: boolean = false ) { this.canonicalRef = canonicalRef; this.virtualRef = virtualRef !== undefined ? virtualRef : canonicalRef; } - updateWithID(id: any) { + public updateWithID(id: any) { if (typeof id !== "string") return this; const parsed = Ref.parse(id); const virtual = this.haveID ? parsed.resolveAgainst(this.virtualRef) : parsed; @@ -392,19 +392,19 @@ class Location { return new Location(this.canonicalRef, virtual, true); } - push(...keys: string[]): Location { + public push(...keys: string[]): Location { return new Location(this.canonicalRef.push(...keys), this.virtualRef.push(...keys), this.haveID); } - pushObject(): Location { + public pushObject(): Location { return new Location(this.canonicalRef.pushObject(), this.virtualRef.pushObject(), this.haveID); } - pushType(index: number): Location { + public pushType(index: number): Location { return new Location(this.canonicalRef.pushType(index), this.virtualRef.pushType(index), this.haveID); } - toString(): string { + public toString(): string { return `${this.virtualRef.toString()} (${this.canonicalRef.toString()})`; } } @@ -414,7 +414,7 @@ class Canonizer { private readonly _schemaAddressesAdded = new Set(); - constructor(private readonly _ctx: RunContext) {} + public constructor(private readonly _ctx: RunContext) {} private addIDs(schema: any, loc: Location) { if (schema === null) return; @@ -449,7 +449,7 @@ class Canonizer { } } - addSchema(schema: any, address: string): boolean { + public addSchema(schema: any, address: string): boolean { if (this._schemaAddressesAdded.has(address)) return false; this.addIDs(schema, new Location(Ref.root(address), Ref.root(undefined))); @@ -458,7 +458,7 @@ class Canonizer { } // Returns: Canonical ref - canonize(base: Location, ref: Ref): Location { + public canonize(base: Location, ref: Ref): Location { const virtual = ref.resolveAgainst(base.virtualRef); const loc = this._map.get(virtual); if (loc !== undefined) { @@ -560,7 +560,7 @@ function schemaFetchError(base: Location | undefined, address: string): never { } class Resolver { - constructor( + public constructor( private readonly _ctx: RunContext, private readonly _store: JSONSchemaStore, private readonly _canonizer: Canonizer @@ -608,7 +608,7 @@ class Resolver { } } - async resolveVirtualRef(base: Location, virtualRef: Ref): Promise<[JSONSchema, Location]> { + public async resolveVirtualRef(base: Location, virtualRef: Ref): Promise<[JSONSchema, Location]> { if (this._ctx.debugPrintSchemaResolving) { console.log(`resolving ${virtualRef.toString()} relative to ${base.toString()}`); } @@ -643,7 +643,7 @@ class Resolver { return schemaFetchError(base, virtualRef.address); } - async resolveTopLevelRef(ref: Ref): Promise<[JSONSchema, Location]> { + public async resolveTopLevelRef(ref: Ref): Promise<[JSONSchema, Location]> { return await this.resolveVirtualRef(new Location(new Ref(ref.addressURI, [])), new Ref(undefined, ref.path)); } } @@ -1151,14 +1151,14 @@ async function refsInSchemaForURI( } class InputJSONSchemaStore extends JSONSchemaStore { - constructor( + public constructor( private readonly _inputs: Map, private readonly _delegate?: JSONSchemaStore ) { super(); } - async fetch(address: string): Promise { + public async fetch(address: string): Promise { const maybeInput = this._inputs.get(address); if (maybeInput !== undefined) { return checkJSONSchema(parseJSON(maybeInput, "JSON Schema", address), () => Ref.root(address)); @@ -1180,9 +1180,9 @@ export interface JSONSchemaSourceData { } export class JSONSchemaInput implements Input { - readonly kind: string = "schema"; + public readonly kind: string = "schema"; - readonly needSchemaProcessing: boolean = true; + public readonly needSchemaProcessing: boolean = true; private readonly _attributeProducers: JSONSchemaAttributeProducer[]; @@ -1194,7 +1194,7 @@ export class JSONSchemaInput implements Input { private _needIR = false; - constructor( + public constructor( private _schemaStore: JSONSchemaStore | undefined, additionalAttributeProducers: JSONSchemaAttributeProducer[] = [], private readonly _additionalSchemaAddresses: readonly string[] = [] @@ -1210,15 +1210,15 @@ export class JSONSchemaInput implements Input { ].concat(additionalAttributeProducers); } - get needIR(): boolean { + public get needIR(): boolean { return this._needIR; } - addTopLevel(name: string, ref: Ref): void { + public addTopLevel(name: string, ref: Ref): void { this._topLevels.set(name, ref); } - async addTypes(ctx: RunContext, typeBuilder: TypeBuilder): Promise { + public async addTypes(ctx: RunContext, typeBuilder: TypeBuilder): Promise { if (this._schemaSources.length === 0) return; let maybeSchemaStore = this._schemaStore; @@ -1267,15 +1267,15 @@ export class JSONSchemaInput implements Input { await addTypesInSchema(resolver, typeBuilder, this._topLevels, this._attributeProducers); } - addTypesSync(): void { + public addTypesSync(): void { return panic("addTypesSync not supported in JSONSchemaInput"); } - async addSource(schemaSource: JSONSchemaSourceData): Promise { + public async addSource(schemaSource: JSONSchemaSourceData): Promise { this.addSourceSync(schemaSource); } - addSourceSync(schemaSource: JSONSchemaSourceData): void { + public addSourceSync(schemaSource: JSONSchemaSourceData): void { const { name, uris, schema, isConverted } = schemaSource; if (isConverted !== true) { @@ -1323,7 +1323,7 @@ export class JSONSchemaInput implements Input { } } - singleStringSchemaSource(): string | undefined { + public singleStringSchemaSource(): string | undefined { if (!this._schemaSources.every(([_, { schema }]) => typeof schema === "string")) { return undefined; } diff --git a/packages/quicktype-core/src/input/JSONSchemaStore.ts b/packages/quicktype-core/src/input/JSONSchemaStore.ts index 32f886e3e..9fe5c62ec 100644 --- a/packages/quicktype-core/src/input/JSONSchemaStore.ts +++ b/packages/quicktype-core/src/input/JSONSchemaStore.ts @@ -1,4 +1,4 @@ -import { type StringMap} from "../support/Support"; +import { type StringMap } from "../support/Support"; import { assert } from "../support/Support"; export type JSONSchema = StringMap | boolean; @@ -6,15 +6,15 @@ export type JSONSchema = StringMap | boolean; export abstract class JSONSchemaStore { private readonly _schemas = new Map(); - private add (address: string, schema: JSONSchema): void { + private add(address: string, schema: JSONSchema): void { assert(!this._schemas.has(address), "Cannot set a schema for an address twice"); this._schemas.set(address, schema); } // FIXME: Remove the undefined option - abstract fetch (_address: string): Promise; + public abstract fetch(_address: string): Promise; - async get (address: string, debugPrint: boolean): Promise { + public async get(address: string, debugPrint: boolean): Promise { let schema = this._schemas.get(address); if (schema !== undefined) { return schema; diff --git a/packages/quicktype-core/src/language/CJSON.ts b/packages/quicktype-core/src/language/CJSON.ts index 96556fe3e..4bfb848ea 100644 --- a/packages/quicktype-core/src/language/CJSON.ts +++ b/packages/quicktype-core/src/language/CJSON.ts @@ -139,7 +139,7 @@ export class CJSONTargetLanguage extends TargetLanguage { * @params names: names * @param extension: extension of files */ - constructor(displayName = "C (cJSON)", names: string[] = ["cjson", "cJSON"], extension = "h") { + public constructor(displayName = "C (cJSON)", names: string[] = ["cjson", "cJSON"], extension = "h") { super(displayName, names, extension); } @@ -164,7 +164,7 @@ export class CJSONTargetLanguage extends TargetLanguage { * Indicate if language support union with both number types * @return true */ - get supportsUnionsWithBothNumberTypes(): boolean { + public get supportsUnionsWithBothNumberTypes(): boolean { return true; } @@ -172,7 +172,7 @@ export class CJSONTargetLanguage extends TargetLanguage { * Indicate if language support optional class properties * @return true */ - get supportsOptionalClassProperties(): boolean { + public get supportsOptionalClassProperties(): boolean { return true; } @@ -387,7 +387,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param renderContext: render context * @param _options: renderer options */ - constructor( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues diff --git a/packages/quicktype-core/src/language/CPlusPlus.ts b/packages/quicktype-core/src/language/CPlusPlus.ts index 94b60d3a4..f5ec4f5f0 100644 --- a/packages/quicktype-core/src/language/CPlusPlus.ts +++ b/packages/quicktype-core/src/language/CPlusPlus.ts @@ -125,7 +125,7 @@ export const cPlusPlusOptions = { }; export class CPlusPlusTargetLanguage extends TargetLanguage { - constructor(displayName = "C++", names: string[] = ["c++", "cpp", "cplusplus"], extension = "cpp") { + public constructor(displayName = "C++", names: string[] = ["c++", "cpp", "cplusplus"], extension = "cpp") { super(displayName, names, extension); } @@ -147,11 +147,11 @@ export class CPlusPlusTargetLanguage extends TargetLanguage { ]; } - get supportsUnionsWithBothNumberTypes(): boolean { + public get supportsUnionsWithBothNumberTypes(): boolean { return true; } - get supportsOptionalClassProperties(): boolean { + public get supportsOptionalClassProperties(): boolean { return true; } @@ -392,12 +392,12 @@ function addQualifier(qualifier: Sourcelike, qualified: Sourcelike[]): Sourcelik } class WrappingCode { - constructor( + public constructor( private readonly start: Sourcelike[], private readonly end: Sourcelike[] ) {} - wrap(qualifier: Sourcelike, inner: Sourcelike): Sourcelike { + public wrap(qualifier: Sourcelike, inner: Sourcelike): Sourcelike { return [addQualifier(qualifier, this.start), inner, this.end]; } } @@ -419,7 +419,7 @@ class BaseString { public _encodingFunction: Sourcelike; - constructor( + public constructor( stringType: string, constStringType: string, smatch: string, @@ -509,7 +509,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { protected readonly enumeratorNamingStyle: NamingStyle; - constructor( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues @@ -557,14 +557,14 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } // union typeguard - isUnion(t: Type | UnionType): t is UnionType { + private isUnion(t: Type | UnionType): t is UnionType { return t.kind === "union"; } // Returns true if the type can be stored in // a stack based optional type. This requires // that the type does not require forward declaration. - isOptionalAsValuePossible(t: Type): boolean { + private isOptionalAsValuePossible(t: Type): boolean { if (this.isForwardDeclaredType(t)) return false; if (this.isUnion(t)) { @@ -626,42 +626,42 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { return !this.isCycleBreakerType(t); } - isImplicitCycleBreaker(t: Type): boolean { + public isImplicitCycleBreaker(t: Type): boolean { const kind = t.kind; return kind === "array" || kind === "map"; } // Is likely to return std::optional or boost::optional - optionalTypeStack(): string { + private optionalTypeStack(): string { return this._optionalType; } // Is likely to return std::make_optional or boost::optional - optionalFactoryStack(): string { + private optionalFactoryStack(): string { return this._optionalFactory; } // Is likely to return std::shared_ptr - optionalTypeHeap(): string { + private optionalTypeHeap(): string { return optionalAsSharedType; } // Is likely to return std::make_shared - optionalFactoryHeap(): string { + private optionalFactoryHeap(): string { return optionalFactoryAsSharedType; } // Returns the optional type most suitable for the given type. // Classes that don't require forward declarations can be stored // in std::optional ( or boost::optional ) - optionalType(t: Type): string { + private optionalType(t: Type): string { if (this.isOptionalAsValuePossible(t)) return this.optionalTypeStack(); else return this.optionalTypeHeap(); } // Returns a label that can be used to distinguish between // heap and stack based optional handling methods - optionalTypeLabel(t: Type): string { + private optionalTypeLabel(t: Type): string { if (this.isOptionalAsValuePossible(t)) return "stack"; else return "heap"; } @@ -3012,7 +3012,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } public NarrowString = new (class extends BaseString implements StringType { - constructor() { + public constructor() { super( "std::string", "const std::string & ", @@ -3040,7 +3040,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { })(); public WideString = new (class extends BaseString implements StringType { - constructor(public superThis: CPlusPlusRenderer) { + public constructor(public superThis: CPlusPlusRenderer) { super( "std::wstring", "const std::wstring & ", diff --git a/packages/quicktype-core/src/language/CSharp.ts b/packages/quicktype-core/src/language/CSharp.ts index e9ee7be51..f87193182 100644 --- a/packages/quicktype-core/src/language/CSharp.ts +++ b/packages/quicktype-core/src/language/CSharp.ts @@ -201,7 +201,7 @@ export const cSharpOptions = { }; export class CSharpTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super("C#", ["cs", "csharp"], "cs"); } @@ -222,7 +222,7 @@ export class CSharpTargetLanguage extends TargetLanguage { ]; } - get stringTypeMapping(): StringTypeMapping { + public get stringTypeMapping(): StringTypeMapping { const mapping: Map = new Map(); mapping.set("date", "date-time"); mapping.set("time", "date-time"); @@ -234,15 +234,15 @@ export class CSharpTargetLanguage extends TargetLanguage { return mapping; } - get supportsUnionsWithBothNumberTypes(): boolean { + public get supportsUnionsWithBothNumberTypes(): boolean { return true; } - get supportsOptionalClassProperties(): boolean { + public get supportsOptionalClassProperties(): boolean { return true; } - needsTransformerForType(t: Type): boolean { + public needsTransformerForType(t: Type): boolean { const need = needTransformerForType(t); return need !== "none" && need !== "nullable"; } @@ -424,7 +424,7 @@ function isValueType(t: Type): boolean { } export class CSharpRenderer extends ConvenienceRenderer { - constructor( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, private readonly _csOptions: OptionValues @@ -801,7 +801,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { private readonly _needNamespaces: boolean; - constructor( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues @@ -1562,7 +1562,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { private readonly _needNamespaces: boolean; - constructor( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues @@ -2428,19 +2428,19 @@ internal class IsoDateTimeOffsetConverter : JsonConverter public DateTimeStyles DateTimeStyles { - get => _dateTimeStyles; +public get => _dateTimeStyles; set => _dateTimeStyles = value; } public string? DateTimeFormat { - get => _dateTimeFormat ?? string.Empty; +public get => _dateTimeFormat ?? string.Empty; set => _dateTimeFormat = (string.IsNullOrEmpty(value)) ? null : value; } public CultureInfo Culture { - get => _culture ?? CultureInfo.CurrentCulture; +public get => _culture ?? CultureInfo.CurrentCulture; set => _culture = value; } diff --git a/packages/quicktype-core/src/language/Crystal.ts b/packages/quicktype-core/src/language/Crystal.ts index 61fcd28c9..05708f30a 100644 --- a/packages/quicktype-core/src/language/Crystal.ts +++ b/packages/quicktype-core/src/language/Crystal.ts @@ -13,32 +13,32 @@ import { escapeNonPrintableMapper, isPrintable, isAscii, - isLetterOrUnderscore, + isLetterOrUnderscore } from "../support/Strings"; -import { type Name, type Namer} from "../Naming"; +import { type Name, type Namer } from "../Naming"; import { funPrefixNamer } from "../Naming"; import { type UnionType, type Type, type ClassType, type EnumType } from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { type Sourcelike} from "../Source"; +import { type Sourcelike } from "../Source"; import { maybeAnnotated } from "../Source"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; import { type Option } from "../RendererOptions"; import { type RenderContext } from "../Renderer"; export class CrystalTargetLanguage extends TargetLanguage { - protected makeRenderer (renderContext: RenderContext): CrystalRenderer { + protected makeRenderer(renderContext: RenderContext): CrystalRenderer { return new CrystalRenderer(this, renderContext); } - constructor () { + public constructor() { super("Crystal", ["crystal", "cr", "crystallang"], "cr"); } - protected get defaultIndentation (): string { + protected get defaultIndentation(): string { return " "; } - protected getOptions (): Array> { + protected getOptions(): Array> { return []; } } @@ -179,10 +179,10 @@ const keywords = [ "when", "while", "with", - "yield", + "yield" ]; -function isAsciiLetterOrUnderscoreOrDigit (codePoint: number): boolean { +function isAsciiLetterOrUnderscoreOrDigit(codePoint: number): boolean { if (!isAscii(codePoint)) { return false; } @@ -190,7 +190,7 @@ function isAsciiLetterOrUnderscoreOrDigit (codePoint: number): boolean { return isLetterOrUnderscoreOrDigit(codePoint); } -function isAsciiLetterOrUnderscore (codePoint: number): boolean { +function isAsciiLetterOrUnderscore(codePoint: number): boolean { if (!isAscii(codePoint)) { return false; } @@ -200,7 +200,7 @@ function isAsciiLetterOrUnderscore (codePoint: number): boolean { const legalizeName = legalizeCharacters(isAsciiLetterOrUnderscoreOrDigit); -function crystalStyle (original: string, isSnakeCase: boolean): string { +function crystalStyle(original: string, isSnakeCase: boolean): string { const words = splitIntoWords(original); const wordStyle = isSnakeCase ? allLowerWordStyle : firstUpperWordStyle; @@ -213,7 +213,7 @@ function crystalStyle (original: string, isSnakeCase: boolean): string { wordStyle, wordStyle, isSnakeCase ? "_" : "", - isAsciiLetterOrUnderscore, + isAsciiLetterOrUnderscore ); return combined === "_" ? "_underscore" : combined; @@ -222,7 +222,7 @@ function crystalStyle (original: string, isSnakeCase: boolean): string { const snakeNamingFunction = funPrefixNamer("default", (original: string) => crystalStyle(original, true)); const camelNamingFunction = funPrefixNamer("camel", (original: string) => crystalStyle(original, false)); -function standardUnicodeCrystalEscape (codePoint: number): string { +function standardUnicodeCrystalEscape(codePoint: number): string { if (codePoint <= 0xffff) { return "\\u{" + intToHex(codePoint, 4) + "}"; } else { @@ -233,56 +233,56 @@ function standardUnicodeCrystalEscape (codePoint: number): string { const crystalStringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, standardUnicodeCrystalEscape)); export class CrystalRenderer extends ConvenienceRenderer { - constructor (targetLanguage: TargetLanguage, renderContext: RenderContext) { + public constructor(targetLanguage: TargetLanguage, renderContext: RenderContext) { super(targetLanguage, renderContext); } - protected makeNamedTypeNamer (): Namer { + protected makeNamedTypeNamer(): Namer { return camelNamingFunction; } - protected namerForObjectProperty (): Namer | null { + protected namerForObjectProperty(): Namer | null { return snakeNamingFunction; } - protected makeUnionMemberNamer (): Namer | null { + protected makeUnionMemberNamer(): Namer | null { return camelNamingFunction; } - protected makeEnumCaseNamer (): Namer | null { + protected makeEnumCaseNamer(): Namer | null { return camelNamingFunction; } - protected forbiddenNamesForGlobalNamespace (): string[] { + protected forbiddenNamesForGlobalNamespace(): string[] { return keywords; } - protected forbiddenForObjectProperties (_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForUnionMembers (_u: UnionType, _unionName: Name): ForbiddenWordsInfo { + protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForEnumCases (_e: EnumType, _enumName: Name): ForbiddenWordsInfo { + protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected get commentLineStart (): string { + protected get commentLineStart(): string { return "# "; } - private nullableCrystalType (t: Type, withIssues: boolean): Sourcelike { + private nullableCrystalType(t: Type, withIssues: boolean): Sourcelike { return [this.crystalType(t, withIssues), "?"]; } - protected isImplicitCycleBreaker (t: Type): boolean { + protected isImplicitCycleBreaker(t: Type): boolean { const kind = t.kind; return kind === "array" || kind === "map"; } - private crystalType (t: Type, withIssues = false): Sourcelike { + private crystalType(t: Type, withIssues = false): Sourcelike { return matchType( t, _anyType => maybeAnnotated(withIssues, anyTypeIssueAnnotation, "JSON::Any?"), @@ -305,23 +305,23 @@ export class CrystalRenderer extends ConvenienceRenderer { const name = this.nameForNamedType(unionType); return hasNull !== null ? ([name, "?"] as Sourcelike) : name; - }, + } ); } - private breakCycle (t: Type, withIssues: boolean): Sourcelike { + private breakCycle(t: Type, withIssues: boolean): Sourcelike { return this.crystalType(t, withIssues); } - private emitRenameAttribute (propName: Name, jsonName: string): void { + private emitRenameAttribute(propName: Name, jsonName: string): void { const escapedName = crystalStringEscape(jsonName); const namesDiffer = this.sourcelikeToString(propName) !== escapedName; if (namesDiffer) { - this.emitLine("@[JSON::Field(key: \"", escapedName, "\")]"); + this.emitLine('@[JSON::Field(key: "', escapedName, '")]'); } } - protected emitStructDefinition (c: ClassType, className: Name): void { + protected emitStructDefinition(c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); const structBody = () => @@ -335,7 +335,7 @@ export class CrystalRenderer extends ConvenienceRenderer { this.emitBlock(["class ", className], structBody); } - protected emitBlock (line: Sourcelike, f: () => void): void { + protected emitBlock(line: Sourcelike, f: () => void): void { this.emitLine(line); this.indent(() => { this.emitLine("include JSON::Serializable"); @@ -345,13 +345,13 @@ export class CrystalRenderer extends ConvenienceRenderer { this.emitLine("end"); } - protected emitEnum (line: Sourcelike, f: () => void): void { + protected emitEnum(line: Sourcelike, f: () => void): void { this.emitLine(line); this.indent(f); this.emitLine("end"); } - protected emitUnion (u: UnionType, unionName: Name): void { + protected emitUnion(u: UnionType, unionName: Name): void { const isMaybeWithSingleType = nullableFromUnion(u); if (isMaybeWithSingleType !== null) { @@ -372,30 +372,30 @@ export class CrystalRenderer extends ConvenienceRenderer { "alias ", unionName, " = ", - types.map(r => r.map(sl => this.sourcelikeToString(sl))).join(" | "), + types.map(r => r.map(sl => this.sourcelikeToString(sl))).join(" | ") ]); } - protected emitTopLevelAlias (t: Type, name: Name): void { + protected emitTopLevelAlias(t: Type, name: Name): void { this.emitLine("alias ", name, " = ", this.crystalType(t)); } - protected emitLeadingComments (): void { + protected emitLeadingComments(): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); return; } } - protected emitSourceStructure (): void { + protected emitSourceStructure(): void { this.emitLeadingComments(); this.ensureBlankLine(); - this.emitLine("require \"json\""); + this.emitLine('require "json"'); this.forEachTopLevel( "leading", (t, name) => this.emitTopLevelAlias(t, name), - t => this.namedTypeToNameForTopLevel(t) === undefined, + t => this.namedTypeToNameForTopLevel(t) === undefined ); this.forEachObject("leading-and-interposing", (c: ClassType, name: Name) => this.emitStructDefinition(c, name)); diff --git a/packages/quicktype-core/src/language/Dart.ts b/packages/quicktype-core/src/language/Dart.ts index 308d8091b..a30e797a1 100644 --- a/packages/quicktype-core/src/language/Dart.ts +++ b/packages/quicktype-core/src/language/Dart.ts @@ -4,11 +4,9 @@ import { type PrimitiveStringTypeKind, type TransformedStringTypeKind, type Type, - type UnionType, -} from "../Type"; -import { - EnumType, + type UnionType } from "../Type"; +import { EnumType } from "../Type"; import { directlyReachableSingleNamedType, matchType, nullableFromUnion } from "../TypeUtils"; import { type Sourcelike } from "../Source"; import { maybeAnnotated, modifySource } from "../Source"; @@ -27,7 +25,7 @@ import { splitIntoWords, standardUnicodeHexEscape, utf16ConcatMap, - utf16LegalizeCharacters, + utf16LegalizeCharacters } from "../support/Strings"; import { type StringTypeMapping } from "../TypeBuilder"; @@ -37,7 +35,7 @@ import { DependencyName, funPrefixNamer } from "../Naming"; import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; import { TargetLanguage } from "../TargetLanguage"; -import { type Option, type OptionValues} from "../RendererOptions"; +import { type Option, type OptionValues } from "../RendererOptions"; import { BooleanOption, getOptionValues, StringOption } from "../RendererOptions"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; import { defined } from "../support/Support"; @@ -55,24 +53,24 @@ export const dartOptions = { "use-freezed", "Generate class definitions with @freezed compatibility", false, - "secondary", + "secondary" ), useHive: new BooleanOption("use-hive", "Generate annotations for Hive type adapters", false, "secondary"), useJsonAnnotation: new BooleanOption( "use-json-annotation", "Generate annotations for json_serializable", false, - "secondary", + "secondary" ), - partName: new StringOption("part-name", "Use this name in `part` directive", "NAME", "", "secondary"), + partName: new StringOption("part-name", "Use this name in `part` directive", "NAME", "", "secondary") }; export class DartTargetLanguage extends TargetLanguage { - constructor () { + public constructor() { super("Dart", ["dart"], "dart"); } - protected getOptions (): Array> { + protected getOptions(): Array> { return [ dartOptions.nullSafety, dartOptions.justTypes, @@ -84,22 +82,22 @@ export class DartTargetLanguage extends TargetLanguage { dartOptions.useFreezed, dartOptions.useHive, dartOptions.useJsonAnnotation, - dartOptions.partName, + dartOptions.partName ]; } - get supportsUnionsWithBothNumberTypes (): boolean { + public get supportsUnionsWithBothNumberTypes(): boolean { return true; } - get stringTypeMapping (): StringTypeMapping { + public get stringTypeMapping(): StringTypeMapping { const mapping: Map = new Map(); mapping.set("date", "date"); mapping.set("date-time", "date-time"); return mapping; } - protected makeRenderer (renderContext: RenderContext, untypedOptionValues: { [name: string]: any, }): DartRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): DartRenderer { const options = getOptionValues(dartOptions, untypedOptionValues); return new DartRenderer(this, renderContext, options); } @@ -174,7 +172,7 @@ const keywords = [ "fromJson", "toJson", "fromMap", - "toMap", + "toMap" ]; const typeNamingFunction = funPrefixNamer("types", n => dartNameStyle(true, false, n)); @@ -183,16 +181,16 @@ const enumCaseNamingFunction = funPrefixNamer("enum-cases", n => dartNameStyle(t // Escape the dollar sign, which is used in string interpolation const stringEscape = utf16ConcatMap( - escapeNonPrintableMapper(cp => isPrintable(cp) && cp !== 0x24, standardUnicodeHexEscape), + escapeNonPrintableMapper(cp => isPrintable(cp) && cp !== 0x24, standardUnicodeHexEscape) ); -function isStartCharacter (codePoint: number): boolean { +function isStartCharacter(codePoint: number): boolean { if (codePoint === 0x5f) return false; // underscore return isAscii(codePoint) && isLetter(codePoint); } -function isPartCharacter (codePoint: number): boolean { - return isStartCharacter(codePoint) || isAscii(codePoint) && isDigit(codePoint); +function isPartCharacter(codePoint: number): boolean { + return isStartCharacter(codePoint) || (isAscii(codePoint) && isDigit(codePoint)); } const legalizeName = utf16LegalizeCharacters(isPartCharacter); @@ -201,13 +199,13 @@ const legalizeName = utf16LegalizeCharacters(isPartCharacter); // we have to use namers to produce the getter and setter names - we can't // just capitalize and concatenate. // https://stackoverflow.com/questions/8277355/naming-convention-for-upper-case-abbreviations -function dartNameStyle (startWithUpper: boolean, upperUnderscore: boolean, original: string): string { +function dartNameStyle(startWithUpper: boolean, upperUnderscore: boolean, original: string): string { const words = splitIntoWords(original); const firstWordStyle = upperUnderscore ? allUpperWordStyle : startWithUpper - ? firstUpperWordStyle - : allLowerWordStyle; + ? firstUpperWordStyle + : allLowerWordStyle; const restWordStyle = upperUnderscore ? allUpperWordStyle : firstUpperWordStyle; return combineWords( words, @@ -217,7 +215,7 @@ function dartNameStyle (startWithUpper: boolean, upperUnderscore: boolean, origi firstWordStyle, restWordStyle, upperUnderscore ? "_" : "", - isStartCharacter, + isStartCharacter ); } @@ -239,104 +237,104 @@ export class DartRenderer extends ConvenienceRenderer { private readonly _enumValues = new Map(); - constructor ( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues, + private readonly _options: OptionValues ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace (): string[] { + protected forbiddenNamesForGlobalNamespace(): string[] { return keywords; } - protected forbiddenForObjectProperties (_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected makeNamedTypeNamer (): Namer { + protected makeNamedTypeNamer(): Namer { return typeNamingFunction; } - protected namerForObjectProperty (): Namer { + protected namerForObjectProperty(): Namer { return propertyNamingFunction; } - protected makeUnionMemberNamer (): Namer { + protected makeUnionMemberNamer(): Namer { return propertyNamingFunction; } - protected makeEnumCaseNamer (): Namer { + protected makeEnumCaseNamer(): Namer { return enumCaseNamingFunction; } - protected unionNeedsName (u: UnionType): boolean { + protected unionNeedsName(u: UnionType): boolean { return nullableFromUnion(u) === null; } - protected namedTypeToNameForTopLevel (type: Type): Type | undefined { + protected namedTypeToNameForTopLevel(type: Type): Type | undefined { // If the top-level type doesn't contain any classes or unions // we have to define a class just for the `FromJson` method, in // emitFromJsonForTopLevel. return directlyReachableSingleNamedType(type); } - protected get toJson (): string { + protected get toJson(): string { return `to${this._options.methodNamesWithMap ? "Map" : "Json"}`; } - protected get fromJson (): string { + protected get fromJson(): string { return `from${this._options.methodNamesWithMap ? "Map" : "Json"}`; } - protected makeTopLevelDependencyNames (_t: Type, name: Name): DependencyName[] { + protected makeTopLevelDependencyNames(_t: Type, name: Name): DependencyName[] { const encoder = new DependencyName( propertyNamingFunction, name.order, - lookup => `${lookup(name)}_${this.toJson}`, + lookup => `${lookup(name)}_${this.toJson}` ); const decoder = new DependencyName( propertyNamingFunction, name.order, - lookup => `${lookup(name)}_${this.fromJson}`, + lookup => `${lookup(name)}_${this.fromJson}` ); this._topLevelDependents.set(name, { encoder, decoder }); return [encoder, decoder]; } - protected makeNamesForPropertyGetterAndSetter ( + protected makeNamesForPropertyGetterAndSetter( _c: ClassType, _className: Name, _p: ClassProperty, _jsonName: string, - name: Name, + name: Name ): [Name, Name] { const getterName = new DependencyName(propertyNamingFunction, name.order, lookup => `get_${lookup(name)}`); const setterName = new DependencyName(propertyNamingFunction, name.order, lookup => `set_${lookup(name)}`); return [getterName, setterName]; } - protected makePropertyDependencyNames ( + protected makePropertyDependencyNames( c: ClassType, className: Name, p: ClassProperty, jsonName: string, - name: Name, + name: Name ): Name[] { const getterAndSetterNames = this.makeNamesForPropertyGetterAndSetter(c, className, p, jsonName, name); this._gettersAndSettersForPropertyName.set(name, getterAndSetterNames); return getterAndSetterNames; } - protected makeNamedTypeDependencyNames (t: Type, name: Name): DependencyName[] { + protected makeNamedTypeDependencyNames(t: Type, name: Name): DependencyName[] { if (!(t instanceof EnumType)) return []; const enumValue = new DependencyName(propertyNamingFunction, name.order, lookup => `${lookup(name)}_values`); this._enumValues.set(t, enumValue); return [enumValue]; } - protected emitFileHeader (): void { + protected emitFileHeader(): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } @@ -377,7 +375,7 @@ export class DartRenderer extends ConvenienceRenderer { // FIXME: This should use a `Name`, not `modifySource` const name = modifySource( snakeCase, - optionNameIsEmpty ? [...this.topLevels.keys()][0] : this._options.partName, + optionNameIsEmpty ? [...this.topLevels.keys()][0] : this._options.partName ); if (this._options.useFreezed) { this.emitLine("part '", name, ".freezed.dart';"); @@ -389,20 +387,20 @@ export class DartRenderer extends ConvenienceRenderer { } } - protected emitDescriptionBlock (lines: Sourcelike[]): void { + protected emitDescriptionBlock(lines: Sourcelike[]): void { this.emitCommentLines(lines, { lineStart: "///", beforeComment: "" }); } - protected emitBlock (line: Sourcelike, f: () => void): void { + protected emitBlock(line: Sourcelike, f: () => void): void { this.emitLine(line, " {"); this.indent(f); this.emitLine("}"); } - protected dartType (t: Type, withIssues = false, forceNullable = false): Sourcelike { + protected dartType(t: Type, withIssues = false, forceNullable = false): Sourcelike { const nullable = - forceNullable || this._options.nullSafety && t.isNullable && !this._options.requiredProperties; - const withNullable = (s: Sourcelike): Sourcelike => nullable ? [s, "?"] : s; + forceNullable || (this._options.nullSafety && t.isNullable && !this._options.requiredProperties); + const withNullable = (s: Sourcelike): Sourcelike => (nullable ? [s, "?"] : s); return matchType( t, _anyType => maybeAnnotated(withIssues, anyTypeIssueAnnotation, "dynamic"), @@ -431,11 +429,11 @@ export class DartRenderer extends ConvenienceRenderer { default: return withNullable("String"); } - }, + } ); } - protected mapList (isNullable: boolean, itemType: Sourcelike, list: Sourcelike, mapper: Sourcelike): Sourcelike { + protected mapList(isNullable: boolean, itemType: Sourcelike, list: Sourcelike, mapper: Sourcelike): Sourcelike { if (this._options.nullSafety && isNullable && !this._options.requiredProperties) { return [list, " == null ? [] : ", "List<", itemType, ">.from(", list, "!.map((x) => ", mapper, "))"]; } @@ -443,7 +441,7 @@ export class DartRenderer extends ConvenienceRenderer { return ["List<", itemType, ">.from(", list, ".map((x) => ", mapper, "))"]; } - protected mapMap (isNullable: boolean, valueType: Sourcelike, map: Sourcelike, valueMapper: Sourcelike): Sourcelike { + protected mapMap(isNullable: boolean, valueType: Sourcelike, map: Sourcelike, valueMapper: Sourcelike): Sourcelike { if (this._options.nullSafety && isNullable && !this._options.requiredProperties) { return ["Map.from(", map, "!).map((k, v) => MapEntry(k, ", valueMapper, "))"]; } @@ -451,7 +449,7 @@ export class DartRenderer extends ConvenienceRenderer { return ["Map.from(", map, ").map((k, v) => MapEntry(k, ", valueMapper, "))"]; } - protected mapClass (isNullable: boolean, classType: ClassType, dynamic: Sourcelike) { + protected mapClass(isNullable: boolean, classType: ClassType, dynamic: Sourcelike) { if (this._options.nullSafety && isNullable && !this._options.requiredProperties) { return [ dynamic, @@ -461,7 +459,7 @@ export class DartRenderer extends ConvenienceRenderer { this.fromJson, "(", dynamic, - ")", + ")" ]; } @@ -471,7 +469,7 @@ export class DartRenderer extends ConvenienceRenderer { // If the first time is the unionType type, after nullableFromUnion conversion, // the isNullable property will become false, which is obviously wrong, // so add isNullable property - protected fromDynamicExpression (isNullable: boolean = false, t: Type, ...dynamic: Sourcelike[]): Sourcelike { + protected fromDynamicExpression(isNullable: boolean = false, t: Type, ...dynamic: Sourcelike[]): Sourcelike { return matchType( t, _anyType => dynamic, @@ -485,7 +483,7 @@ export class DartRenderer extends ConvenienceRenderer { isNullable || arrayType.isNullable, this.dartType(arrayType.items), dynamic, - this.fromDynamicExpression(arrayType.items.isNullable, arrayType.items, "x"), + this.fromDynamicExpression(arrayType.items.isNullable, arrayType.items, "x") ), classType => this.mapClass(isNullable || classType.isNullable, classType, dynamic), mapType => @@ -493,14 +491,14 @@ export class DartRenderer extends ConvenienceRenderer { mapType.isNullable || isNullable, this.dartType(mapType.values), dynamic, - this.fromDynamicExpression(mapType.values.isNullable, mapType.values, "v"), + this.fromDynamicExpression(mapType.values.isNullable, mapType.values, "v") ), enumType => { return [ defined(this._enumValues.get(enumType)), ".map[", dynamic, - this._options.nullSafety ? "]!" : "]", + this._options.nullSafety ? "]!" : "]" ]; }, unionType => { @@ -527,14 +525,14 @@ export class DartRenderer extends ConvenienceRenderer { default: return dynamic; } - }, + } ); } // If the first time is the unionType type, after nullableFromUnion conversion, // the isNullable property will become false, which is obviously wrong, // so add isNullable property - protected toDynamicExpression (isNullable: boolean = false, t: Type, ...dynamic: Sourcelike[]): Sourcelike { + protected toDynamicExpression(isNullable: boolean = false, t: Type, ...dynamic: Sourcelike[]): Sourcelike { return matchType( t, _anyType => dynamic, @@ -548,7 +546,7 @@ export class DartRenderer extends ConvenienceRenderer { arrayType.isNullable || isNullable, "dynamic", dynamic, - this.toDynamicExpression(arrayType.items.isNullable, arrayType.items, "x"), + this.toDynamicExpression(arrayType.items.isNullable, arrayType.items, "x") ), _classType => { if ( @@ -566,7 +564,7 @@ export class DartRenderer extends ConvenienceRenderer { mapType.isNullable || isNullable, "dynamic", dynamic, - this.toDynamicExpression(mapType.values.isNullable, mapType.values, "v"), + this.toDynamicExpression(mapType.values.isNullable, mapType.values, "v") ), enumType => { return [defined(this._enumValues.get(enumType)), ".reverse[", dynamic, "]"]; @@ -598,45 +596,45 @@ export class DartRenderer extends ConvenienceRenderer { (transformedStringType.isNullable || isNullable) ) { return [ - "\"${", + '"${', dynamic, "!.year.toString().padLeft(4, '0')", "}-${", dynamic, "!.month.toString().padLeft(2, '0')}-${", dynamic, - "!.day.toString().padLeft(2, '0')}\"", + "!.day.toString().padLeft(2, '0')}\"" ]; } return [ - "\"${", + '"${', dynamic, ".year.toString().padLeft(4, '0')", "}-${", dynamic, ".month.toString().padLeft(2, '0')}-${", dynamic, - ".day.toString().padLeft(2, '0')}\"", + ".day.toString().padLeft(2, '0')}\"" ]; default: return dynamic; } - }, + } ); } - private _emitEmptyConstructor (className: Name): void { + private _emitEmptyConstructor(className: Name): void { this.emitLine(className, "();"); } - private _emitConstructor (c: ClassType, className: Name): void { + private _emitConstructor(c: ClassType, className: Name): void { this.emitLine(className, "({"); this.indent(() => { this.forEachClassProperty(c, "none", (name, _, prop) => { const required = this._options.requiredProperties || - this._options.nullSafety && (!prop.type.isNullable || !prop.isOptional); + (this._options.nullSafety && (!prop.type.isNullable || !prop.isOptional)); this.emitLine(required ? "required " : "", "this.", name, ","); }); }); @@ -644,7 +642,7 @@ export class DartRenderer extends ConvenienceRenderer { this.ensureBlankLine(); } - private _emitVariables (c: ClassType): void { + private _emitVariables(c: ClassType): void { this.forEachClassProperty(c, "none", (name, jsonName, p) => { const description = this.descriptionForClassProperty(c, jsonName); if (description !== undefined) { @@ -665,7 +663,7 @@ export class DartRenderer extends ConvenienceRenderer { }); } - private _emitCopyConstructor (c: ClassType, className: Name): void { + private _emitCopyConstructor(c: ClassType, className: Name): void { this.ensureBlankLine(); this.emitLine(className, " copyWith({"); this.indent(() => { @@ -685,7 +683,7 @@ export class DartRenderer extends ConvenienceRenderer { }); } - private _emitStringJsonEncoderDecoder (className: Name): void { + private _emitStringJsonEncoderDecoder(className: Name): void { this.ensureBlankLine(); this.emitLine( "factory ", @@ -696,7 +694,7 @@ export class DartRenderer extends ConvenienceRenderer { className, ".", this.fromJson, - "(json.decode(str));", + "(json.decode(str));" ); this.ensureBlankLine(); @@ -705,11 +703,11 @@ export class DartRenderer extends ConvenienceRenderer { this._options.methodNamesWithMap ? "toJson() => " : "toRawJson() => ", "json.encode(", this.toJson, - "());", + "());" ); } - private _emitMapEncoderDecoder (c: ClassType, className: Name): void { + private _emitMapEncoderDecoder(c: ClassType, className: Name): void { this.ensureBlankLine(); this.emitLine("factory ", className, ".", this.fromJson, "(Map json) => ", className, "("); this.indent(() => { @@ -720,11 +718,11 @@ export class DartRenderer extends ConvenienceRenderer { this.fromDynamicExpression( property.type.isNullable, property.type, - "json[\"", + 'json["', stringEscape(jsonName), - "\"]", + '"]' ), - ",", + "," ); }); }); @@ -736,18 +734,18 @@ export class DartRenderer extends ConvenienceRenderer { this.indent(() => { this.forEachClassProperty(c, "none", (name, jsonName, property) => { this.emitLine( - "\"", + '"', stringEscape(jsonName), - "\": ", + '": ', this.toDynamicExpression(property.type.isNullable, property.type, name), - ",", + "," ); }); }); this.emitLine("};"); } - protected emitClassDefinition (c: ClassType, className: Name): void { + protected emitClassDefinition(c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); if (this._options.useHive) { this.classCounter++; @@ -781,7 +779,7 @@ export class DartRenderer extends ConvenienceRenderer { ".fromJson(Map json) => ", "_$", className, - "FromJson(json);", + "FromJson(json);" ); this.ensureBlankLine(); @@ -790,7 +788,7 @@ export class DartRenderer extends ConvenienceRenderer { "Map toJson() => ", "_$", className, - "ToJson(this);", + "ToJson(this);" ); } else { if (this._options.justTypes) return; @@ -804,7 +802,7 @@ export class DartRenderer extends ConvenienceRenderer { }); } - protected emitFreezedClassDefinition (c: ClassType, className: Name): void { + protected emitFreezedClassDefinition(c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); this.emitLine("@freezed"); @@ -822,7 +820,7 @@ export class DartRenderer extends ConvenienceRenderer { const required = this._options.requiredProperties || - this._options.nullSafety && (!prop.type.isNullable || !prop.isOptional); + (this._options.nullSafety && (!prop.type.isNullable || !prop.isOptional)); if (this._options.useJsonAnnotation) { this.classPropertyCounter++; this.emitLine(`@JsonKey(name: "${jsonName}")`); @@ -844,19 +842,19 @@ export class DartRenderer extends ConvenienceRenderer { ".fromJson(Map json) => ", "_$", className, - "FromJson(json);", + "FromJson(json);" ); }); } - protected emitEnumDefinition (e: EnumType, enumName: Name): void { + protected emitEnumDefinition(e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); this.emitLine("enum ", enumName, " {"); this.indent(() => { this.forEachEnumCase(e, "none", (name, jsonName, pos) => { const comma = pos === "first" || pos === "middle" ? "," : []; if (this._options.useJsonAnnotation) { - this.emitLine("@JsonValue(\"", stringEscape(jsonName), "\")"); + this.emitLine('@JsonValue("', stringEscape(jsonName), '")'); } this.emitLine(name, comma); @@ -871,7 +869,7 @@ export class DartRenderer extends ConvenienceRenderer { this.indent(() => { this.forEachEnumCase(e, "none", (name, jsonName, pos) => { const comma = pos === "first" || pos === "middle" ? "," : []; - this.emitLine("\"", stringEscape(jsonName), "\": ", enumName, ".", name, comma); + this.emitLine('"', stringEscape(jsonName), '": ', enumName, ".", name, comma); }); }); this.emitLine("});"); @@ -879,7 +877,7 @@ export class DartRenderer extends ConvenienceRenderer { this._needEnumValues = true; } - protected emitEnumValues (): void { + protected emitEnumValues(): void { this.ensureBlankLine(); this.emitMultiline(`class EnumValues { Map map; @@ -894,7 +892,7 @@ export class DartRenderer extends ConvenienceRenderer { }`); } - private _emitTopLvlEncoderDecoder (): void { + private _emitTopLvlEncoderDecoder(): void { this.forEachTopLevel("leading-and-interposing", (t, name) => { const { encoder, decoder } = defined(this._topLevelDependents.get(name)); @@ -904,7 +902,7 @@ export class DartRenderer extends ConvenienceRenderer { decoder, "(String str) => ", this.fromDynamicExpression(t.isNullable, t, "json.decode(str)"), - ";", + ";" ); this.ensureBlankLine(); @@ -916,7 +914,7 @@ export class DartRenderer extends ConvenienceRenderer { this.dartType(t), " data) => json.encode(", this.toDynamicExpression(t.isNullable, t, "data"), - ");", + ");" ); // this.emitBlock(["String ", encoder, "(", this.dartType(t), " data)"], () => { @@ -925,7 +923,7 @@ export class DartRenderer extends ConvenienceRenderer { }); } - protected emitSourceStructure (): void { + protected emitSourceStructure(): void { this.emitFileHeader(); if (!this._options.justTypes && !this._options.codersInClass) { @@ -939,7 +937,7 @@ export class DartRenderer extends ConvenienceRenderer { (e, n) => this.emitEnumDefinition(e, n), (_e, _n) => { // We don't support this yet. - }, + } ); if (this._needEnumValues) { diff --git a/packages/quicktype-core/src/language/Elm.ts b/packages/quicktype-core/src/language/Elm.ts index 01fa4f807..a9c81776e 100644 --- a/packages/quicktype-core/src/language/Elm.ts +++ b/packages/quicktype-core/src/language/Elm.ts @@ -8,7 +8,7 @@ import { UnionType } from "../Type"; import { matchType, nullableFromUnion } from "../TypeUtils"; import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Namer, type Name} from "../Naming"; +import { type Namer, type Name } from "../Naming"; import { DependencyName, funPrefixNamer } from "../Naming"; import { legalizeCharacters, @@ -21,10 +21,10 @@ import { combineWords, firstUpperWordStyle, allLowerWordStyle, - allUpperWordStyle, + allUpperWordStyle } from "../support/Strings"; import { defined } from "../support/Support"; -import { type Sourcelike, type MultiWord} from "../Source"; +import { type Sourcelike, type MultiWord } from "../Source"; import { annotated, singleWord, multiWord, parenIfNeeded } from "../Source"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; import { type RenderContext } from "../Renderer"; @@ -33,30 +33,30 @@ export const elmOptions = { justTypes: new BooleanOption("just-types", "Plain types only", false), useList: new EnumOption("array-type", "Use Array or List", [ ["array", false], - ["list", true], + ["list", true] ]), // FIXME: Do this via a configurable named eventually. - moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType"), + moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType") }; export class ElmTargetLanguage extends TargetLanguage { - constructor () { + public constructor() { super("Elm", ["elm"], "elm"); } - protected getOptions (): Array> { + protected getOptions(): Array> { return [elmOptions.justTypes, elmOptions.moduleName, elmOptions.useList]; } - get supportsOptionalClassProperties (): boolean { + public get supportsOptionalClassProperties(): boolean { return true; } - get supportsUnionsWithBothNumberTypes (): boolean { + public get supportsUnionsWithBothNumberTypes(): boolean { return true; } - protected makeRenderer (renderContext: RenderContext, untypedOptionValues: { [name: string]: any, }): ElmRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): ElmRenderer { return new ElmRenderer(this, renderContext, getOptionValues(elmOptions, untypedOptionValues)); } } @@ -99,12 +99,12 @@ const forbiddenNames = [ "True", "False", "String", - "Float", + "Float" ]; const legalizeName = legalizeCharacters(cp => isAscii(cp) && isLetterOrUnderscoreOrDigit(cp)); -function elmNameStyle (original: string, upper: boolean): string { +function elmNameStyle(original: string, upper: boolean): string { const words = splitIntoWords(original); return combineWords( words, @@ -114,7 +114,7 @@ function elmNameStyle (original: string, upper: boolean): string { upper ? allUpperWordStyle : allLowerWordStyle, allUpperWordStyle, "", - isLetterOrUnderscore, + isLetterOrUnderscore ); } @@ -126,13 +126,13 @@ interface RequiredOrOptional { reqOrOpt: string; } -function requiredOrOptional (p: ClassProperty): RequiredOrOptional { - function optional (fallback: string): RequiredOrOptional { +function requiredOrOptional(p: ClassProperty): RequiredOrOptional { + function optional(fallback: string): RequiredOrOptional { return { reqOrOpt: "Jpipe.optional", fallback }; } const t = p.type; - if (p.isOptional || t instanceof UnionType && nullableFromUnion(t) !== null) { + if (p.isOptional || (t instanceof UnionType && nullableFromUnion(t) !== null)) { return optional(" Nothing"); } @@ -158,23 +158,23 @@ export class ElmRenderer extends ConvenienceRenderer { private readonly _namedTypeDependents = new Map(); - constructor ( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues, + private readonly _options: OptionValues ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace (): string[] { + protected forbiddenNamesForGlobalNamespace(): string[] { return forbiddenNames; } - protected makeTopLevelDependencyNames (t: Type, topLevelName: Name): DependencyName[] { + protected makeTopLevelDependencyNames(t: Type, topLevelName: Name): DependencyName[] { const encoder = new DependencyName( lowerNamingFunction, topLevelName.order, - lookup => `${lookup(topLevelName)}_to_string`, + lookup => `${lookup(topLevelName)}_to_string` ); let decoder: DependencyName | undefined = undefined; if (this.namedTypeToNameForTopLevel(t) === undefined) { @@ -189,56 +189,56 @@ export class ElmRenderer extends ConvenienceRenderer { return [encoder]; } - protected makeNamedTypeNamer (): Namer { + protected makeNamedTypeNamer(): Namer { return upperNamingFunction; } - protected makeNamedTypeDependencyNames (_: Type, typeName: Name): DependencyName[] { + protected makeNamedTypeDependencyNames(_: Type, typeName: Name): DependencyName[] { const encoder = new DependencyName(lowerNamingFunction, typeName.order, lookup => `encode_${lookup(typeName)}`); const decoder = new DependencyName(lowerNamingFunction, typeName.order, lookup => lookup(typeName)); this._namedTypeDependents.set(typeName, { encoder, decoder }); return [encoder, decoder]; } - protected namerForObjectProperty (): Namer { + protected namerForObjectProperty(): Namer { return lowerNamingFunction; } - protected forbiddenForObjectProperties (_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected makeUnionMemberNamer (): Namer { + protected makeUnionMemberNamer(): Namer { return upperNamingFunction; } - protected get unionMembersInGlobalNamespace (): boolean { + protected get unionMembersInGlobalNamespace(): boolean { return true; } - protected makeEnumCaseNamer (): Namer { + protected makeEnumCaseNamer(): Namer { return upperNamingFunction; } - protected get enumCasesInGlobalNamespace (): boolean { + protected get enumCasesInGlobalNamespace(): boolean { return true; } - protected proposeUnionMemberName ( + protected proposeUnionMemberName( u: UnionType, unionName: Name, fieldType: Type, - lookup: (n: Name) => string, + lookup: (n: Name) => string ): string { const fieldName = super.proposeUnionMemberName(u, unionName, fieldType, lookup); return `${fieldName}_in_${lookup(unionName)}`; } - protected get commentLineStart (): string { + protected get commentLineStart(): string { return "-- "; } - protected emitDescriptionBlock (lines: Sourcelike[]): void { + protected emitDescriptionBlock(lines: Sourcelike[]): void { if (lines.length === 1) { this.emitComments([{ customLines: lines, lineStart: "{-| ", lineEnd: " -}" }]); } else { @@ -246,11 +246,11 @@ export class ElmRenderer extends ConvenienceRenderer { } } - private get arrayType (): string { + private get arrayType(): string { return this._options.useList ? "List" : "Array"; } - private elmType (t: Type, noOptional = false): MultiWord { + private elmType(t: Type, noOptional = false): MultiWord { return matchType( t, _anyType => singleWord(annotated(anyTypeIssueAnnotation, "Jdec.Value")), @@ -272,11 +272,11 @@ export class ElmRenderer extends ConvenienceRenderer { } return singleWord(this.nameForNamedType(unionType)); - }, + } ); } - private elmProperty (p: ClassProperty): Sourcelike { + private elmProperty(p: ClassProperty): Sourcelike { if (p.isOptional) { return multiWord(" ", "Maybe", parenIfNeeded(this.elmType(p.type, true))).source; } else { @@ -284,12 +284,12 @@ export class ElmRenderer extends ConvenienceRenderer { } } - private decoderNameForNamedType (t: Type): Name { + private decoderNameForNamedType(t: Type): Name { const name = this.nameForNamedType(t); return defined(this._namedTypeDependents.get(name)).decoder; } - private decoderNameForType (t: Type, noOptional = false): MultiWord { + private decoderNameForType(t: Type, noOptional = false): MultiWord { return matchType( t, _anyType => singleWord("Jdec.value"), @@ -302,7 +302,7 @@ export class ElmRenderer extends ConvenienceRenderer { multiWord( " ", ["Jdec.", decapitalize(this.arrayType)], - parenIfNeeded(this.decoderNameForType(arrayType.items)), + parenIfNeeded(this.decoderNameForType(arrayType.items)) ), classType => singleWord(this.decoderNameForNamedType(classType)), mapType => multiWord(" ", "Jdec.dict", parenIfNeeded(this.decoderNameForType(mapType.values))), @@ -316,11 +316,11 @@ export class ElmRenderer extends ConvenienceRenderer { } return singleWord(this.decoderNameForNamedType(unionType)); - }, + } ); } - private decoderNameForProperty (p: ClassProperty): MultiWord { + private decoderNameForProperty(p: ClassProperty): MultiWord { if (p.isOptional) { return multiWord(" ", "Jdec.nullable", parenIfNeeded(this.decoderNameForType(p.type, true))); } else { @@ -328,12 +328,12 @@ export class ElmRenderer extends ConvenienceRenderer { } } - private encoderNameForNamedType (t: Type): Name { + private encoderNameForNamedType(t: Type): Name { const name = this.nameForNamedType(t); return defined(this._namedTypeDependents.get(name)).encoder; } - private encoderNameForType (t: Type, noOptional = false): MultiWord { + private encoderNameForType(t: Type, noOptional = false): MultiWord { return matchType( t, _anyType => singleWord("identity"), @@ -346,7 +346,7 @@ export class ElmRenderer extends ConvenienceRenderer { multiWord( " ", ["make", this.arrayType, "Encoder"], - parenIfNeeded(this.encoderNameForType(arrayType.items)), + parenIfNeeded(this.encoderNameForType(arrayType.items)) ), classType => singleWord(this.encoderNameForNamedType(classType)), mapType => multiWord(" ", "makeDictEncoder", parenIfNeeded(this.encoderNameForType(mapType.values))), @@ -360,11 +360,11 @@ export class ElmRenderer extends ConvenienceRenderer { } return singleWord(this.encoderNameForNamedType(unionType)); - }, + } ); } - private encoderNameForProperty (p: ClassProperty): MultiWord { + private encoderNameForProperty(p: ClassProperty): MultiWord { if (p.isOptional) { return multiWord(" ", "makeNullableEncoder", parenIfNeeded(this.encoderNameForType(p.type, true))); } else { @@ -372,11 +372,11 @@ export class ElmRenderer extends ConvenienceRenderer { } } - private emitTopLevelDefinition (t: Type, topLevelName: Name): void { + private emitTopLevelDefinition(t: Type, topLevelName: Name): void { this.emitLine("type alias ", topLevelName, " = ", this.elmType(t).source); } - private emitClassDefinition (c: ClassType, className: Name): void { + private emitClassDefinition(c: ClassType, className: Name): void { let description = this.descriptionForType(c); this.forEachClassProperty(c, "none", (name, jsonName) => { const propertyDescription = this.descriptionForClassProperty(c, jsonName); @@ -408,7 +408,7 @@ export class ElmRenderer extends ConvenienceRenderer { }); } - private emitEnumDefinition (e: EnumType, enumName: Name): void { + private emitEnumDefinition(e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); this.emitLine("type ", enumName); this.indent(() => { @@ -421,7 +421,7 @@ export class ElmRenderer extends ConvenienceRenderer { }); } - private emitUnionDefinition (u: UnionType, unionName: Name): void { + private emitUnionDefinition(u: UnionType, unionName: Name): void { this.emitDescription(this.descriptionForType(u)); this.emitLine("type ", unionName); this.indent(() => { @@ -439,7 +439,7 @@ export class ElmRenderer extends ConvenienceRenderer { }); } - private emitTopLevelFunctions (t: Type, topLevelName: Name): void { + private emitTopLevelFunctions(t: Type, topLevelName: Name): void { const { encoder, decoder } = defined(this._topLevelDependents.get(topLevelName)); if (this.namedTypeToNameForTopLevel(t) === undefined) { this.emitLine(defined(decoder), " : Jdec.Decoder ", topLevelName); @@ -451,7 +451,7 @@ export class ElmRenderer extends ConvenienceRenderer { this.emitLine(encoder, " r = Jenc.encode 0 (", this.encoderNameForType(t).source, " r)"); } - private emitClassFunctions (c: ClassType, className: Name): void { + private emitClassFunctions(c: ClassType, className: Name): void { const decoderName = this.decoderNameForNamedType(c); this.emitLine(decoderName, " : Jdec.Decoder ", className); this.emitLine(decoderName, " ="); @@ -461,7 +461,7 @@ export class ElmRenderer extends ConvenienceRenderer { this.forEachClassProperty(c, "none", (_, jsonName, p) => { const propDecoder = parenIfNeeded(this.decoderNameForProperty(p)); const { reqOrOpt, fallback } = requiredOrOptional(p); - this.emitLine("|> ", reqOrOpt, " \"", stringEscape(jsonName), "\" ", propDecoder, fallback); + this.emitLine("|> ", reqOrOpt, ' "', stringEscape(jsonName), '" ', propDecoder, fallback); }); }); }); @@ -477,7 +477,7 @@ export class ElmRenderer extends ConvenienceRenderer { this.forEachClassProperty(c, "none", (name, jsonName, p) => { const bracketOrComma = onFirst ? "[" : ","; const propEncoder = this.encoderNameForProperty(p).source; - this.emitLine(bracketOrComma, " (\"", stringEscape(jsonName), "\", ", propEncoder, " x.", name, ")"); + this.emitLine(bracketOrComma, ' ("', stringEscape(jsonName), '", ', propEncoder, " x.", name, ")"); onFirst = false; }); if (onFirst) { @@ -489,7 +489,7 @@ export class ElmRenderer extends ConvenienceRenderer { }); } - private emitEnumFunctions (e: EnumType, enumName: Name): void { + private emitEnumFunctions(e: EnumType, enumName: Name): void { const decoderName = this.decoderNameForNamedType(e); this.emitLine(decoderName, " : Jdec.Decoder ", enumName); this.emitLine(decoderName, " ="); @@ -501,9 +501,9 @@ export class ElmRenderer extends ConvenienceRenderer { this.emitLine("case str of"); this.indent(() => { this.forEachEnumCase(e, "none", (name, jsonName) => { - this.emitLine("\"", stringEscape(jsonName), "\" -> Jdec.succeed ", name); + this.emitLine('"', stringEscape(jsonName), '" -> Jdec.succeed ', name); }); - this.emitLine("somethingElse -> Jdec.fail <| \"Invalid ", enumName, ": \" ++ somethingElse"); + this.emitLine('somethingElse -> Jdec.fail <| "Invalid ', enumName, ': " ++ somethingElse'); }); }); this.emitLine(")"); @@ -516,14 +516,14 @@ export class ElmRenderer extends ConvenienceRenderer { this.emitLine(encoderName, " x = case x of"); this.indent(() => { this.forEachEnumCase(e, "none", (name, jsonName) => { - this.emitLine(name, " -> Jenc.string \"", stringEscape(jsonName), "\""); + this.emitLine(name, ' -> Jenc.string "', stringEscape(jsonName), '"'); }); }); } - private emitUnionFunctions (u: UnionType, unionName: Name): void { + private emitUnionFunctions(u: UnionType, unionName: Name): void { // We need arrays first, then strings, and integers before doubles. - function sortOrder (_: Name, t: Type): string { + function sortOrder(_: Name, t: Type): string { if (t.kind === "array") { return " array"; } else if (t.kind === "double") { @@ -573,7 +573,7 @@ export class ElmRenderer extends ConvenienceRenderer { }); } - protected emitSourceStructure (): void { + protected emitSourceStructure(): void { const exports: Sourcelike[] = []; const topLevelDecoders: Sourcelike[] = []; this.forEachTopLevel("none", (_, name) => { @@ -605,14 +605,14 @@ export class ElmRenderer extends ConvenienceRenderer { "", "add these imports", "", - " import Json.Decode exposing (decodeString)`);", + " import Json.Decode exposing (decodeString)`);" ]); this.emitLine( "-- import ", this._options.moduleName, " exposing (", arrayIntercalate(", ", topLevelDecoders), - ")", + ")" ); this.emitMultiline(`-- -- and you're off to the races with @@ -653,13 +653,13 @@ import Dict exposing (Dict, map, toList)`); this.forEachTopLevel( "leading-and-interposing", (t: Type, topLevelName: Name) => this.emitTopLevelDefinition(t, topLevelName), - t => this.namedTypeToNameForTopLevel(t) === undefined, + t => this.namedTypeToNameForTopLevel(t) === undefined ); this.forEachNamedType( "leading-and-interposing", (c: ClassType, className: Name) => this.emitClassDefinition(c, className), (e: EnumType, enumName: Name) => this.emitEnumDefinition(e, enumName), - (u: UnionType, unionName: Name) => this.emitUnionDefinition(u, unionName), + (u: UnionType, unionName: Name) => this.emitUnionDefinition(u, unionName) ); if (this._options.justTypes) return; @@ -667,13 +667,13 @@ import Dict exposing (Dict, map, toList)`); this.ensureBlankLine(); this.emitLine("-- decoders and encoders"); this.forEachTopLevel("leading-and-interposing", (t: Type, topLevelName: Name) => - this.emitTopLevelFunctions(t, topLevelName), + this.emitTopLevelFunctions(t, topLevelName) ); this.forEachNamedType( "leading-and-interposing", (c: ClassType, className: Name) => this.emitClassFunctions(c, className), (e: EnumType, enumName: Name) => this.emitEnumFunctions(e, enumName), - (u: UnionType, unionName: Name) => this.emitUnionFunctions(u, unionName), + (u: UnionType, unionName: Name) => this.emitUnionFunctions(u, unionName) ); this.ensureBlankLine(); diff --git a/packages/quicktype-core/src/language/Golang.ts b/packages/quicktype-core/src/language/Golang.ts index c41a6af26..0dd4afcb5 100644 --- a/packages/quicktype-core/src/language/Golang.ts +++ b/packages/quicktype-core/src/language/Golang.ts @@ -1,7 +1,7 @@ import { type TypeKind, type Type, type ClassType, type EnumType, type ClassProperty } from "../Type"; import { UnionType } from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { type Name, type Namer} from "../Naming"; +import { type Name, type Namer } from "../Naming"; import { DependencyName, funPrefixNamer } from "../Naming"; import { legalizeCharacters, @@ -12,12 +12,12 @@ import { combineWords, firstUpperWordStyle, allUpperWordStyle, - camelCase, + camelCase } from "../support/Strings"; import { assert, defined } from "../support/Support"; -import { type Option, type OptionValues} from "../RendererOptions"; +import { type Option, type OptionValues } from "../RendererOptions"; import { StringOption, BooleanOption, getOptionValues } from "../RendererOptions"; -import { type Sourcelike} from "../Source"; +import { type Sourcelike } from "../Source"; import { maybeAnnotated, modifySource } from "../Source"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; import { TargetLanguage } from "../TargetLanguage"; @@ -33,46 +33,46 @@ export const goOptions = { fieldTags: new StringOption("field-tags", "list of tags which should be generated for fields", "TAGS", "json"), omitEmpty: new BooleanOption( "omit-empty", - "If set, all non-required objects will be tagged with \",omitempty\"", - false, - ), + 'If set, all non-required objects will be tagged with ",omitempty"', + false + ) }; export class GoTargetLanguage extends TargetLanguage { - constructor () { + public constructor() { super("Go", ["go", "golang"], "go"); } - protected getOptions (): Array> { + protected getOptions(): Array> { return [ goOptions.justTypes, goOptions.justTypesAndPackage, goOptions.packageName, goOptions.multiFileOutput, goOptions.fieldTags, - goOptions.omitEmpty, + goOptions.omitEmpty ]; } - get supportsUnionsWithBothNumberTypes (): boolean { + public get supportsUnionsWithBothNumberTypes(): boolean { return true; } - get stringTypeMapping (): StringTypeMapping { + public get stringTypeMapping(): StringTypeMapping { const mapping: Map = new Map(); mapping.set("date-time", "date-time"); return mapping; } - get supportsOptionalClassProperties (): boolean { + public get supportsOptionalClassProperties(): boolean { return true; } - protected makeRenderer (renderContext: RenderContext, untypedOptionValues: { [name: string]: any, }): GoRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): GoRenderer { return new GoRenderer(this, renderContext, getOptionValues(goOptions, untypedOptionValues)); } - protected get defaultIndentation (): string { + protected get defaultIndentation(): string { return "\t"; } } @@ -81,7 +81,7 @@ const namingFunction = funPrefixNamer("namer", goNameStyle); const legalizeName = legalizeCharacters(isLetterOrUnderscoreOrDigit); -function goNameStyle (original: string): string { +function goNameStyle(original: string): string { const words = splitIntoWords(original); return combineWords( words, @@ -91,19 +91,19 @@ function goNameStyle (original: string): string { allUpperWordStyle, allUpperWordStyle, "", - isLetterOrUnderscore, + isLetterOrUnderscore ); } const primitiveValueTypeKinds: TypeKind[] = ["integer", "double", "bool", "string"]; const compoundTypeKinds: TypeKind[] = ["array", "class", "map", "enum"]; -function isValueType (t: Type): boolean { +function isValueType(t: Type): boolean { const kind = t.kind; return primitiveValueTypeKinds.includes(kind) || kind === "class" || kind === "enum" || kind === "date-time"; } -function canOmitEmpty (cp: ClassProperty, omitEmptyOption: boolean): boolean { +function canOmitEmpty(cp: ClassProperty, omitEmptyOption: boolean): boolean { if (!cp.isOptional) return false; if (omitEmptyOption) return true; const t = cp.type; @@ -115,46 +115,46 @@ export class GoRenderer extends ConvenienceRenderer { private _currentFilename: string | undefined; - constructor ( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues, + private readonly _options: OptionValues ) { super(targetLanguage, renderContext); } - protected makeNamedTypeNamer (): Namer { + protected makeNamedTypeNamer(): Namer { return namingFunction; } - protected namerForObjectProperty (): Namer { + protected namerForObjectProperty(): Namer { return namingFunction; } - protected makeUnionMemberNamer (): Namer { + protected makeUnionMemberNamer(): Namer { return namingFunction; } - protected makeEnumCaseNamer (): Namer { + protected makeEnumCaseNamer(): Namer { return namingFunction; } - protected get enumCasesInGlobalNamespace (): boolean { + protected get enumCasesInGlobalNamespace(): boolean { return true; } - protected makeTopLevelDependencyNames (_: Type, topLevelName: Name): DependencyName[] { + protected makeTopLevelDependencyNames(_: Type, topLevelName: Name): DependencyName[] { const unmarshalName = new DependencyName( namingFunction, topLevelName.order, - lookup => `unmarshal_${lookup(topLevelName)}`, + lookup => `unmarshal_${lookup(topLevelName)}` ); this._topLevelUnmarshalNames.set(topLevelName, unmarshalName); return [unmarshalName]; } /// startFile takes a file name, lowercases it, appends ".go" to it, and sets it as the current filename. - protected startFile (basename: Sourcelike): void { + protected startFile(basename: Sourcelike): void { if (this._options.multiFileOutput === false) { return; } @@ -165,7 +165,7 @@ export class GoRenderer extends ConvenienceRenderer { } /// endFile pushes the current file name onto the collection of finished files and then resets the current file name. These finished files are used in index.ts to write the output. - protected endFile (): void { + protected endFile(): void { if (this._options.multiFileOutput === false) { return; } @@ -174,21 +174,21 @@ export class GoRenderer extends ConvenienceRenderer { this._currentFilename = undefined; } - private emitBlock (line: Sourcelike, f: () => void): void { + private emitBlock(line: Sourcelike, f: () => void): void { this.emitLine(line, " {"); this.indent(f); this.emitLine("}"); } - private emitFunc (decl: Sourcelike, f: () => void): void { + private emitFunc(decl: Sourcelike, f: () => void): void { this.emitBlock(["func ", decl], f); } - private emitStruct (name: Name, table: Sourcelike[][]): void { + private emitStruct(name: Name, table: Sourcelike[][]): void { this.emitBlock(["type ", name, " struct"], () => this.emitTable(table)); } - private nullableGoType (t: Type, withIssues: boolean): Sourcelike { + private nullableGoType(t: Type, withIssues: boolean): Sourcelike { const goType = this.goType(t, withIssues); if (isValueType(t)) { return ["*", goType]; @@ -197,7 +197,7 @@ export class GoRenderer extends ConvenienceRenderer { } } - private propertyGoType (cp: ClassProperty): Sourcelike { + private propertyGoType(cp: ClassProperty): Sourcelike { const t = cp.type; if (t instanceof UnionType && nullableFromUnion(t) === null) { return ["*", this.goType(t, true)]; @@ -210,7 +210,7 @@ export class GoRenderer extends ConvenienceRenderer { return this.goType(t, true); } - private goType (t: Type, withIssues = false): Sourcelike { + private goType(t: Type, withIssues = false): Sourcelike { return matchType( t, _anyType => maybeAnnotated(withIssues, anyTypeIssueAnnotation, "interface{}"), @@ -244,11 +244,11 @@ export class GoRenderer extends ConvenienceRenderer { } return "string"; - }, + } ); } - private emitTopLevel (t: Type, name: Name): void { + private emitTopLevel(t: Type, name: Name): void { this.startFile(name); if ( @@ -258,7 +258,7 @@ export class GoRenderer extends ConvenienceRenderer { this.leadingComments === undefined ) { this.emitLineOnce( - "// This file was generated from JSON Schema using quicktype, do not modify it directly.", + "// This file was generated from JSON Schema using quicktype, do not modify it directly." ); this.emitLineOnce("// To parse and unparse this JSON data, add this code to your project and do:"); this.emitLineOnce("//"); @@ -289,7 +289,7 @@ export class GoRenderer extends ConvenienceRenderer { this.endFile(); } - private emitClass (c: ClassType, className: Name): void { + private emitClass(c: ClassType, className: Name): void { this.startFile(className); let columns: Sourcelike[][] = []; const usedTypes = new Set(); @@ -303,12 +303,12 @@ export class GoRenderer extends ConvenienceRenderer { docStrings.forEach(doc => columns.push([doc])); const tags = this._options.fieldTags .split(",") - .map(tag => tag + ":\"" + stringEscape(jsonName) + omitEmpty + "\"") + .map(tag => tag + ':"' + stringEscape(jsonName) + omitEmpty + '"') .join(" "); columns.push([ [name, " "], [goType, " "], - ["`", tags, "`"], + ["`", tags, "`"] ]); usedTypes.add(goType.toString()); }); @@ -317,14 +317,14 @@ export class GoRenderer extends ConvenienceRenderer { false, usedTypes.has("time.Time") || usedTypes.has("*,time.Time") || usedTypes.has("[],time.Time") ? new Set(["time"]) - : undefined, + : undefined ); this.emitDescription(this.descriptionForType(c)); this.emitStruct(className, columns); this.endFile(); } - private emitEnum (e: EnumType, enumName: Name): void { + private emitEnum(e: EnumType, enumName: Name): void { this.startFile(enumName); this.emitPackageDefinitons(false); this.emitDescription(this.descriptionForType(e)); @@ -335,7 +335,7 @@ export class GoRenderer extends ConvenienceRenderer { this.forEachEnumCase(e, "none", (name, jsonName) => { columns.push([ [name, " "], - [enumName, " = \"", stringEscape(jsonName), "\""], + [enumName, ' = "', stringEscape(jsonName), '"'] ]); }); this.indent(() => this.emitTable(columns)); @@ -343,7 +343,7 @@ export class GoRenderer extends ConvenienceRenderer { this.endFile(); } - private emitUnion (u: UnionType, unionName: Name): void { + private emitUnion(u: UnionType, unionName: Name): void { this.startFile(unionName); this.emitPackageDefinitons(false); const [hasNull, nonNulls] = removeNullFromUnion(u); @@ -367,20 +367,20 @@ export class GoRenderer extends ConvenienceRenderer { const makeArgs = ( primitiveArg: (fieldName: Sourcelike) => Sourcelike, - compoundArg: (isClass: boolean, fieldName: Sourcelike) => Sourcelike, + compoundArg: (isClass: boolean, fieldName: Sourcelike) => Sourcelike ): Sourcelike => { const args: Sourcelike = []; for (const kind of primitiveValueTypeKinds) { args.push( ifMember(kind, "nil", (_1, fieldName, _2) => primitiveArg(fieldName)), - ", ", + ", " ); } for (const kind of compoundTypeKinds) { args.push( ifMember(kind, "false, nil", (t, fieldName, _) => compoundArg(t.kind === "class", fieldName)), - ", ", + ", " ); } @@ -415,7 +415,7 @@ export class GoRenderer extends ConvenienceRenderer { } else { return ["true, &x.", fn]; } - }, + } ); this.emitLine("object, err := unmarshalUnion(data, ", args, ")"); this.emitBlock("if err != nil", () => { @@ -432,14 +432,14 @@ export class GoRenderer extends ConvenienceRenderer { this.emitFunc(["(x *", unionName, ") MarshalJSON() ([]byte, error)"], () => { const args = makeArgs( fn => ["x.", fn], - (_, fn) => ["x.", fn, " != nil, x.", fn], + (_, fn) => ["x.", fn, " != nil, x.", fn] ); this.emitLine("return marshalUnion(", args, ")"); }); this.endFile(); } - private emitSingleFileHeaderComments (): void { + private emitSingleFileHeaderComments(): void { this.emitLineOnce("// This file was generated from JSON Schema using quicktype, do not modify it directly."); this.emitLineOnce("// To parse and unparse this JSON data, add this code to your project and do:"); this.forEachTopLevel("none", (_: Type, name: Name) => { @@ -450,7 +450,7 @@ export class GoRenderer extends ConvenienceRenderer { }); } - private emitPackageDefinitons (includeJSONEncodingImport: boolean, imports: Set = new Set()): void { + private emitPackageDefinitons(includeJSONEncodingImport: boolean, imports: Set = new Set()): void { if (!this._options.justTypes || this._options.justTypesAndPackage) { this.ensureBlankLine(); const packageDeclaration = "package " + this._options.packageName; @@ -472,7 +472,7 @@ export class GoRenderer extends ConvenienceRenderer { this.emitImports(imports); } - private emitImports (imports: Set): void { + private emitImports(imports: Set): void { const sortedImports = Array.from(imports).sort((a, b) => a.localeCompare(b)); if (sortedImports.length === 0) { @@ -485,7 +485,7 @@ export class GoRenderer extends ConvenienceRenderer { this.ensureBlankLine(); } - private emitHelperFunctions (): void { + private emitHelperFunctions(): void { if (this.haveNamedUnions) { this.startFile("JSONSchemaSupport"); const imports = new Set(); @@ -614,7 +614,7 @@ func marshalUnion(pi *int64, pf *float64, pb *bool, ps *string, haveArray bool, } } - protected emitSourceStructure (): void { + protected emitSourceStructure(): void { if ( this._options.multiFileOutput === false && this._options.justTypes === false && @@ -630,7 +630,7 @@ func marshalUnion(pi *int64, pf *float64, pb *bool, ps *string, haveArray bool, (t, name) => this.emitTopLevel(t, name), t => !(this._options.justTypes || this._options.justTypesAndPackage) || - this.namedTypeToNameForTopLevel(t) === undefined, + this.namedTypeToNameForTopLevel(t) === undefined ); this.forEachObject("leading-and-interposing", (c: ClassType, className: Name) => this.emitClass(c, className)); this.forEachEnum("leading-and-interposing", (u: EnumType, enumName: Name) => this.emitEnum(u, enumName)); @@ -643,7 +643,7 @@ func marshalUnion(pi *int64, pf *float64, pb *bool, ps *string, haveArray bool, this.emitHelperFunctions(); } - private collectAllImports (): Set { + private collectAllImports(): Set { let imports = new Set(); this.forEachObject("leading-and-interposing", (c: ClassType, _className: Name) => { const classImports = this.collectClassImports(c); @@ -657,7 +657,7 @@ func marshalUnion(pi *int64, pf *float64, pb *bool, ps *string, haveArray bool, return imports; } - private collectClassImports (c: ClassType): Set { + private collectClassImports(c: ClassType): Set { const usedTypes = new Set(); const mapping: Map = new Map(); mapping.set("time.Time", "time"); @@ -680,7 +680,7 @@ func marshalUnion(pi *int64, pf *float64, pb *bool, ps *string, haveArray bool, return imports; } - private collectUnionImports (u: UnionType): Set { + private collectUnionImports(u: UnionType): Set { const usedTypes = new Set(); const mapping: Map = new Map(); mapping.set("time.Time", "time"); diff --git a/packages/quicktype-core/src/language/Haskell.ts b/packages/quicktype-core/src/language/Haskell.ts index ed13a8ee7..f33ce9927 100644 --- a/packages/quicktype-core/src/language/Haskell.ts +++ b/packages/quicktype-core/src/language/Haskell.ts @@ -6,7 +6,7 @@ import { type Type, type ClassType, type UnionType, type EnumType, type ClassPro import { matchType, nullableFromUnion } from "../TypeUtils"; import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Namer, type Name} from "../Naming"; +import { type Namer, type Name } from "../Naming"; import { funPrefixNamer } from "../Naming"; import { legalizeCharacters, @@ -18,9 +18,9 @@ import { combineWords, firstUpperWordStyle, allLowerWordStyle, - allUpperWordStyle, + allUpperWordStyle } from "../support/Strings"; -import { type Sourcelike, type MultiWord} from "../Source"; +import { type Sourcelike, type MultiWord } from "../Source"; import { singleWord, multiWord, parenIfNeeded } from "../Source"; import { type RenderContext } from "../Renderer"; @@ -28,31 +28,31 @@ export const haskellOptions = { justTypes: new BooleanOption("just-types", "Plain types only", false), useList: new EnumOption("array-type", "Use Array or List", [ ["array", false], - ["list", true], + ["list", true] ]), - moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType"), + moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType") }; export class HaskellTargetLanguage extends TargetLanguage { - constructor () { + public constructor() { super("Haskell", ["haskell"], "haskell"); } - protected getOptions (): Array> { + protected getOptions(): Array> { return [haskellOptions.justTypes, haskellOptions.moduleName, haskellOptions.useList]; } - get supportsOptionalClassProperties (): boolean { + public get supportsOptionalClassProperties(): boolean { return true; } - get supportsUnionsWithBothNumberTypes (): boolean { + public get supportsUnionsWithBothNumberTypes(): boolean { return true; } - protected makeRenderer ( + protected makeRenderer( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any, }, + untypedOptionValues: { [name: string]: any } ): HaskellRenderer { return new HaskellRenderer(this, renderContext, getOptionValues(haskellOptions, untypedOptionValues)); } @@ -110,12 +110,12 @@ const forbiddenNames = [ "Object", "Result", "Series", - "Error", + "Error" ]; const legalizeName = legalizeCharacters(cp => isAscii(cp) && isLetterOrUnderscoreOrDigit(cp)); -function haskellNameStyle (original: string, upper: boolean): string { +function haskellNameStyle(original: string, upper: boolean): string { const words = splitIntoWords(original); return combineWords( words, @@ -125,7 +125,7 @@ function haskellNameStyle (original: string, upper: boolean): string { upper ? allUpperWordStyle : allLowerWordStyle, allUpperWordStyle, "", - isLetterOrUnderscore, + isLetterOrUnderscore ); } @@ -133,73 +133,73 @@ const upperNamingFunction = funPrefixNamer("upper", n => haskellNameStyle(n, tru const lowerNamingFunction = funPrefixNamer("lower", n => haskellNameStyle(n, false)); export class HaskellRenderer extends ConvenienceRenderer { - constructor ( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues, + private readonly _options: OptionValues ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace (): string[] { + protected forbiddenNamesForGlobalNamespace(): string[] { return forbiddenNames; } - protected makeNamedTypeNamer (): Namer { + protected makeNamedTypeNamer(): Namer { return upperNamingFunction; } - protected namerForObjectProperty (): Namer { + protected namerForObjectProperty(): Namer { return lowerNamingFunction; } - protected forbiddenForObjectProperties (_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected makeUnionMemberNamer (): Namer { + protected makeUnionMemberNamer(): Namer { return upperNamingFunction; } - protected get unionMembersInGlobalNamespace (): boolean { + protected get unionMembersInGlobalNamespace(): boolean { return true; } - protected makeEnumCaseNamer (): Namer { + protected makeEnumCaseNamer(): Namer { return upperNamingFunction; } - protected get enumCasesInGlobalNamespace (): boolean { + protected get enumCasesInGlobalNamespace(): boolean { return true; } - protected proposeUnionMemberName ( + protected proposeUnionMemberName( u: UnionType, unionName: Name, fieldType: Type, - lookup: (n: Name) => string, + lookup: (n: Name) => string ): string { const fieldName = super.proposeUnionMemberName(u, unionName, fieldType, lookup); return `${fieldName}_in_${lookup(unionName)}`; } - protected get commentLineStart (): string { + protected get commentLineStart(): string { return "-- "; } - protected emitDescriptionBlock (lines: Sourcelike[]): void { + protected emitDescriptionBlock(lines: Sourcelike[]): void { if (lines.length === 1) { this.emitComments([{ customLines: lines, lineStart: "{-| ", lineEnd: " -}" }]); } else { this.emitCommentLines(lines, { firstLineStart: "{-| ", lineStart: "", - afterComment: "-}", + afterComment: "-}" }); } } - private haskellType (t: Type, noOptional = false): MultiWord { + private haskellType(t: Type, noOptional = false): MultiWord { return matchType( t, _anyType => multiWord(" ", "Maybe", "Text"), @@ -227,11 +227,11 @@ export class HaskellRenderer extends ConvenienceRenderer { } return singleWord(this.nameForNamedType(unionType)); - }, + } ); } - private haskellProperty (p: ClassProperty): Sourcelike { + private haskellProperty(p: ClassProperty): Sourcelike { if (p.isOptional) { return multiWord(" ", "Maybe", parenIfNeeded(this.haskellType(p.type, true))).source; } else { @@ -239,7 +239,7 @@ export class HaskellRenderer extends ConvenienceRenderer { } } - private encoderNameForType (t: Type): MultiWord { + private encoderNameForType(t: Type): MultiWord { return matchType( t, _anyType => singleWord("String"), @@ -252,15 +252,15 @@ export class HaskellRenderer extends ConvenienceRenderer { _classType => singleWord("Object"), _mapType => singleWord("Object"), _enumType => singleWord("Object"), - _unionType => singleWord("Object"), + _unionType => singleWord("Object") ); } - private emitTopLevelDefinition (t: Type, topLevelName: Name): void { + private emitTopLevelDefinition(t: Type, topLevelName: Name): void { this.emitLine("type ", topLevelName, " = ", this.haskellType(t).source); } - private emitClassDefinition (c: ClassType, className: Name): void { + private emitClassDefinition(c: ClassType, className: Name): void { let description = this.descriptionForType(c); this.forEachClassProperty(c, "none", (name, jsonName) => { const propertyDescription = this.descriptionForClassProperty(c, jsonName); @@ -292,7 +292,7 @@ export class HaskellRenderer extends ConvenienceRenderer { }); } - private emitEnumDefinition (e: EnumType, enumName: Name): void { + private emitEnumDefinition(e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); this.emitLine("data ", enumName); this.indent(() => { @@ -306,7 +306,7 @@ export class HaskellRenderer extends ConvenienceRenderer { }); } - private emitUnionDefinition (u: UnionType, unionName: Name): void { + private emitUnionDefinition(u: UnionType, unionName: Name): void { this.emitDescription(this.descriptionForType(u)); this.emitLine("data ", unionName); this.indent(() => { @@ -325,12 +325,12 @@ export class HaskellRenderer extends ConvenienceRenderer { }); } - private emitTopLevelFunctions (topLevelName: Name): void { + private emitTopLevelFunctions(topLevelName: Name): void { this.emitLine("decodeTopLevel :: ByteString -> Maybe ", topLevelName); this.emitLine("decodeTopLevel = decode"); } - private classPropertyLength (c: ClassType): number { + private classPropertyLength(c: ClassType): number { let counter = 0; this.forEachClassProperty(c, "none", () => { counter += 1; @@ -338,7 +338,7 @@ export class HaskellRenderer extends ConvenienceRenderer { return counter; } - private emitClassEncoderInstance (c: ClassType, className: Name): void { + private emitClassEncoderInstance(c: ClassType, className: Name): void { let classProperties: Array = []; this.forEachClassProperty(c, "none", name => { classProperties.push(" "); @@ -356,7 +356,7 @@ export class HaskellRenderer extends ConvenienceRenderer { this.emitLine("object"); let onFirst = true; this.forEachClassProperty(c, "none", (name, jsonName) => { - this.emitLine(onFirst ? "[ " : ", ", "\"", stringEscape(jsonName), "\" .= ", name, className); + this.emitLine(onFirst ? "[ " : ", ", '"', stringEscape(jsonName), '" .= ', name, className); onFirst = false; }); if (onFirst) { @@ -369,7 +369,7 @@ export class HaskellRenderer extends ConvenienceRenderer { }); } - private emitClassDecoderInstance (c: ClassType, className: Name): void { + private emitClassDecoderInstance(c: ClassType, className: Name): void { this.emitLine("instance FromJSON ", className, " where"); this.indent(() => { @@ -381,7 +381,7 @@ export class HaskellRenderer extends ConvenienceRenderer { let onFirst = true; this.forEachClassProperty(c, "none", (_, jsonName, p) => { const operator = p.isOptional ? ".:?" : ".:"; - this.emitLine(onFirst ? "<$> " : "<*> ", "v ", operator, " \"", stringEscape(jsonName), "\""); + this.emitLine(onFirst ? "<$> " : "<*> ", "v ", operator, ' "', stringEscape(jsonName), '"'); onFirst = false; }); }); @@ -389,43 +389,43 @@ export class HaskellRenderer extends ConvenienceRenderer { }); } - private emitClassFunctions (c: ClassType, className: Name): void { + private emitClassFunctions(c: ClassType, className: Name): void { this.emitClassEncoderInstance(c, className); this.ensureBlankLine(); this.emitClassDecoderInstance(c, className); } - private emitEnumEncoderInstance (e: EnumType, enumName: Name): void { + private emitEnumEncoderInstance(e: EnumType, enumName: Name): void { this.emitLine("instance ToJSON ", enumName, " where"); this.indent(() => { this.forEachEnumCase(e, "none", (name, jsonName) => { - this.emitLine("toJSON ", name, enumName, " = \"", stringEscape(jsonName), "\""); + this.emitLine("toJSON ", name, enumName, ' = "', stringEscape(jsonName), '"'); }); }); } - private emitEnumDecoderInstance (e: EnumType, enumName: Name): void { + private emitEnumDecoderInstance(e: EnumType, enumName: Name): void { this.emitLine("instance FromJSON ", enumName, " where"); this.indent(() => { - this.emitLine("parseJSON = withText \"", enumName, "\" parseText"); + this.emitLine('parseJSON = withText "', enumName, '" parseText'); this.indent(() => { this.emitLine("where"); this.indent(() => { this.forEachEnumCase(e, "none", (name, jsonName) => { - this.emitLine("parseText \"", stringEscape(jsonName), "\" = return ", name, enumName); + this.emitLine('parseText "', stringEscape(jsonName), '" = return ', name, enumName); }); }); }); }); } - private emitEnumFunctions (e: EnumType, enumName: Name): void { + private emitEnumFunctions(e: EnumType, enumName: Name): void { this.emitEnumEncoderInstance(e, enumName); this.ensureBlankLine(); this.emitEnumDecoderInstance(e, enumName); } - private emitUnionEncoderInstance (u: UnionType, unionName: Name): void { + private emitUnionEncoderInstance(u: UnionType, unionName: Name): void { this.emitLine("instance ToJSON ", unionName, " where"); this.indent(() => { this.forEachUnionMember(u, null, "none", null, (constructor, t) => { @@ -438,7 +438,7 @@ export class HaskellRenderer extends ConvenienceRenderer { }); } - private emitUnionDecoderInstance (u: UnionType, unionName: Name): void { + private emitUnionDecoderInstance(u: UnionType, unionName: Name): void { this.emitLine("instance FromJSON ", unionName, " where"); this.indent(() => { this.forEachUnionMember(u, null, "none", null, (constructor, t) => { @@ -450,24 +450,24 @@ export class HaskellRenderer extends ConvenienceRenderer { this.encoderNameForType(t).source, " _) = (fmap ", constructor, - " . parseJSON) xs", + " . parseJSON) xs" ); } }); }); } - private emitUnionFunctions (u: UnionType, unionName: Name): void { + private emitUnionFunctions(u: UnionType, unionName: Name): void { this.emitUnionEncoderInstance(u, unionName); this.ensureBlankLine(); this.emitUnionDecoderInstance(u, unionName); } - private emitLanguageExtensions (ext: string): void { + private emitLanguageExtensions(ext: string): void { this.emitLine(`{-# LANGUAGE ${ext} #-}`); } - protected emitSourceStructure (): void { + protected emitSourceStructure(): void { const exports: Sourcelike[] = []; this.forEachTopLevel("none", (_, name) => { exports.push([name, " (..)"]); @@ -512,25 +512,25 @@ import Data.Text (Text)`); this.forEachTopLevel( "leading-and-interposing", (t: Type, topLevelName: Name) => this.emitTopLevelDefinition(t, topLevelName), - t => this.namedTypeToNameForTopLevel(t) === undefined, + t => this.namedTypeToNameForTopLevel(t) === undefined ); this.forEachNamedType( "leading-and-interposing", (c: ClassType, className: Name) => this.emitClassDefinition(c, className), (e: EnumType, enumName: Name) => this.emitEnumDefinition(e, enumName), - (u: UnionType, unionName: Name) => this.emitUnionDefinition(u, unionName), + (u: UnionType, unionName: Name) => this.emitUnionDefinition(u, unionName) ); this.forEachTopLevel("leading-and-interposing", (_: Type, topLevelName: Name) => - this.emitTopLevelFunctions(topLevelName), + this.emitTopLevelFunctions(topLevelName) ); this.forEachNamedType( "leading-and-interposing", (c: ClassType, className: Name) => this.emitClassFunctions(c, className), (e: EnumType, enumName: Name) => this.emitEnumFunctions(e, enumName), - (u: UnionType, unionName: Name) => this.emitUnionFunctions(u, unionName), + (u: UnionType, unionName: Name) => this.emitUnionFunctions(u, unionName) ); if (this._options.justTypes) return; diff --git a/packages/quicktype-core/src/language/JSONSchema.ts b/packages/quicktype-core/src/language/JSONSchema.ts index c18d6c744..612bd7310 100644 --- a/packages/quicktype-core/src/language/JSONSchema.ts +++ b/packages/quicktype-core/src/language/JSONSchema.ts @@ -1,7 +1,7 @@ import { mapFirst, iterableFirst } from "collection-utils"; import { TargetLanguage } from "../TargetLanguage"; -import { type Type, type UnionType, type EnumType, type ObjectType} from "../Type"; +import { type Type, type UnionType, type EnumType, type ObjectType } from "../Type"; import { transformedStringTypeTargetTypeKindsMap } from "../Type"; import { matchTypeExhaustive } from "../TypeUtils"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; @@ -12,39 +12,39 @@ import { splitIntoWords, combineWords, firstUpperWordStyle, - allUpperWordStyle, + allUpperWordStyle } from "../support/Strings"; import { defined, panic } from "../support/Support"; -import { type StringTypeMapping} from "../TypeBuilder"; +import { type StringTypeMapping } from "../TypeBuilder"; import { getNoStringTypeMapping } from "../TypeBuilder"; import { addDescriptionToSchema } from "../attributes/Description"; import { type Option } from "../RendererOptions"; import { type RenderContext } from "../Renderer"; export class JSONSchemaTargetLanguage extends TargetLanguage { - constructor () { + public constructor() { super("JSON Schema", ["schema", "json-schema"], "schema"); } - protected getOptions (): Array> { + protected getOptions(): Array> { return []; } - get stringTypeMapping (): StringTypeMapping { + public get stringTypeMapping(): StringTypeMapping { return getNoStringTypeMapping(); } - get supportsOptionalClassProperties (): boolean { + public get supportsOptionalClassProperties(): boolean { return true; } - get supportsFullObjectType (): boolean { + public get supportsFullObjectType(): boolean { return true; } - protected makeRenderer ( + protected makeRenderer( renderContext: RenderContext, - _untypedOptionValues: { [name: string]: any, }, + _untypedOptionValues: { [name: string]: any } ): JSONSchemaRenderer { return new JSONSchemaRenderer(this, renderContext); } @@ -54,7 +54,7 @@ const namingFunction = funPrefixNamer("namer", jsonNameStyle); const legalizeName = legalizeCharacters(cp => cp >= 32 && cp < 128 && cp !== 0x2f /* slash */); -function jsonNameStyle (original: string): string { +function jsonNameStyle(original: string): string { const words = splitIntoWords(original); return combineWords( words, @@ -64,36 +64,36 @@ function jsonNameStyle (original: string): string { allUpperWordStyle, allUpperWordStyle, "", - _ => true, + _ => true ); } interface Schema { - [name: string]: any; + [name: string]: any; } export class JSONSchemaRenderer extends ConvenienceRenderer { - protected makeNamedTypeNamer (): Namer { + protected makeNamedTypeNamer(): Namer { return namingFunction; } - protected namerForObjectProperty (): null { + protected namerForObjectProperty(): null { return null; } - protected makeUnionMemberNamer (): null { + protected makeUnionMemberNamer(): null { return null; } - protected makeEnumCaseNamer (): null { + protected makeEnumCaseNamer(): null { return null; } - private nameForType (t: Type): string { + private nameForType(t: Type): string { return defined(this.names.get(this.nameForNamedType(t))); } - private makeOneOf (types: ReadonlySet): Schema { + private makeOneOf(types: ReadonlySet): Schema { const first = iterableFirst(types); if (first === undefined) { return panic("Must have at least one type for oneOf"); @@ -106,19 +106,19 @@ export class JSONSchemaRenderer extends ConvenienceRenderer { return { anyOf: Array.from(types).map((t: Type) => this.schemaForType(t)) }; } - private makeRef (t: Type): Schema { + private makeRef(t: Type): Schema { return { $ref: `#/definitions/${this.nameForType(t)}` }; } - private addAttributesToSchema (t: Type, schema: Schema): void { + private addAttributesToSchema(t: Type, schema: Schema): void { const attributes = this.typeGraph.attributeStore.attributesForType(t); for (const [kind, attr] of attributes) { kind.addToSchema(schema, t, attr); } } - private schemaForType (t: Type): Schema { - const schema = matchTypeExhaustive<{ [name: string]: any, }>( + private schemaForType(t: Type): Schema { + const schema = matchTypeExhaustive<{ [name: string]: any }>( t, _noneType => { return panic("none type should have been replaced"); @@ -148,7 +148,7 @@ export class JSONSchemaRenderer extends ConvenienceRenderer { } return { type: "string", format: target.jsonSchema }; - }, + } ); if (schema.$ref === undefined) { this.addAttributesToSchema(t, schema); @@ -157,7 +157,7 @@ export class JSONSchemaRenderer extends ConvenienceRenderer { return schema; } - private definitionForObject (o: ObjectType, title: string | undefined): Schema { + private definitionForObject(o: ObjectType, title: string | undefined): Schema { let properties: Schema | undefined; let required: string[] | undefined; if (o.getProperties().size === 0) { @@ -189,13 +189,13 @@ export class JSONSchemaRenderer extends ConvenienceRenderer { additionalProperties, properties, required, - title, + title }; this.addAttributesToSchema(o, schema); return schema; } - private definitionForUnion (u: UnionType, title?: string): Schema { + private definitionForUnion(u: UnionType, title?: string): Schema { const oneOf = this.makeOneOf(u.sortedMembers); if (title !== undefined) { oneOf.title = title; @@ -205,17 +205,17 @@ export class JSONSchemaRenderer extends ConvenienceRenderer { return oneOf; } - private definitionForEnum (e: EnumType, title: string): Schema { + private definitionForEnum(e: EnumType, title: string): Schema { const schema = { type: "string", enum: Array.from(e.cases), title }; this.addAttributesToSchema(e, schema); return schema; } - protected emitSourceStructure (): void { + protected emitSourceStructure(): void { // FIXME: Find a good way to do multiple top-levels. Maybe multiple files? const topLevelType = this.topLevels.size === 1 ? this.schemaForType(defined(mapFirst(this.topLevels))) : {}; const schema = Object.assign({ $schema: "http://json-schema.org/draft-06/schema#" }, topLevelType); - const definitions: { [name: string]: Schema, } = {}; + const definitions: { [name: string]: Schema } = {}; this.forEachObject("none", (o: ObjectType, name: Name) => { const title = defined(this.names.get(name)); definitions[title] = this.definitionForObject(o, title); diff --git a/packages/quicktype-core/src/language/Java.ts b/packages/quicktype-core/src/language/Java.ts index a4cc006d1..25b975ad2 100644 --- a/packages/quicktype-core/src/language/Java.ts +++ b/packages/quicktype-core/src/language/Java.ts @@ -4,7 +4,7 @@ import { ConvenienceRenderer } from "../ConvenienceRenderer"; import { type Name, type Namer } from "../Naming"; import { DependencyName, funPrefixNamer } from "../Naming"; import { type RenderContext } from "../Renderer"; -import { type Option, type OptionValues} from "../RendererOptions"; +import { type Option, type OptionValues } from "../RendererOptions"; import { BooleanOption, EnumOption, getOptionValues, StringOption } from "../RendererOptions"; import { type Sourcelike } from "../Source"; import { maybeAnnotated } from "../Source"; @@ -22,11 +22,11 @@ import { splitIntoWords, standardUnicodeHexEscape, utf16ConcatMap, - utf16LegalizeCharacters, + utf16LegalizeCharacters } from "../support/Strings"; import { assert, assertNever, defined, panic } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; -import { type ClassProperty, type Type, type TypeKind} from "../Type"; +import { type ClassProperty, type Type, type TypeKind } from "../Type"; import { ArrayType, ClassType, EnumType, MapType, UnionType } from "../Type"; import { directlyReachableSingleNamedType, matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; import { type StringTypeMapping, type TransformedStringTypeKind, type PrimitiveStringTypeKind } from ".."; @@ -37,9 +37,9 @@ export const javaOptions = { "Use T[] or List", [ ["array", false], - ["list", true], + ["list", true] ], - "array", + "array" ), justTypes: new BooleanOption("just-types", "Plain types only", false), dateTimeProvider: new EnumOption( @@ -47,23 +47,23 @@ export const javaOptions = { "Date time provider type", [ ["java8", "java8"], - ["legacy", "legacy"], + ["legacy", "legacy"] ], - "java8", + "java8" ), acronymStyle: acronymOption(AcronymStyleOptions.Pascal), // FIXME: Do this via a configurable named eventually. packageName: new StringOption("package", "Generated package name", "NAME", "io.quicktype"), lombok: new BooleanOption("lombok", "Use lombok", false, "primary"), - lombokCopyAnnotations: new BooleanOption("lombok-copy-annotations", "Copy accessor annotations", true, "secondary"), + lombokCopyAnnotations: new BooleanOption("lombok-copy-annotations", "Copy accessor annotations", true, "secondary") }; export class JavaTargetLanguage extends TargetLanguage { - constructor () { + public constructor() { super("Java", ["java"], "java"); } - protected getOptions (): Array> { + protected getOptions(): Array> { return [ javaOptions.useList, javaOptions.justTypes, @@ -71,15 +71,15 @@ export class JavaTargetLanguage extends TargetLanguage { javaOptions.acronymStyle, javaOptions.packageName, javaOptions.lombok, - javaOptions.lombokCopyAnnotations, + javaOptions.lombokCopyAnnotations ]; } - get supportsUnionsWithBothNumberTypes (): boolean { + public get supportsUnionsWithBothNumberTypes(): boolean { return true; } - protected makeRenderer (renderContext: RenderContext, untypedOptionValues: { [name: string]: any, }): JavaRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): JavaRenderer { const options = getOptionValues(javaOptions, untypedOptionValues); if (options.justTypes) { return new JavaRenderer(this, renderContext, options); @@ -88,7 +88,7 @@ export class JavaTargetLanguage extends TargetLanguage { return new JacksonRenderer(this, renderContext, options); } - get stringTypeMapping (): StringTypeMapping { + public get stringTypeMapping(): StringTypeMapping { const mapping: Map = new Map(); mapping.set("date", "date"); mapping.set("time", "time"); @@ -165,27 +165,27 @@ const javaKeywords = [ "while", "null", "false", - "true", + "true" ]; export const stringEscape = utf16ConcatMap(escapeNonPrintableMapper(isAscii, standardUnicodeHexEscape)); -function isStartCharacter (codePoint: number): boolean { +function isStartCharacter(codePoint: number): boolean { if (codePoint === 0x5f) return true; // underscore return isAscii(codePoint) && isLetter(codePoint); } -function isPartCharacter (codePoint: number): boolean { - return isStartCharacter(codePoint) || isAscii(codePoint) && isDigit(codePoint); +function isPartCharacter(codePoint: number): boolean { + return isStartCharacter(codePoint) || (isAscii(codePoint) && isDigit(codePoint)); } const legalizeName = utf16LegalizeCharacters(isPartCharacter); -export function javaNameStyle ( +export function javaNameStyle( startWithUpper: boolean, upperUnderscore: boolean, original: string, - acronymsStyle: (s: string) => string = allUpperWordStyle, + acronymsStyle: (s: string) => string = allUpperWordStyle ): string { const words = splitIntoWords(original); return combineWords( @@ -196,39 +196,39 @@ export function javaNameStyle ( upperUnderscore || startWithUpper ? allUpperWordStyle : allLowerWordStyle, acronymsStyle, upperUnderscore ? "_" : "", - isStartCharacter, + isStartCharacter ); } abstract class JavaDateTimeProvider { - constructor ( + public constructor( protected readonly _renderer: JavaRenderer, - protected readonly _className: string, + protected readonly _className: string ) {} - abstract keywords: string[]; + public abstract keywords: string[]; - abstract dateTimeImports: string[]; + public abstract dateTimeImports: string[]; - abstract dateImports: string[]; + public abstract dateImports: string[]; - abstract timeImports: string[]; + public abstract timeImports: string[]; - abstract converterImports: string[]; + public abstract converterImports: string[]; - abstract dateTimeType: string; + public abstract dateTimeType: string; - abstract dateType: string; + public abstract dateType: string; - abstract timeType: string; + public abstract timeType: string; - abstract dateTimeJacksonAnnotations: string[]; + public abstract dateTimeJacksonAnnotations: string[]; - abstract dateJacksonAnnotations: string[]; + public abstract dateJacksonAnnotations: string[]; - abstract timeJacksonAnnotations: string[]; + public abstract timeJacksonAnnotations: string[]; - abstract emitDateTimeConverters (): void; + public abstract emitDateTimeConverters(): void; public shouldEmitDateTimeConverter = true; @@ -236,17 +236,17 @@ abstract class JavaDateTimeProvider { public shouldEmitDateConverter = true; - abstract convertStringToDateTime (variable: Sourcelike): Sourcelike; - abstract convertStringToTime (variable: Sourcelike): Sourcelike; - abstract convertStringToDate (variable: Sourcelike): Sourcelike; + public abstract convertStringToDateTime(variable: Sourcelike): Sourcelike; + public abstract convertStringToTime(variable: Sourcelike): Sourcelike; + public abstract convertStringToDate(variable: Sourcelike): Sourcelike; - abstract convertDateTimeToString (variable: Sourcelike): Sourcelike; - abstract convertTimeToString (variable: Sourcelike): Sourcelike; - abstract convertDateToString (variable: Sourcelike): Sourcelike; + public abstract convertDateTimeToString(variable: Sourcelike): Sourcelike; + public abstract convertTimeToString(variable: Sourcelike): Sourcelike; + public abstract convertDateToString(variable: Sourcelike): Sourcelike; } class Java8DateTimeProvider extends JavaDateTimeProvider { - keywords = [ + public keywords = [ "LocalDate", "OffsetDateTime", "OffsetTime", @@ -254,16 +254,16 @@ class Java8DateTimeProvider extends JavaDateTimeProvider { "ZonedDateTime", "DateTimeFormatter", "DateTimeFormatterBuilder", - "ChronoField", + "ChronoField" ]; - dateTimeImports: string[] = ["java.time.OffsetDateTime"]; + public dateTimeImports: string[] = ["java.time.OffsetDateTime"]; - dateImports: string[] = ["java.time.LocalDate"]; + public dateImports: string[] = ["java.time.LocalDate"]; - timeImports: string[] = ["java.time.OffsetTime"]; + public timeImports: string[] = ["java.time.OffsetTime"]; - converterImports: string[] = [ + public converterImports: string[] = [ "java.time.LocalDate", "java.time.OffsetDateTime", "java.time.OffsetTime", @@ -271,48 +271,48 @@ class Java8DateTimeProvider extends JavaDateTimeProvider { "java.time.ZonedDateTime", "java.time.format.DateTimeFormatter", "java.time.format.DateTimeFormatterBuilder", - "java.time.temporal.ChronoField", + "java.time.temporal.ChronoField" ]; - dateTimeType = "OffsetDateTime"; + public dateTimeType = "OffsetDateTime"; - dateType = "LocalDate"; + public dateType = "LocalDate"; - timeType = "OffsetTime"; + public timeType = "OffsetTime"; - dateTimeJacksonAnnotations: string[] = []; + public dateTimeJacksonAnnotations: string[] = []; - dateJacksonAnnotations: string[] = []; + public dateJacksonAnnotations: string[] = []; - timeJacksonAnnotations: string[] = []; + public timeJacksonAnnotations: string[] = []; - emitDateTimeConverters (): void { + public emitDateTimeConverters(): void { this._renderer.ensureBlankLine(); this._renderer.emitLine( - "private static final DateTimeFormatter DATE_TIME_FORMATTER = new DateTimeFormatterBuilder()", + "private static final DateTimeFormatter DATE_TIME_FORMATTER = new DateTimeFormatterBuilder()" ); this._renderer.indent(() => this._renderer.indent(() => { this._renderer.emitLine(".appendOptional(DateTimeFormatter.ISO_DATE_TIME)"); this._renderer.emitLine(".appendOptional(DateTimeFormatter.ISO_OFFSET_DATE_TIME)"); this._renderer.emitLine(".appendOptional(DateTimeFormatter.ISO_INSTANT)"); - this._renderer.emitLine(".appendOptional(DateTimeFormatter.ofPattern(\"yyyy-MM-dd HH:mm:ss.SX\"))"); - this._renderer.emitLine(".appendOptional(DateTimeFormatter.ofPattern(\"yyyy-MM-dd HH:mm:ssX\"))"); - this._renderer.emitLine(".appendOptional(DateTimeFormatter.ofPattern(\"yyyy-MM-dd HH:mm:ss\"))"); + this._renderer.emitLine('.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SX"))'); + this._renderer.emitLine('.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ssX"))'); + this._renderer.emitLine('.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))'); this._renderer.emitLine(".toFormatter()"); this._renderer.emitLine(".withZone(ZoneOffset.UTC);"); - }), + }) ); this._renderer.ensureBlankLine(); this._renderer.emitBlock("public static OffsetDateTime parseDateTimeString(String str)", () => { this._renderer.emitLine( - "return ZonedDateTime.from(Converter.DATE_TIME_FORMATTER.parse(str)).toOffsetDateTime();", + "return ZonedDateTime.from(Converter.DATE_TIME_FORMATTER.parse(str)).toOffsetDateTime();" ); }); this._renderer.ensureBlankLine(); this._renderer.emitLine( - "private static final DateTimeFormatter TIME_FORMATTER = new DateTimeFormatterBuilder()", + "private static final DateTimeFormatter TIME_FORMATTER = new DateTimeFormatterBuilder()" ); this._renderer.indent(() => this._renderer.indent(() => { @@ -323,65 +323,71 @@ class Java8DateTimeProvider extends JavaDateTimeProvider { this._renderer.emitLine(".parseDefaulting(ChronoField.DAY_OF_MONTH, 1)"); this._renderer.emitLine(".toFormatter()"); this._renderer.emitLine(".withZone(ZoneOffset.UTC);"); - }), + }) ); this._renderer.ensureBlankLine(); this._renderer.emitBlock("public static OffsetTime parseTimeString(String str)", () => { this._renderer.emitLine( - "return ZonedDateTime.from(Converter.TIME_FORMATTER.parse(str)).toOffsetDateTime().toOffsetTime();", + "return ZonedDateTime.from(Converter.TIME_FORMATTER.parse(str)).toOffsetDateTime().toOffsetTime();" ); }); } - convertStringToDateTime (variable: Sourcelike): Sourcelike { + public convertStringToDateTime(variable: Sourcelike): Sourcelike { return [this._className, ".parseDateTimeString(", variable, ")"]; } - convertStringToTime (variable: Sourcelike): Sourcelike { + public convertStringToTime(variable: Sourcelike): Sourcelike { return [this._className, ".parseTimeString(", variable, ")"]; } - convertStringToDate (variable: Sourcelike): Sourcelike { + public convertStringToDate(variable: Sourcelike): Sourcelike { return ["LocalDate.parse(", variable, ")"]; } - convertDateTimeToString (variable: Sourcelike): Sourcelike { + public convertDateTimeToString(variable: Sourcelike): Sourcelike { return [variable, ".format(java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME)"]; } - convertTimeToString (variable: Sourcelike): Sourcelike { + public convertTimeToString(variable: Sourcelike): Sourcelike { return [variable, ".format(java.time.format.DateTimeFormatter.ISO_OFFSET_TIME)"]; } - convertDateToString (variable: Sourcelike): Sourcelike { + public convertDateToString(variable: Sourcelike): Sourcelike { return [variable, ".format(java.time.format.DateTimeFormatter.ISO_DATE)"]; } } class JavaLegacyDateTimeProvider extends JavaDateTimeProvider { - keywords = ["SimpleDateFormat", "Date"]; + public keywords = ["SimpleDateFormat", "Date"]; - dateTimeImports: string[] = ["java.util.Date"]; + public dateTimeImports: string[] = ["java.util.Date"]; - dateImports: string[] = ["java.util.Date"]; + public dateImports: string[] = ["java.util.Date"]; - timeImports: string[] = ["java.util.Date"]; + public timeImports: string[] = ["java.util.Date"]; - converterImports: string[] = ["java.util.Date", "java.text.SimpleDateFormat"]; + public converterImports: string[] = ["java.util.Date", "java.text.SimpleDateFormat"]; - dateTimeType = "Date"; + public dateTimeType = "Date"; - dateType = "Date"; + public dateType = "Date"; - timeType = "Date"; + public timeType = "Date"; - dateTimeJacksonAnnotations: string[] = ["@JsonFormat(pattern = \"yyyy-MM-dd'T'HH:mm:ssX\", timezone = \"UTC\")"]; + public dateTimeJacksonAnnotations: string[] = [ + '@JsonFormat(pattern = "yyyy-MM-dd\'T\'HH:mm:ssX", timezone = "UTC")' + ]; + + public dateJacksonAnnotations: string[] = ['@JsonFormat(pattern = "yyyy-MM-dd")']; + + public timeJacksonAnnotations: string[] = ['@JsonFormat(pattern = "HH:mm:ssX", timezone = "UTC")']; - dateJacksonAnnotations: string[] = ["@JsonFormat(pattern = \"yyyy-MM-dd\")"]; + public shouldEmitTimeConverter = false; - timeJacksonAnnotations: string[] = ["@JsonFormat(pattern = \"HH:mm:ssX\", timezone = \"UTC\")"]; + public shouldEmitDateConverter = false; - emitDateTimeConverters (): void { + public emitDateTimeConverters(): void { this._renderer.ensureBlankLine(); this._renderer.emitLine("private static final String[] DATE_TIME_FORMATS = {"); this._renderer.indent(() => @@ -390,16 +396,16 @@ class JavaLegacyDateTimeProvider extends JavaDateTimeProvider { this._renderer.emitLine("\"yyyy-MM-dd'T'HH:mm:ss.S\","); this._renderer.emitLine("\"yyyy-MM-dd'T'HH:mm:ssX\","); this._renderer.emitLine("\"yyyy-MM-dd'T'HH:mm:ss\","); - this._renderer.emitLine("\"yyyy-MM-dd HH:mm:ss.SX\","); - this._renderer.emitLine("\"yyyy-MM-dd HH:mm:ss.S\","); - this._renderer.emitLine("\"yyyy-MM-dd HH:mm:ssX\","); - this._renderer.emitLine("\"yyyy-MM-dd HH:mm:ss\","); - this._renderer.emitLine("\"HH:mm:ss.SZ\","); - this._renderer.emitLine("\"HH:mm:ss.S\","); - this._renderer.emitLine("\"HH:mm:ssZ\","); - this._renderer.emitLine("\"HH:mm:ss\","); - this._renderer.emitLine("\"yyyy-MM-dd\","); - }), + this._renderer.emitLine('"yyyy-MM-dd HH:mm:ss.SX",'); + this._renderer.emitLine('"yyyy-MM-dd HH:mm:ss.S",'); + this._renderer.emitLine('"yyyy-MM-dd HH:mm:ssX",'); + this._renderer.emitLine('"yyyy-MM-dd HH:mm:ss",'); + this._renderer.emitLine('"HH:mm:ss.SZ",'); + this._renderer.emitLine('"HH:mm:ss.S",'); + this._renderer.emitLine('"HH:mm:ssZ",'); + this._renderer.emitLine('"HH:mm:ss",'); + this._renderer.emitLine('"yyyy-MM-dd",'); + }) ); this._renderer.emitLine("};"); this._renderer.ensureBlankLine(); @@ -419,40 +425,36 @@ class JavaLegacyDateTimeProvider extends JavaDateTimeProvider { this._renderer.ensureBlankLine(); this._renderer.emitBlock("public static String serializeDate(Date datetime)", () => { - this._renderer.emitLine("return new SimpleDateFormat(\"yyyy-MM-dd\").format(datetime);"); + this._renderer.emitLine('return new SimpleDateFormat("yyyy-MM-dd").format(datetime);'); }); this._renderer.ensureBlankLine(); this._renderer.emitBlock("public static String serializeTime(Date datetime)", () => { - this._renderer.emitLine("return new SimpleDateFormat(\"hh:mm:ssZ\").format(datetime);"); + this._renderer.emitLine('return new SimpleDateFormat("hh:mm:ssZ").format(datetime);'); }); } - shouldEmitTimeConverter = false; - - shouldEmitDateConverter = false; - - convertStringToDateTime (variable: Sourcelike): Sourcelike { + public convertStringToDateTime(variable: Sourcelike): Sourcelike { return [this._className, ".parseAllDateTimeString(", variable, ")"]; } - convertStringToTime (variable: Sourcelike): Sourcelike { + public convertStringToTime(variable: Sourcelike): Sourcelike { return [this._className, ".parseAllDateTimeString(", variable, ")"]; } - convertStringToDate (variable: Sourcelike): Sourcelike { + public convertStringToDate(variable: Sourcelike): Sourcelike { return [this._className, ".parseAllDateTimeString(", variable, ")"]; } - convertDateTimeToString (variable: Sourcelike): Sourcelike { + public convertDateTimeToString(variable: Sourcelike): Sourcelike { return [this._className, ".serializeDateTime(", variable, ")"]; } - convertTimeToString (variable: Sourcelike): Sourcelike { + public convertTimeToString(variable: Sourcelike): Sourcelike { return [this._className, ".serializeTime(", variable, ")"]; } - convertDateToString (variable: Sourcelike): Sourcelike { + public convertDateToString(variable: Sourcelike): Sourcelike { return [this._className, ".serializeDate(", variable, ")"]; } } @@ -470,10 +472,10 @@ export class JavaRenderer extends ConvenienceRenderer { protected readonly _converterKeywords: string[] = []; - constructor ( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - protected readonly _options: OptionValues, + protected readonly _options: OptionValues ) { super(targetLanguage, renderContext); @@ -488,95 +490,95 @@ export class JavaRenderer extends ConvenienceRenderer { } } - protected forbiddenNamesForGlobalNamespace (): string[] { + protected forbiddenNamesForGlobalNamespace(): string[] { const keywords = [ ...javaKeywords, ...this._converterKeywords, this._converterClassname, - ...this._dateTimeProvider.keywords, + ...this._dateTimeProvider.keywords ]; return keywords; } - protected forbiddenForObjectProperties (_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected makeNamedTypeNamer (): Namer { + protected makeNamedTypeNamer(): Namer { return this.getNameStyling("typeNamingFunction"); } - protected namerForObjectProperty (): Namer { + protected namerForObjectProperty(): Namer { return this.getNameStyling("propertyNamingFunction"); } - protected makeUnionMemberNamer (): Namer { + protected makeUnionMemberNamer(): Namer { return this.getNameStyling("propertyNamingFunction"); } - protected makeEnumCaseNamer (): Namer { + protected makeEnumCaseNamer(): Namer { return this.getNameStyling("enumCaseNamingFunction"); } - protected unionNeedsName (u: UnionType): boolean { + protected unionNeedsName(u: UnionType): boolean { return nullableFromUnion(u) === null; } - protected namedTypeToNameForTopLevel (type: Type): Type | undefined { + protected namedTypeToNameForTopLevel(type: Type): Type | undefined { // If the top-level type doesn't contain any classes or unions // we have to define a class just for the `FromJson` method, in // emitFromJsonForTopLevel. return directlyReachableSingleNamedType(type); } - protected makeNamesForPropertyGetterAndSetter ( + protected makeNamesForPropertyGetterAndSetter( _c: ClassType, _className: Name, _p: ClassProperty, _jsonName: string, - name: Name, + name: Name ): [Name, Name] { const getterName = new DependencyName( this.getNameStyling("propertyNamingFunction"), name.order, - lookup => `get_${lookup(name)}`, + lookup => `get_${lookup(name)}` ); const setterName = new DependencyName( this.getNameStyling("propertyNamingFunction"), name.order, - lookup => `set_${lookup(name)}`, + lookup => `set_${lookup(name)}` ); return [getterName, setterName]; } - protected makePropertyDependencyNames ( + protected makePropertyDependencyNames( c: ClassType, className: Name, p: ClassProperty, jsonName: string, - name: Name, + name: Name ): Name[] { const getterAndSetterNames = this.makeNamesForPropertyGetterAndSetter(c, className, p, jsonName, name); this._gettersAndSettersForPropertyName.set(name, getterAndSetterNames); return getterAndSetterNames; } - private getNameStyling (convention: string): Namer { - const styling: { [key: string]: Namer, } = { + private getNameStyling(convention: string): Namer { + const styling: { [key: string]: Namer } = { typeNamingFunction: funPrefixNamer("types", n => - javaNameStyle(true, false, n, acronymStyle(this._options.acronymStyle)), + javaNameStyle(true, false, n, acronymStyle(this._options.acronymStyle)) ), propertyNamingFunction: funPrefixNamer("properties", n => - javaNameStyle(false, false, n, acronymStyle(this._options.acronymStyle)), + javaNameStyle(false, false, n, acronymStyle(this._options.acronymStyle)) ), enumCaseNamingFunction: funPrefixNamer("enum-cases", n => - javaNameStyle(true, true, n, acronymStyle(this._options.acronymStyle)), - ), + javaNameStyle(true, true, n, acronymStyle(this._options.acronymStyle)) + ) }; return styling[convention]; } - protected fieldOrMethodName (methodName: string, topLevelName: Name): Sourcelike { + protected fieldOrMethodName(methodName: string, topLevelName: Name): Sourcelike { if (this.topLevels.size === 1) { return methodName; } @@ -584,7 +586,7 @@ export class JavaRenderer extends ConvenienceRenderer { return [topLevelName, capitalize(methodName)]; } - protected methodName (prefix: string, suffix: string, topLevelName: Name): Sourcelike { + protected methodName(prefix: string, suffix: string, topLevelName: Name): Sourcelike { if (this.topLevels.size === 1) { return [prefix, suffix]; } @@ -592,23 +594,23 @@ export class JavaRenderer extends ConvenienceRenderer { return [prefix, topLevelName, suffix]; } - protected decoderName (topLevelName: Name): Sourcelike { + protected decoderName(topLevelName: Name): Sourcelike { return this.fieldOrMethodName("fromJsonString", topLevelName); } - protected encoderName (topLevelName: Name): Sourcelike { + protected encoderName(topLevelName: Name): Sourcelike { return this.fieldOrMethodName("toJsonString", topLevelName); } - protected readerGetterName (topLevelName: Name): Sourcelike { + protected readerGetterName(topLevelName: Name): Sourcelike { return this.methodName("get", "ObjectReader", topLevelName); } - protected writerGetterName (topLevelName: Name): Sourcelike { + protected writerGetterName(topLevelName: Name): Sourcelike { return this.methodName("get", "ObjectWriter", topLevelName); } - protected startFile (basename: Sourcelike): void { + protected startFile(basename: Sourcelike): void { assert(this._currentFilename === undefined, "Previous file wasn't finished"); // FIXME: The filenames should actually be Sourcelikes, too this._currentFilename = `${this.sourcelikeToString(basename)}.java`; @@ -621,12 +623,12 @@ export class JavaRenderer extends ConvenienceRenderer { } } - protected finishFile (): void { + protected finishFile(): void { super.finishFile(defined(this._currentFilename)); this._currentFilename = undefined; } - protected emitPackageAndImports (imports: string[]): void { + protected emitPackageAndImports(imports: string[]): void { this.emitLine("package ", this._options.packageName, ";"); this.ensureBlankLine(); for (const pkg of imports) { @@ -634,23 +636,23 @@ export class JavaRenderer extends ConvenienceRenderer { } } - protected emitFileHeader (fileName: Sourcelike, imports: string[]): void { + protected emitFileHeader(fileName: Sourcelike, imports: string[]): void { this.startFile(fileName); this.emitPackageAndImports(imports); this.ensureBlankLine(); } - public emitDescriptionBlock (lines: Sourcelike[]): void { + public emitDescriptionBlock(lines: Sourcelike[]): void { this.emitCommentLines(lines, { lineStart: " * ", beforeComment: "/**", afterComment: " */" }); } - public emitBlock (line: Sourcelike, f: () => void): void { + public emitBlock(line: Sourcelike, f: () => void): void { this.emitLine(line, " {"); this.indent(f); this.emitLine("}"); } - public emitTryCatch (main: () => void, handler: () => void, exception = "Exception") { + public emitTryCatch(main: () => void, handler: () => void, exception = "Exception") { this.emitLine("try {"); this.indent(main); this.emitLine("} catch (", exception, " ex) {"); @@ -658,18 +660,18 @@ export class JavaRenderer extends ConvenienceRenderer { this.emitLine("}"); } - public emitIgnoredTryCatchBlock (f: () => void) { + public emitIgnoredTryCatchBlock(f: () => void) { this.emitTryCatch(f, () => this.emitLine("// Ignored")); } - protected javaType (reference: boolean, t: Type, withIssues = false): Sourcelike { + protected javaType(reference: boolean, t: Type, withIssues = false): Sourcelike { return matchType( t, _anyType => maybeAnnotated(withIssues, anyTypeIssueAnnotation, "Object"), _nullType => maybeAnnotated(withIssues, nullTypeIssueAnnotation, "Object"), - _boolType => reference ? "Boolean" : "boolean", - _integerType => reference ? "Long" : "long", - _doubleType => reference ? "Double" : "double", + _boolType => (reference ? "Boolean" : "boolean"), + _integerType => (reference ? "Long" : "long"), + _doubleType => (reference ? "Double" : "double"), _stringType => "String", arrayType => { if (this._options.useList) { @@ -704,11 +706,11 @@ export class JavaRenderer extends ConvenienceRenderer { } return "String"; - }, + } ); } - protected javaImport (t: Type): string[] { + protected javaImport(t: Type): string[] { return matchType( t, _anyType => [], @@ -750,11 +752,11 @@ export class JavaRenderer extends ConvenienceRenderer { } return []; - }, + } ); } - protected javaTypeWithoutGenerics (reference: boolean, t: Type): Sourcelike { + protected javaTypeWithoutGenerics(reference: boolean, t: Type): Sourcelike { if (t instanceof ArrayType) { if (this._options.useList) { return ["List"]; @@ -772,24 +774,24 @@ export class JavaRenderer extends ConvenienceRenderer { } } - protected emitClassAttributes (_c: ClassType, _className: Name): void { + protected emitClassAttributes(_c: ClassType, _className: Name): void { if (this._options.lombok) { this.emitLine("@lombok.Data"); } } - protected annotationsForAccessor ( + protected annotationsForAccessor( _c: ClassType, _className: Name, _propertyName: Name, _jsonName: string, _p: ClassProperty, - _isSetter: boolean, + _isSetter: boolean ): string[] { return []; } - protected importsForType (t: ClassType | UnionType | EnumType): string[] { + protected importsForType(t: ClassType | UnionType | EnumType): string[] { if (t instanceof ClassType) { return []; } @@ -805,7 +807,7 @@ export class JavaRenderer extends ConvenienceRenderer { return assertNever(t); } - protected importsForClass (c: ClassType): string[] { + protected importsForClass(c: ClassType): string[] { const imports: string[] = []; this.forEachClassProperty(c, "none", (_name, _jsonName, p) => { this.javaImport(p.type).forEach(imp => imports.push(imp)); @@ -814,7 +816,7 @@ export class JavaRenderer extends ConvenienceRenderer { return [...new Set(imports)]; } - protected importsForUnionMembers (u: UnionType): string[] { + protected importsForUnionMembers(u: UnionType): string[] { const imports: string[] = []; const [, nonNulls] = removeNullFromUnion(u); this.forEachUnionMember(u, nonNulls, "none", null, (_fieldName, t) => { @@ -824,7 +826,7 @@ export class JavaRenderer extends ConvenienceRenderer { return [...new Set(imports)]; } - protected emitClassDefinition (c: ClassType, className: Name): void { + protected emitClassDefinition(c: ClassType, className: Name): void { let imports = [...this.importsForType(c), ...this.importsForClass(c)]; this.emitFileHeader(className, imports); @@ -852,11 +854,11 @@ export class JavaRenderer extends ConvenienceRenderer { const [getterName, setterName] = defined(this._gettersAndSettersForPropertyName.get(name)); const rendered = this.javaType(false, p.type); this.annotationsForAccessor(c, className, name, jsonName, p, false).forEach(annotation => - this.emitLine(annotation), + this.emitLine(annotation) ); this.emitLine("public ", rendered, " ", getterName, "() { return ", name, "; }"); this.annotationsForAccessor(c, className, name, jsonName, p, true).forEach(annotation => - this.emitLine(annotation), + this.emitLine(annotation) ); this.emitLine("public void ", setterName, "(", rendered, " value) { this.", name, " = value; }"); }); @@ -865,22 +867,22 @@ export class JavaRenderer extends ConvenienceRenderer { this.finishFile(); } - protected unionField (u: UnionType, t: Type, withIssues = false): { fieldName: Sourcelike, fieldType: Sourcelike, } { + protected unionField(u: UnionType, t: Type, withIssues = false): { fieldName: Sourcelike; fieldType: Sourcelike } { const fieldType = this.javaType(true, t, withIssues); // FIXME: "Value" should be part of the name. const fieldName = [this.nameForUnionMember(u, t), "Value"]; return { fieldType, fieldName }; } - protected emitUnionAttributes (_u: UnionType, _unionName: Name): void { + protected emitUnionAttributes(_u: UnionType, _unionName: Name): void { // empty } - protected emitUnionSerializer (_u: UnionType, _unionName: Name): void { + protected emitUnionSerializer(_u: UnionType, _unionName: Name): void { // empty } - protected emitUnionDefinition (u: UnionType, unionName: Name): void { + protected emitUnionDefinition(u: UnionType, unionName: Name): void { const imports = [...this.importsForType(u), ...this.importsForUnionMembers(u)]; this.emitFileHeader(unionName, imports); @@ -899,15 +901,15 @@ export class JavaRenderer extends ConvenienceRenderer { this.finishFile(); } - protected emitEnumSerializationAttributes (_e: EnumType) { + protected emitEnumSerializationAttributes(_e: EnumType) { // Empty } - protected emitEnumDeserializationAttributes (_e: EnumType) { + protected emitEnumDeserializationAttributes(_e: EnumType) { // Empty } - protected emitEnumDefinition (e: EnumType, enumName: Name): void { + protected emitEnumDefinition(e: EnumType, enumName: Name): void { this.emitFileHeader(enumName, this.importsForType(e)); this.emitDescription(this.descriptionForType(e)); const caseNames: Sourcelike[] = []; @@ -925,7 +927,7 @@ export class JavaRenderer extends ConvenienceRenderer { this.emitLine("switch (this) {"); this.indent(() => { this.forEachEnumCase(e, "none", (name, jsonName) => { - this.emitLine("case ", name, ": return \"", stringEscape(jsonName), "\";"); + this.emitLine("case ", name, ': return "', stringEscape(jsonName), '";'); }); }); this.emitLine("}"); @@ -936,29 +938,29 @@ export class JavaRenderer extends ConvenienceRenderer { this.emitEnumDeserializationAttributes(e); this.emitBlock(["public static ", enumName, " forValue(String value) throws IOException"], () => { this.forEachEnumCase(e, "none", (name, jsonName) => { - this.emitLine("if (value.equals(\"", stringEscape(jsonName), "\")) return ", name, ";"); + this.emitLine('if (value.equals("', stringEscape(jsonName), '")) return ', name, ";"); }); - this.emitLine("throw new IOException(\"Cannot deserialize ", enumName, "\");"); + this.emitLine('throw new IOException("Cannot deserialize ', enumName, '");'); }); }); this.finishFile(); } - protected emitSourceStructure (): void { + protected emitSourceStructure(): void { this.forEachNamedType( "leading-and-interposing", (c: ClassType, n: Name) => this.emitClassDefinition(c, n), (e, n) => this.emitEnumDefinition(e, n), - (u, n) => this.emitUnionDefinition(u, n), + (u, n) => this.emitUnionDefinition(u, n) ); } } export class JacksonRenderer extends JavaRenderer { - constructor ( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - options: OptionValues, + options: OptionValues ) { super(targetLanguage, renderContext, options); } @@ -972,27 +974,27 @@ export class JacksonRenderer extends JavaRenderer { "JsonParser", "JsonProcessingException", "DeserializationContext", - "SerializerProvider", + "SerializerProvider" ]; - protected emitClassAttributes (c: ClassType, _className: Name): void { + protected emitClassAttributes(c: ClassType, _className: Name): void { if (c.getProperties().size === 0) this.emitLine("@JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.NONE)"); super.emitClassAttributes(c, _className); } - protected annotationsForAccessor ( + protected annotationsForAccessor( _c: ClassType, _className: Name, _propertyName: Name, jsonName: string, p: ClassProperty, - _isSetter: boolean, + _isSetter: boolean ): string[] { const superAnnotations = super.annotationsForAccessor(_c, _className, _propertyName, jsonName, p, _isSetter); - const annotations: string[] = ["@JsonProperty(\"" + stringEscape(jsonName) + "\")"]; + const annotations: string[] = ['@JsonProperty("' + stringEscape(jsonName) + '")']; switch (p.type.kind) { case "date-time": @@ -1011,7 +1013,7 @@ export class JacksonRenderer extends JavaRenderer { return [...superAnnotations, ...annotations]; } - protected importsForType (t: ClassType | UnionType | EnumType): string[] { + protected importsForType(t: ClassType | UnionType | EnumType): string[] { if (t instanceof ClassType) { const imports = super.importsForType(t); imports.push("com.fasterxml.jackson.annotation.*"); @@ -1024,7 +1026,7 @@ export class JacksonRenderer extends JavaRenderer { "java.io.IOException", "com.fasterxml.jackson.core.*", "com.fasterxml.jackson.databind.*", - "com.fasterxml.jackson.databind.annotation.*", + "com.fasterxml.jackson.databind.annotation.*" ); if (this._options.useList) { imports.push("com.fasterxml.jackson.core.type.*"); @@ -1042,12 +1044,12 @@ export class JacksonRenderer extends JavaRenderer { return assertNever(t); } - protected emitUnionAttributes (_u: UnionType, unionName: Name): void { + protected emitUnionAttributes(_u: UnionType, unionName: Name): void { this.emitLine("@JsonDeserialize(using = ", unionName, ".Deserializer.class)"); this.emitLine("@JsonSerialize(using = ", unionName, ".Serializer.class)"); } - protected emitUnionSerializer (u: UnionType, unionName: Name): void { + protected emitUnionSerializer(u: UnionType, unionName: Name): void { const stringBasedObjects: TypeKind[] = ["uuid", "time", "date", "date-time"]; const tokenCase = (tokenType: string): void => { @@ -1064,7 +1066,7 @@ export class JacksonRenderer extends JavaRenderer { const emitDeserializerCodeForStringObjects = ( fieldName: Sourcelike, kind: TypeKind, - parseFrom: string, + parseFrom: string ): void => { switch (kind) { case "date": @@ -1073,7 +1075,7 @@ export class JacksonRenderer extends JavaRenderer { fieldName, " = ", this._dateTimeProvider.convertStringToDate(parseFrom), - ";", + ";" ); break; @@ -1083,7 +1085,7 @@ export class JacksonRenderer extends JavaRenderer { fieldName, " = ", this._dateTimeProvider.convertStringToTime(parseFrom), - ";", + ";" ); break; @@ -1093,7 +1095,7 @@ export class JacksonRenderer extends JavaRenderer { fieldName, " = ", this._dateTimeProvider.convertStringToDateTime(parseFrom), - ";", + ";" ); break; case "uuid": @@ -1114,7 +1116,7 @@ export class JacksonRenderer extends JavaRenderer { fieldName, " = jsonParser.readValueAs(new TypeReference<", rendered, - ">() {});", + ">() {});" ); } else if (stringBasedObjects.some(stringBasedTypeKind => t.kind === stringBasedTypeKind)) { emitDeserializerCodeForStringObjects(fieldName, t.kind, variableFieldName); @@ -1249,7 +1251,7 @@ export class JacksonRenderer extends JavaRenderer { [ "public ", unionName, - " deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException", + " deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException" ], () => { this.emitLine(unionName, " value = new ", unionName, "();"); @@ -1262,11 +1264,11 @@ export class JacksonRenderer extends JavaRenderer { emitDeserializer(["START_OBJECT"], "class"); emitDeserializer(["START_OBJECT"], "map"); this.indent(() => - this.emitLine("default: throw new IOException(\"Cannot deserialize ", unionName, "\");"), + this.emitLine('default: throw new IOException("Cannot deserialize ', unionName, '");') ); this.emitLine("}"); this.emitLine("return value;"); - }, + } ); }); this.ensureBlankLine(); @@ -1276,7 +1278,7 @@ export class JacksonRenderer extends JavaRenderer { [ "public void serialize(", unionName, - " obj, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException", + " obj, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException" ], () => { for (const t of nonNulls) { @@ -1286,22 +1288,22 @@ export class JacksonRenderer extends JavaRenderer { if (maybeNull !== null) { this.emitLine("jsonGenerator.writeNull();"); } else { - this.emitLine("throw new IOException(\"", unionName, " must not be null\");"); + this.emitLine('throw new IOException("', unionName, ' must not be null");'); } - }, + } ); }); } - protected emitEnumSerializationAttributes (_e: EnumType) { + protected emitEnumSerializationAttributes(_e: EnumType) { this.emitLine("@JsonValue"); } - protected emitEnumDeserializationAttributes (_e: EnumType) { + protected emitEnumDeserializationAttributes(_e: EnumType) { this.emitLine("@JsonCreator"); } - protected emitOffsetDateTimeConverterModule (): void { + protected emitOffsetDateTimeConverterModule(): void { this.emitLine("SimpleModule module = new SimpleModule();"); if (this._dateTimeProvider.shouldEmitDateTimeConverter) { @@ -1310,7 +1312,7 @@ export class JacksonRenderer extends JavaRenderer { this._dateTimeProvider.dateTimeType, ".class, new JsonDeserializer<", this._dateTimeProvider.dateTimeType, - ">() {", + ">() {" ); this.indent(() => { this.emitLine("@Override"); @@ -1319,12 +1321,12 @@ export class JacksonRenderer extends JavaRenderer { "public ", this._dateTimeProvider.dateTimeType, " deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) ", - "throws IOException, JsonProcessingException", + "throws IOException, JsonProcessingException" ], () => { this.emitLine("String value = jsonParser.getText();"); this.emitLine("return ", this._dateTimeProvider.convertStringToDateTime("value"), ";"); - }, + } ); }); this.emitLine("});"); @@ -1336,7 +1338,7 @@ export class JacksonRenderer extends JavaRenderer { this._dateTimeProvider.timeType, ".class, new JsonDeserializer<", this._dateTimeProvider.timeType, - ">() {", + ">() {" ); this.indent(() => { this.emitLine("@Override"); @@ -1345,12 +1347,12 @@ export class JacksonRenderer extends JavaRenderer { "public ", this._dateTimeProvider.timeType, " deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) ", - "throws IOException, JsonProcessingException", + "throws IOException, JsonProcessingException" ], () => { this.emitLine("String value = jsonParser.getText();"); this.emitLine("return ", this._dateTimeProvider.convertStringToTime("value"), ";"); - }, + } ); }); this.emitLine("});"); @@ -1362,7 +1364,7 @@ export class JacksonRenderer extends JavaRenderer { this._dateTimeProvider.dateType, ".class, new JsonDeserializer<", this._dateTimeProvider.dateType, - ">() {", + ">() {" ); this.indent(() => { this.emitLine("@Override"); @@ -1371,12 +1373,12 @@ export class JacksonRenderer extends JavaRenderer { "public ", this._dateTimeProvider.dateType, " deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) ", - "throws IOException, JsonProcessingException", + "throws IOException, JsonProcessingException" ], () => { this.emitLine("String value = jsonParser.getText();"); this.emitLine("return ", this._dateTimeProvider.convertStringToDate("value"), ";"); - }, + } ); }); this.emitLine("});"); @@ -1385,7 +1387,7 @@ export class JacksonRenderer extends JavaRenderer { this.emitLine("mapper.registerModule(module);"); } - protected emitConverterClass (): void { + protected emitConverterClass(): void { this.startFile(this._converterClassname); this.emitCommentLines([ "To use this code, add the following Maven dependency to your project:", @@ -1397,7 +1399,7 @@ export class JacksonRenderer extends JavaRenderer { : "", "", "Import this package:", - "", + "" ]); this.emitLine("// import ", this._options.packageName, ".Converter;"); this.emitMultiline(`// @@ -1409,7 +1411,7 @@ export class JacksonRenderer extends JavaRenderer { this.javaType(false, t), " data = Converter.", this.decoderName(name), - "(jsonString);", + "(jsonString);" ); }); this.ensureBlankLine(); @@ -1419,7 +1421,7 @@ export class JacksonRenderer extends JavaRenderer { "com.fasterxml.jackson.databind.module.SimpleModule", "com.fasterxml.jackson.core.JsonParser", "com.fasterxml.jackson.core.JsonProcessingException", - "java.util.*", + "java.util.*" ].concat(this._dateTimeProvider.converterImports); this.emitPackageAndImports(imports); this.ensureBlankLine(); @@ -1436,11 +1438,11 @@ export class JacksonRenderer extends JavaRenderer { topLevelTypeRendered, " ", this.decoderName(topLevelName), - "(String json) throws IOException", + "(String json) throws IOException" ], () => { this.emitLine("return ", this.readerGetterName(topLevelName), "().readValue(json);"); - }, + } ); this.ensureBlankLine(); this.emitBlock( @@ -1449,11 +1451,11 @@ export class JacksonRenderer extends JavaRenderer { this.encoderName(topLevelName), "(", topLevelTypeRendered, - " obj) throws JsonProcessingException", + " obj) throws JsonProcessingException" ], () => { this.emitLine("return ", this.writerGetterName(topLevelName), "().writeValueAsString(obj);"); - }, + } ); }); this.forEachTopLevel("leading-and-interposing", (topLevelType, topLevelName) => { @@ -1473,7 +1475,7 @@ export class JacksonRenderer extends JavaRenderer { this.emitOffsetDateTimeConverterModule(); this.emitLine(readerName, " = mapper.readerFor(", renderedForClass, ".class);"); this.emitLine(writerName, " = mapper.writerFor(", renderedForClass, ".class);"); - }, + } ); this.ensureBlankLine(); this.emitBlock(["private static ObjectReader ", this.readerGetterName(topLevelName), "()"], () => { @@ -1482,7 +1484,7 @@ export class JacksonRenderer extends JavaRenderer { readerName, " == null) ", this.methodName("instantiate", "Mapper", topLevelName), - "();", + "();" ); this.emitLine("return ", readerName, ";"); }); @@ -1493,7 +1495,7 @@ export class JacksonRenderer extends JavaRenderer { writerName, " == null) ", this.methodName("instantiate", "Mapper", topLevelName), - "();", + "();" ); this.emitLine("return ", writerName, ";"); }); @@ -1502,7 +1504,7 @@ export class JacksonRenderer extends JavaRenderer { this.finishFile(); } - protected emitSourceStructure (): void { + protected emitSourceStructure(): void { this.emitConverterClass(); super.emitSourceStructure(); } diff --git a/packages/quicktype-core/src/language/JavaScript.ts b/packages/quicktype-core/src/language/JavaScript.ts index 1936de7b2..5b1b1b7c8 100644 --- a/packages/quicktype-core/src/language/JavaScript.ts +++ b/packages/quicktype-core/src/language/JavaScript.ts @@ -6,7 +6,7 @@ import { type Type, type ClassProperty, type ClassType, - type ObjectType, + type ObjectType } from "../Type"; import { matchType, directlyReachableSingleNamedType } from "../TypeUtils"; import { acronymOption, acronymStyle, AcronymStyleOptions } from "../support/Acronyms"; @@ -20,18 +20,18 @@ import { combineWords, firstUpperWordStyle, camelCase, - allLowerWordStyle, + allLowerWordStyle } from "../support/Strings"; import { panic } from "../support/Support"; -import { type Sourcelike} from "../Source"; +import { type Sourcelike } from "../Source"; import { modifySource } from "../Source"; -import { type Namer, type Name} from "../Naming"; +import { type Namer, type Name } from "../Naming"; import { funPrefixNamer } from "../Naming"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; import { TargetLanguage } from "../TargetLanguage"; import { type StringTypeMapping } from "../TypeBuilder"; -import { type Option, type OptionValues} from "../RendererOptions"; +import { type Option, type OptionValues } from "../RendererOptions"; import { BooleanOption, getOptionValues, EnumOption } from "../RendererOptions"; import { type RenderContext } from "../Renderer"; import { isES3IdentifierPart, isES3IdentifierStart } from "./JavaScriptUnicodeMaps"; @@ -43,7 +43,7 @@ export const javaScriptOptions = { "runtime-typecheck-ignore-unknown-properties", "Ignore unknown properties when verifying at runtime", false, - "secondary", + "secondary" ), converters: convertersOption(), rawType: new EnumOption<"json" | "any">( @@ -51,11 +51,11 @@ export const javaScriptOptions = { "Type of raw input (json by default)", [ ["json", "json"], - ["any", "any"], + ["any", "any"] ], "json", - "secondary", - ), + "secondary" + ) }; export interface JavaScriptTypeAnnotations { @@ -69,21 +69,21 @@ export interface JavaScriptTypeAnnotations { } export class JavaScriptTargetLanguage extends TargetLanguage { - constructor (displayName = "JavaScript", names: string[] = ["javascript", "js", "jsx"], extension = "js") { + public constructor(displayName = "JavaScript", names: string[] = ["javascript", "js", "jsx"], extension = "js") { super(displayName, names, extension); } - protected getOptions (): Array> { + protected getOptions(): Array> { return [ javaScriptOptions.runtimeTypecheck, javaScriptOptions.runtimeTypecheckIgnoreUnknownProperties, javaScriptOptions.acronymStyle, javaScriptOptions.converters, - javaScriptOptions.rawType, + javaScriptOptions.rawType ]; } - get stringTypeMapping (): StringTypeMapping { + public get stringTypeMapping(): StringTypeMapping { const mapping: Map = new Map(); const dateTimeType = "date-time"; mapping.set("date", dateTimeType); @@ -91,17 +91,17 @@ export class JavaScriptTargetLanguage extends TargetLanguage { return mapping; } - get supportsOptionalClassProperties (): boolean { + public get supportsOptionalClassProperties(): boolean { return true; } - get supportsFullObjectType (): boolean { + public get supportsFullObjectType(): boolean { return true; } - protected makeRenderer ( + protected makeRenderer( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any, }, + untypedOptionValues: { [name: string]: any } ): JavaScriptRenderer { return new JavaScriptRenderer(this, renderContext, getOptionValues(javaScriptOptions, untypedOptionValues)); } @@ -112,15 +112,15 @@ export const legalizeName = utf16LegalizeCharacters(isES3IdentifierPart); const identityNamingFunction = funPrefixNamer("properties", s => s); export class JavaScriptRenderer extends ConvenienceRenderer { - constructor ( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _jsOptions: OptionValues, + private readonly _jsOptions: OptionValues ) { super(targetLanguage, renderContext); } - protected nameStyle (original: string, upper: boolean): string { + protected nameStyle(original: string, upper: boolean): string { const acronyms = acronymStyle(this._jsOptions.acronymStyle); const words = splitIntoWords(original); return combineWords( @@ -131,58 +131,58 @@ export class JavaScriptRenderer extends ConvenienceRenderer { upper ? s => capitalize(acronyms(s)) : allLowerWordStyle, acronyms, "", - isES3IdentifierStart, + isES3IdentifierStart ); } - protected makeNamedTypeNamer (): Namer { + protected makeNamedTypeNamer(): Namer { return funPrefixNamer("types", s => this.nameStyle(s, true)); } - protected namerForObjectProperty (): Namer { + protected namerForObjectProperty(): Namer { return identityNamingFunction; } - protected makeUnionMemberNamer (): null { + protected makeUnionMemberNamer(): null { return null; } - protected makeEnumCaseNamer (): Namer { + protected makeEnumCaseNamer(): Namer { return funPrefixNamer("enum-cases", s => this.nameStyle(s, true)); } - protected namedTypeToNameForTopLevel (type: Type): Type | undefined { + protected namedTypeToNameForTopLevel(type: Type): Type | undefined { return directlyReachableSingleNamedType(type); } - protected makeNameForProperty ( + protected makeNameForProperty( c: ClassType, className: Name, p: ClassProperty, jsonName: string, - _assignedName: string | undefined, + _assignedName: string | undefined ): Name | undefined { // Ignore the assigned name return super.makeNameForProperty(c, className, p, jsonName, undefined); } - protected emitDescriptionBlock (lines: Sourcelike[]): void { + protected emitDescriptionBlock(lines: Sourcelike[]): void { this.emitCommentLines(lines, { lineStart: " * ", beforeComment: "/**", afterComment: " */" }); } - typeMapTypeFor (t: Type): Sourcelike { + private typeMapTypeFor(t: Type): Sourcelike { if (["class", "object", "enum"].includes(t.kind)) { - return ["r(\"", this.nameForNamedType(t), "\")"]; + return ['r("', this.nameForNamedType(t), '")']; } return matchType( t, - _anyType => "\"any\"", + _anyType => '"any"', _nullType => "null", _boolType => "true", _integerType => "0", _doubleType => "3.14", - _stringType => "\"\"", + _stringType => '""', arrayType => ["a(", this.typeMapTypeFor(arrayType.items), ")"], _classType => panic("We handled this above"), mapType => ["m(", this.typeMapTypeFor(mapType.values), ")"], @@ -196,12 +196,12 @@ export class JavaScriptRenderer extends ConvenienceRenderer { return "Date"; } - return "\"\""; - }, + return '""'; + } ); } - typeMapTypeForProperty (p: ClassProperty): Sourcelike { + private typeMapTypeForProperty(p: ClassProperty): Sourcelike { const typeMap = this.typeMapTypeFor(p.type); if (!p.isOptional) { return typeMap; @@ -210,13 +210,13 @@ export class JavaScriptRenderer extends ConvenienceRenderer { return ["u(undefined, ", typeMap, ")"]; } - emitBlock (source: Sourcelike, end: Sourcelike, emit: () => void) { + protected emitBlock(source: Sourcelike, end: Sourcelike, emit: () => void) { this.emitLine(source, "{"); this.indent(emit); this.emitLine("}", end); } - emitTypeMap () { + private emitTypeMap() { const { any: anyAnnotation } = this.typeAnnotations; this.emitBlock(`const typeMap${anyAnnotation} = `, ";", () => { @@ -224,24 +224,24 @@ export class JavaScriptRenderer extends ConvenienceRenderer { const additionalProperties = t.getAdditionalProperties(); const additional = additionalProperties !== undefined ? this.typeMapTypeFor(additionalProperties) : "false"; - this.emitLine("\"", name, "\": o(["); + this.emitLine('"', name, '": o(['); this.indent(() => { this.forEachClassProperty(t, "none", (propName, jsonName, property) => { this.emitLine( - "{ json: \"", + '{ json: "', utf16StringEscape(jsonName), - "\", js: \"", + '", js: "', modifySource(utf16StringEscape, propName), - "\", typ: ", + '", typ: ', this.typeMapTypeForProperty(property), - " },", + " }," ); }); }); this.emitLine("], ", additional, "),"); }); this.forEachEnum("none", (e, name) => { - this.emitLine("\"", name, "\": ["); + this.emitLine('"', name, '": ['); this.indent(() => { this.forEachEnumCase(e, "none", (_caseName, jsonName) => { this.emitLine(`"${utf16StringEscape(jsonName)}",`); @@ -252,32 +252,32 @@ export class JavaScriptRenderer extends ConvenienceRenderer { }); } - protected deserializerFunctionName (name: Name): Sourcelike { + protected deserializerFunctionName(name: Name): Sourcelike { return ["to", name]; } - protected deserializerFunctionLine (_t: Type, name: Name): Sourcelike { + protected deserializerFunctionLine(_t: Type, name: Name): Sourcelike { return ["function ", this.deserializerFunctionName(name), "(json)"]; } - protected serializerFunctionName (name: Name): Sourcelike { + protected serializerFunctionName(name: Name): Sourcelike { const camelCaseName = modifySource(camelCase, name); return [camelCaseName, "ToJson"]; } - protected serializerFunctionLine (_t: Type, name: Name): Sourcelike { + protected serializerFunctionLine(_t: Type, name: Name): Sourcelike { return ["function ", this.serializerFunctionName(name), "(value)"]; } - protected get moduleLine (): string | undefined { + protected get moduleLine(): string | undefined { return undefined; } - protected get castFunctionLines (): [string, string] { + protected get castFunctionLines(): [string, string] { return ["function cast(val, typ)", "function uncast(val, typ)"]; } - protected get typeAnnotations (): JavaScriptTypeAnnotations { + protected get typeAnnotations(): JavaScriptTypeAnnotations { return { any: "", anyArray: "", @@ -285,11 +285,11 @@ export class JavaScriptRenderer extends ConvenienceRenderer { string: "", stringArray: "", boolean: "", - never: "", + never: "" }; } - protected emitConvertModuleBody (): void { + protected emitConvertModuleBody(): void { const converter = (t: Type, name: Name) => { const typeMap = this.typeMapTypeFor(t); this.emitBlock([this.deserializerFunctionLine(t, name), " "], "", () => { @@ -330,7 +330,7 @@ export class JavaScriptRenderer extends ConvenienceRenderer { } } - protected emitConvertModuleHelpers (): void { + protected emitConvertModuleHelpers(): void { if (this._jsOptions.runtimeTypecheck) { const { any: anyAnnotation, @@ -338,7 +338,7 @@ export class JavaScriptRenderer extends ConvenienceRenderer { anyMap: anyMapAnnotation, string: stringAnnotation, stringArray: stringArrayAnnotation, - never: neverAnnotation, + never: neverAnnotation } = this.typeAnnotations; this.ensureBlankLine(); this @@ -434,10 +434,10 @@ function transform(val${anyAnnotation}, typ${anyAnnotation}, getProps${anyAnnota Object.getOwnPropertyNames(val).forEach(key => { if (!Object.prototype.hasOwnProperty.call(props, key)) { result[key] = ${ - this._jsOptions.runtimeTypecheckIgnoreUnknownProperties - ? "val[key]" - : "transform(val[key], additional, getProps, key, ref)" -}; + this._jsOptions.runtimeTypecheckIgnoreUnknownProperties + ? "val[key]" + : "transform(val[key], additional, getProps, key, ref)" + }; } }); return result; @@ -502,14 +502,14 @@ function r(name${stringAnnotation}) { } } - protected emitConvertModule (): void { + protected emitConvertModule(): void { this.ensureBlankLine(); this.emitMultiline( - `// Converts JSON ${this._jsOptions.rawType === "json" ? "strings" : "types"} to/from your types`, + `// Converts JSON ${this._jsOptions.rawType === "json" ? "strings" : "types"} to/from your types` ); if (this._jsOptions.runtimeTypecheck) { this.emitMultiline( - `// and asserts the results${this._jsOptions.rawType === "json" ? " of JSON.parse" : ""} at runtime`, + `// and asserts the results${this._jsOptions.rawType === "json" ? " of JSON.parse" : ""} at runtime` ); } @@ -521,15 +521,15 @@ function r(name${stringAnnotation}) { } } - protected emitTypes (): void { + protected emitTypes(): void { return; } - protected emitUsageImportComment (): void { - this.emitLine("// const Convert = require(\"./file\");"); + protected emitUsageImportComment(): void { + this.emitLine('// const Convert = require("./file");'); } - protected emitUsageComments (): void { + protected emitUsageComments(): void { this.emitMultiline(`// To parse this data: //`); @@ -546,20 +546,20 @@ function r(name${stringAnnotation}) { } } - protected emitModuleExports (): void { + protected emitModuleExports(): void { this.ensureBlankLine(); this.emitBlock("module.exports = ", ";", () => { this.forEachTopLevel("none", (_, name) => { const serializer = this.serializerFunctionName(name); const deserializer = this.deserializerFunctionName(name); - this.emitLine("\"", serializer, "\": ", serializer, ","); - this.emitLine("\"", deserializer, "\": ", deserializer, ","); + this.emitLine('"', serializer, '": ', serializer, ","); + this.emitLine('"', deserializer, '": ', deserializer, ","); }); }); } - protected emitSourceStructure () { + protected emitSourceStructure() { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } else { diff --git a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts index 7c8927f24..3b9348f0b 100644 --- a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts +++ b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts @@ -1,26 +1,13 @@ import { TargetLanguage } from "../TargetLanguage"; -import { type Option, type OptionValues} from "../RendererOptions"; +import { type Option, type OptionValues } from "../RendererOptions"; import { getOptionValues, EnumOption } from "../RendererOptions"; import { type RenderContext } from "../Renderer"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; import { type Name, type Namer } from "../Naming"; import { funPrefixNamer } from "../Naming"; import { acronymOption, acronymStyle, AcronymStyleOptions } from "../support/Acronyms"; -import { - type ClassProperty, - type ClassType, - type ObjectType, - type Sourcelike, - type Type, -} from ".."; -import { - capitalize, - combineWords, - firstUpperWordStyle, - matchType, - panic, - splitIntoWords, -} from ".."; +import { type ClassProperty, type ClassType, type ObjectType, type Sourcelike, type Type } from ".."; +import { capitalize, combineWords, firstUpperWordStyle, matchType, panic, splitIntoWords } from ".."; import { allLowerWordStyle, utf16StringEscape } from "../support/Strings"; import { isES3IdentifierStart } from "./JavaScriptUnicodeMaps"; import { legalizeName } from "./JavaScript"; @@ -37,29 +24,33 @@ export const javaScriptPropTypesOptions = { "Which module system to use", [ ["common-js", false], - ["es6", true], + ["es6", true] ], - "es6", - ), + "es6" + ) }; export class JavaScriptPropTypesTargetLanguage extends TargetLanguage { - protected getOptions (): Array> { + protected getOptions(): Array> { return [javaScriptPropTypesOptions.acronymStyle, javaScriptPropTypesOptions.converters]; } - constructor (displayName = "JavaScript PropTypes", names: string[] = ["javascript-prop-types"], extension = "js") { + public constructor( + displayName = "JavaScript PropTypes", + names: string[] = ["javascript-prop-types"], + extension = "js" + ) { super(displayName, names, extension); } - protected makeRenderer ( + protected makeRenderer( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any, }, + untypedOptionValues: { [name: string]: any } ): JavaScriptPropTypesRenderer { return new JavaScriptPropTypesRenderer( this, renderContext, - getOptionValues(javaScriptPropTypesOptions, untypedOptionValues), + getOptionValues(javaScriptPropTypesOptions, untypedOptionValues) ); } } @@ -67,15 +58,15 @@ export class JavaScriptPropTypesTargetLanguage extends TargetLanguage { const identityNamingFunction = funPrefixNamer("properties", s => s); export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { - constructor ( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _jsOptions: OptionValues, + private readonly _jsOptions: OptionValues ) { super(targetLanguage, renderContext); } - protected nameStyle (original: string, upper: boolean): string { + protected nameStyle(original: string, upper: boolean): string { const acronyms = acronymStyle(this._jsOptions.acronymStyle); const words = splitIntoWords(original); return combineWords( @@ -86,42 +77,42 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { upper ? s => capitalize(acronyms(s)) : allLowerWordStyle, acronyms, "", - isES3IdentifierStart, + isES3IdentifierStart ); } - protected makeNamedTypeNamer (): Namer { + protected makeNamedTypeNamer(): Namer { return funPrefixNamer("types", s => this.nameStyle(s, true)); } - protected namerForObjectProperty (): Namer { + protected namerForObjectProperty(): Namer { return identityNamingFunction; } - protected makeUnionMemberNamer (): null { + protected makeUnionMemberNamer(): null { return null; } - protected makeEnumCaseNamer (): Namer { + protected makeEnumCaseNamer(): Namer { return funPrefixNamer("enum-cases", s => this.nameStyle(s, false)); } - protected namedTypeToNameForTopLevel (type: Type): Type | undefined { + protected namedTypeToNameForTopLevel(type: Type): Type | undefined { return directlyReachableSingleNamedType(type); } - protected makeNameForProperty ( + protected makeNameForProperty( c: ClassType, className: Name, p: ClassProperty, jsonName: string, - _assignedName: string | undefined, + _assignedName: string | undefined ): Name | undefined { // Ignore the assigned name return super.makeNameForProperty(c, className, p, jsonName, undefined); } - typeMapTypeFor (t: Type, required = true): Sourcelike { + private typeMapTypeFor(t: Type, required = true): Sourcelike { if (["class", "object", "enum"].includes(t.kind)) { return ["_", this.nameForNamedType(t)]; } @@ -140,13 +131,13 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { _enumType => panic("Should already be handled."), unionType => { const children = Array.from(unionType.getChildren()).map((type: Type) => - this.typeMapTypeFor(type, false), + this.typeMapTypeFor(type, false) ); return ["PropTypes.oneOfType([", ...arrayIntercalate(", ", children), "])"]; }, _transformedStringType => { return "PropTypes.string"; - }, + } ); if (required) { @@ -156,11 +147,11 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { return match; } - typeMapTypeForProperty (p: ClassProperty): Sourcelike { + private typeMapTypeForProperty(p: ClassProperty): Sourcelike { return this.typeMapTypeFor(p.type); } - private importStatement (lhs: Sourcelike, moduleName: Sourcelike): Sourcelike { + private importStatement(lhs: Sourcelike, moduleName: Sourcelike): Sourcelike { if (this._jsOptions.moduleSystem) { return ["import ", lhs, " from ", moduleName, ";"]; } else { @@ -168,7 +159,7 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { } } - protected emitUsageComments (): void { + protected emitUsageComments(): void { // FIXME: Use the correct type name this.emitCommentLines( [ @@ -182,24 +173,24 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { "", "MyComponent.propTypes = {", " input: MyShape", - "};", + "};" ], - { lineStart: "// " }, + { lineStart: "// " } ); } - protected emitBlock (source: Sourcelike, end: Sourcelike, emit: () => void) { + protected emitBlock(source: Sourcelike, end: Sourcelike, emit: () => void) { this.emitLine(source, "{"); this.indent(emit); this.emitLine("}", end); } - protected emitImports (): void { + protected emitImports(): void { this.ensureBlankLine(); - this.emitLine(this.importStatement("PropTypes", "\"prop-types\"")); + this.emitLine(this.importStatement("PropTypes", '"prop-types"')); } - private emitExport (name: Sourcelike, value: Sourcelike): void { + private emitExport(name: Sourcelike, value: Sourcelike): void { if (this._jsOptions.moduleSystem) { this.emitLine("export const ", name, " = ", value, ";"); } else { @@ -207,7 +198,7 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { } } - protected emitTypes (): void { + protected emitTypes(): void { this.ensureBlankLine(); this.forEachObject("none", (_type: ObjectType, name: Name) => { @@ -282,7 +273,7 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { }); } - private emitObject (name: Name, t: ObjectType) { + private emitObject(name: Name, t: ObjectType) { this.ensureBlankLine(); this.emitLine("_", name, " = PropTypes.shape({"); this.indent(() => { @@ -293,7 +284,7 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { this.emitLine("});"); } - protected emitSourceStructure (): void { + protected emitSourceStructure(): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } else { diff --git a/packages/quicktype-core/src/language/JavaScriptUnicodeMaps.ts b/packages/quicktype-core/src/language/JavaScriptUnicodeMaps.ts index e818aaeb3..0e75bbfaa 100644 --- a/packages/quicktype-core/src/language/JavaScriptUnicodeMaps.ts +++ b/packages/quicktype-core/src/language/JavaScriptUnicodeMaps.ts @@ -1,6 +1,7 @@ +/* eslint-disable */ // Taken from https://github.com/Microsoft/TypeScript -function lookupInUnicodeMap (code: number, map: readonly number[]): boolean { +function lookupInUnicodeMap(code: number, map: readonly number[]): boolean { // Bail out quickly if it couldn't possibly be in the map. if (code < map[0]) { return false; @@ -45,24 +46,24 @@ const enum CharacterCodes { Z = 0x5a } -export function isES3IdentifierStart (ch: number): boolean { +export function isES3IdentifierStart(ch: number): boolean { return ( - ch >= CharacterCodes.A && ch <= CharacterCodes.Z || - ch >= CharacterCodes.a && ch <= CharacterCodes.z || + (ch >= CharacterCodes.A && ch <= CharacterCodes.Z) || + (ch >= CharacterCodes.a && ch <= CharacterCodes.z) || ch === CharacterCodes.$ || ch === CharacterCodes._ || - ch > CharacterCodes.maxAsciiCharacter && lookupInUnicodeMap(ch, unicodeES3IdentifierStart) + (ch > CharacterCodes.maxAsciiCharacter && lookupInUnicodeMap(ch, unicodeES3IdentifierStart)) ); } -export function isES3IdentifierPart (ch: number): boolean { +export function isES3IdentifierPart(ch: number): boolean { return ( - ch >= CharacterCodes.A && ch <= CharacterCodes.Z || - ch >= CharacterCodes.a && ch <= CharacterCodes.z || - ch >= CharacterCodes._0 && ch <= CharacterCodes._9 || + (ch >= CharacterCodes.A && ch <= CharacterCodes.Z) || + (ch >= CharacterCodes.a && ch <= CharacterCodes.z) || + (ch >= CharacterCodes._0 && ch <= CharacterCodes._9) || ch === CharacterCodes.$ || ch === CharacterCodes._ || - ch > CharacterCodes.maxAsciiCharacter && lookupInUnicodeMap(ch, unicodeES3IdentifierPart) + (ch > CharacterCodes.maxAsciiCharacter && lookupInUnicodeMap(ch, unicodeES3IdentifierPart)) ); } @@ -113,7 +114,7 @@ const unicodeES3IdentifierStart = [ 40960, 42124, 44032, 55203, 63744, 64045, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65138, 65140, 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479, - 65482, 65487, 65490, 65495, 65498, 65500, + 65482, 65487, 65490, 65495, 65498, 65500 ]; const unicodeES3IdentifierPart = [ 170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 543, 546, 563, 592, 685, 688, 696, 699, 705, 720, 721, 736, @@ -152,5 +153,5 @@ const unicodeES3IdentifierPart = [ 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65056, 65059, 65075, 65076, 65101, 65103, 65136, 65138, 65140, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65381, 65470, 65474, - 65479, 65482, 65487, 65490, 65495, 65498, 65500, + 65479, 65482, 65487, 65490, 65495, 65498, 65500 ]; diff --git a/packages/quicktype-core/src/language/Kotlin.ts b/packages/quicktype-core/src/language/Kotlin.ts index d88b58060..b2f46b466 100644 --- a/packages/quicktype-core/src/language/Kotlin.ts +++ b/packages/quicktype-core/src/language/Kotlin.ts @@ -57,7 +57,7 @@ export const kotlinOptions = { }; export class KotlinTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super("Kotlin", ["kotlin"], "kt"); } @@ -65,11 +65,11 @@ export class KotlinTargetLanguage extends TargetLanguage { return [kotlinOptions.framework, kotlinOptions.acronymStyle, kotlinOptions.packageName]; } - get supportsOptionalClassProperties(): boolean { + public get supportsOptionalClassProperties(): boolean { return true; } - get supportsUnionsWithBothNumberTypes(): boolean { + public get supportsUnionsWithBothNumberTypes(): boolean { return true; } @@ -186,7 +186,7 @@ function stringEscape(s: string): string { } export class KotlinRenderer extends ConvenienceRenderer { - constructor( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, protected readonly _kotlinOptions: OptionValues @@ -455,7 +455,7 @@ export class KotlinRenderer extends ConvenienceRenderer { } export class KotlinKlaxonRenderer extends KotlinRenderer { - constructor( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, _kotlinOptions: OptionValues @@ -738,7 +738,7 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { } export class KotlinJacksonRenderer extends KotlinRenderer { - constructor( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, _kotlinOptions: OptionValues @@ -1012,7 +1012,7 @@ private fun ObjectMapper.convert(k: kotlin.reflect.KClass<*>, fromJson: (Jso * TODO: Union, Any, Top Level Array, Top Level Map */ export class KotlinXRenderer extends KotlinRenderer { - constructor( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, _kotlinOptions: OptionValues diff --git a/packages/quicktype-core/src/language/Objective-C.ts b/packages/quicktype-core/src/language/Objective-C.ts index 00235121c..e97381a00 100644 --- a/packages/quicktype-core/src/language/Objective-C.ts +++ b/packages/quicktype-core/src/language/Objective-C.ts @@ -4,9 +4,9 @@ import { TargetLanguage } from "../TargetLanguage"; import { type ClassProperty } from "../Type"; import { Type, ClassType, EnumType, ArrayType, MapType, UnionType } from "../Type"; import { matchType, nullableFromUnion, isAnyOrNull } from "../TypeUtils"; -import { type Name} from "../Naming"; +import { type Name } from "../Naming"; import { Namer, funPrefixNamer } from "../Naming"; -import { type Sourcelike} from "../Source"; +import { type Sourcelike } from "../Source"; import { modifySource } from "../Source"; import { splitIntoWords, @@ -19,7 +19,7 @@ import { stringEscape, addPrefixIfNecessary, repeatString, - fastIsUpperCase, + fastIsUpperCase } from "../support/Strings"; import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; @@ -32,7 +32,8 @@ import unicode from "unicode-properties"; export type MemoryAttribute = "assign" | "strong" | "copy"; export interface OutputFeatures { - implementation: boolean; interface: boolean; + implementation: boolean; + interface: boolean; } const DEBUG = false; @@ -42,38 +43,38 @@ export const objcOptions = { features: new EnumOption("features", "Interface and implementation", [ ["all", { interface: true, implementation: true }], ["interface", { interface: true, implementation: false }], - ["implementation", { interface: false, implementation: true }], + ["implementation", { interface: false, implementation: true }] ]), justTypes: new BooleanOption("just-types", "Plain types only", false), marshallingFunctions: new BooleanOption("functions", "C-style functions", false), classPrefix: new StringOption("class-prefix", "Class prefix", "PREFIX", DEFAULT_CLASS_PREFIX), - extraComments: new BooleanOption("extra-comments", "Extra comments", false), + extraComments: new BooleanOption("extra-comments", "Extra comments", false) }; export class ObjectiveCTargetLanguage extends TargetLanguage { - constructor () { + public constructor() { super("Objective-C", ["objc", "objective-c", "objectivec"], "m"); } - protected getOptions (): Array> { + protected getOptions(): Array> { return [ objcOptions.justTypes, objcOptions.classPrefix, objcOptions.features, objcOptions.extraComments, - objcOptions.marshallingFunctions, + objcOptions.marshallingFunctions ]; } - protected makeRenderer ( + protected makeRenderer( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any, }, + untypedOptionValues: { [name: string]: any } ): ObjectiveCRenderer { return new ObjectiveCRenderer(this, renderContext, getOptionValues(objcOptions, untypedOptionValues)); } } -function typeNameStyle (prefix: string, original: string): string { +function typeNameStyle(prefix: string, original: string): string { const words = splitIntoWords(original); const result = combineWords( words, @@ -83,12 +84,12 @@ function typeNameStyle (prefix: string, original: string): string { allUpperWordStyle, allUpperWordStyle, "", - isStartCharacter, + isStartCharacter ); return addPrefixIfNecessary(prefix, result); } -function propertyNameStyle (original: string, isBool = false): string { +function propertyNameStyle(original: string, isBool = false): string { // Objective-C developers are uncomfortable with property "id" // so we use an alternate name in this special case. if (original === "id") { @@ -119,7 +120,7 @@ function propertyNameStyle (original: string, isBool = false): string { allLowerWordStyle, allUpperWordStyle, "", - isStartCharacter, + isStartCharacter ); } @@ -171,7 +172,7 @@ const keywords = [ "unsigned", "void", "volatile", - "while", + "while" ]; const forbiddenPropertyNames = [ @@ -183,7 +184,7 @@ const forbiddenPropertyNames = [ "mutableCopy", "superclass", "debugDescription", - "new", + "new" ]; const booleanPrefixes = [ @@ -203,14 +204,14 @@ const booleanPrefixes = [ "requires", "require", "needs", - "need", + "need" ]; -function isStartCharacter (utf16Unit: number): boolean { +function isStartCharacter(utf16Unit: number): boolean { return unicode.isAlphabetic(utf16Unit) || utf16Unit === 0x5f; // underscore } -function isPartCharacter (utf16Unit: number): boolean { +function isPartCharacter(utf16Unit: number): boolean { const category: string = unicode.getCategory(utf16Unit); return ["Nd", "Pc", "Mn", "Mc"].includes(category) || isStartCharacter(utf16Unit); } @@ -220,7 +221,7 @@ const legalizeName = utf16LegalizeCharacters(isPartCharacter); const staticEnumValuesIdentifier = "values"; const forbiddenForEnumCases = ["new", staticEnumValuesIdentifier]; -function splitExtension (filename: string): [string, string] { +function splitExtension(filename: string): [string, string] { const i = filename.lastIndexOf("."); const extension = i !== -1 ? filename.split(".").pop() : "m"; filename = i !== -1 ? filename.slice(0, i) : filename; @@ -232,10 +233,10 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { private readonly _classPrefix: string; - constructor ( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues, + private readonly _options: OptionValues ) { super(targetLanguage, renderContext); @@ -248,7 +249,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { } } - private inferClassPrefix (name: string): string { + private inferClassPrefix(name: string): string { const l = name.length; let firstNonUpper = 0; while (firstNonUpper < l && fastIsUpperCase(name.charCodeAt(firstNonUpper))) { @@ -259,88 +260,88 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { return name.slice(0, firstNonUpper - 1); } - protected forbiddenNamesForGlobalNamespace (): string[] { + protected forbiddenNamesForGlobalNamespace(): string[] { return keywords; } - protected forbiddenForObjectProperties (_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { return { names: forbiddenPropertyNames, includeGlobalForbidden: true }; } - protected forbiddenForEnumCases (_e: EnumType, _enumName: Name): ForbiddenWordsInfo { + protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { return { names: forbiddenForEnumCases, includeGlobalForbidden: true }; } - protected makeNamedTypeNamer (): Namer { + protected makeNamedTypeNamer(): Namer { return funPrefixNamer("types", rawName => typeNameStyle(this._classPrefix, rawName)); } - protected namerForObjectProperty (_: ClassType, p: ClassProperty): Namer { + protected namerForObjectProperty(_: ClassType, p: ClassProperty): Namer { // TODO why is underscore being removed? return new Namer("properties", s => propertyNameStyle(s, p.type.kind === "bool"), [ "_", "the", "one", "some", - "another", + "another" ]); } - protected makeUnionMemberNamer (): null { + protected makeUnionMemberNamer(): null { return null; } - protected makeEnumCaseNamer (): Namer { + protected makeEnumCaseNamer(): Namer { return new Namer("enum-cases", propertyNameStyle, []); } - protected namedTypeToNameForTopLevel (type: Type): Type | undefined { + protected namedTypeToNameForTopLevel(type: Type): Type | undefined { return type; } - protected emitDescriptionBlock (lines: Sourcelike[]): void { + protected emitDescriptionBlock(lines: Sourcelike[]): void { this.emitCommentLines(lines, { lineStart: "/// " }); } - protected emitBlock (line: Sourcelike, f: () => void): void { + protected emitBlock(line: Sourcelike, f: () => void): void { this.emitLine(line, " {"); this.indent(f); this.emitLine("}"); } - protected emitMethod (declaration: Sourcelike, f: () => void) { + protected emitMethod(declaration: Sourcelike, f: () => void) { this.emitLine(declaration); this.emitLine("{"); this.indent(f); this.emitLine("}"); } - protected emitExtraComments (...comments: Sourcelike[]) { + protected emitExtraComments(...comments: Sourcelike[]) { if (!this._options.extraComments) return; for (const comment of comments) { this.emitLine("// ", comment); } } - protected startFile (basename: Sourcelike, extension: string): void { + protected startFile(basename: Sourcelike, extension: string): void { assert(this._currentFilename === undefined, "Previous file wasn't finished"); // FIXME: The filenames should actually be Sourcelikes, too this._currentFilename = `${this.sourcelikeToString(basename)}.${extension}`; } - protected finishFile (): void { + protected finishFile(): void { super.finishFile(defined(this._currentFilename)); this._currentFilename = undefined; } - protected memoryAttribute (t: Type, isNullable: boolean): MemoryAttribute { + protected memoryAttribute(t: Type, isNullable: boolean): MemoryAttribute { return matchType( t, _anyType => "copy", _nullType => "copy", - _boolType => isNullable ? "strong" : "assign", - _integerType => isNullable ? "strong" : "assign", - _doubleType => isNullable ? "strong" : "assign", + _boolType => (isNullable ? "strong" : "assign"), + _integerType => (isNullable ? "strong" : "assign"), + _doubleType => (isNullable ? "strong" : "assign"), _stringType => "copy", _arrayType => "copy", _classType => "strong", @@ -349,19 +350,19 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { unionType => { const nullable = nullableFromUnion(unionType); return nullable !== null ? this.memoryAttribute(nullable, true) : "copy"; - }, + } ); } - protected objcType (t: Type, nullableOrBoxed = false): [Sourcelike, string] { + protected objcType(t: Type, nullableOrBoxed = false): [Sourcelike, string] { return matchType<[Sourcelike, string]>( t, _anyType => ["id", ""], // For now, we're treating nulls just like any _nullType => ["id", ""], - _boolType => nullableOrBoxed ? ["NSNumber", " *"] : ["BOOL", ""], - _integerType => nullableOrBoxed ? ["NSNumber", " *"] : ["NSInteger", ""], - _doubleType => nullableOrBoxed ? ["NSNumber", " *"] : ["double", ""], + _boolType => (nullableOrBoxed ? ["NSNumber", " *"] : ["BOOL", ""]), + _integerType => (nullableOrBoxed ? ["NSNumber", " *"] : ["NSInteger", ""]), + _doubleType => (nullableOrBoxed ? ["NSNumber", " *"] : ["double", ""]), _stringType => ["NSString", " *"], arrayType => { const itemType = arrayType.items; @@ -379,11 +380,11 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { unionType => { const nullable = nullableFromUnion(unionType); return nullable !== null ? this.objcType(nullable, true) : ["id", ""]; - }, + } ); } - private jsonType (t: Type): [Sourcelike, string] { + private jsonType(t: Type): [Sourcelike, string] { return matchType<[Sourcelike, string]>( t, _anyType => ["id", ""], @@ -400,11 +401,11 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { unionType => { const nullable = nullableFromUnion(unionType); return nullable !== null ? this.jsonType(nullable) : ["id", ""]; - }, + } ); } - protected fromDynamicExpression (t: Type, ...dynamic: Sourcelike[]): Sourcelike { + protected fromDynamicExpression(t: Type, ...dynamic: Sourcelike[]): Sourcelike { return matchType( t, _anyType => dynamic, @@ -420,11 +421,11 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { unionType => { const nullable = nullableFromUnion(unionType); return nullable !== null ? this.fromDynamicExpression(nullable, dynamic) : dynamic; - }, + } ); } - protected toDynamicExpression (t: Type, typed: Sourcelike): Sourcelike { + protected toDynamicExpression(t: Type, typed: Sourcelike): Sourcelike { return matchType( t, _anyType => ["NSNullify(", typed, ")"], @@ -464,11 +465,11 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { // TODO support unions return typed; } - }, + } ); } - protected implicitlyConvertsFromJSON (t: Type): boolean { + protected implicitlyConvertsFromJSON(t: Type): boolean { if (t instanceof ClassType) { return false; } else if (t instanceof EnumType) { @@ -492,11 +493,11 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { } } - protected implicitlyConvertsToJSON (t: Type): boolean { + protected implicitlyConvertsToJSON(t: Type): boolean { return this.implicitlyConvertsFromJSON(t) && "bool" !== t.kind; } - protected emitPropertyAssignment (propertyName: Name, jsonName: string, propertyType: Type) { + protected emitPropertyAssignment(propertyName: Name, jsonName: string, propertyType: Type) { const name = ["_", propertyName]; matchType( propertyType, @@ -516,7 +517,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { name, ", ", ["λ(id x, ", this.fromDynamicExpression(itemType, "x"), ")"], - ");", + ");" ); }, enumType => this.emitLine(name, " = ", this.fromDynamicExpression(enumType, ["(id)", name]), ";"), @@ -528,43 +529,43 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { // TODO This is a union, but for now we just leave it dynamic this.emitLine(name, " = ", this.fromDynamicExpression(unionType, name), ";"); } - }, + } ); } - protected emitPrivateClassInterface (_: ClassType, name: Name): void { + protected emitPrivateClassInterface(_: ClassType, name: Name): void { this.emitLine("@interface ", name, " (JSONConversion)"); this.emitLine("+ (instancetype)fromJSONDictionary:(NSDictionary *)dict;"); this.emitLine("- (NSDictionary *)JSONDictionary;"); this.emitLine("@end"); } - protected pointerAwareTypeName (t: Type | [Sourcelike, string]): Sourcelike { + protected pointerAwareTypeName(t: Type | [Sourcelike, string]): Sourcelike { const name = t instanceof Type ? this.objcType(t) : t; const isPointer = name[1] !== ""; return isPointer ? name : [name, " "]; } - private emitNonClassTopLevelTypedef (t: Type, name: Name): void { + private emitNonClassTopLevelTypedef(t: Type, name: Name): void { let nonPointerTypeName = this.objcType(t)[0]; this.emitLine("typedef ", nonPointerTypeName, " ", name, ";"); } - private topLevelFromDataPrototype (name: Name): Sourcelike { + private topLevelFromDataPrototype(name: Name): Sourcelike { return [name, " *_Nullable ", name, "FromData(NSData *data, NSError **error)"]; } - private topLevelFromJSONPrototype (name: Name): Sourcelike { + private topLevelFromJSONPrototype(name: Name): Sourcelike { return [name, " *_Nullable ", name, "FromJSON(NSString *json, NSStringEncoding encoding, NSError **error)"]; } - private topLevelToDataPrototype (name: Name, pad = false): Sourcelike { + private topLevelToDataPrototype(name: Name, pad = false): Sourcelike { const parameter = this.variableNameForTopLevel(name); const padding = pad ? repeatString(" ", this.sourcelikeToString(name).length - "NSData".length) : ""; return ["NSData", padding, " *_Nullable ", name, "ToData(", name, " *", parameter, ", NSError **error)"]; } - private topLevelToJSONPrototype (name: Name, pad = false): Sourcelike { + private topLevelToJSONPrototype(name: Name, pad = false): Sourcelike { const parameter = this.variableNameForTopLevel(name); const padding = pad ? repeatString(" ", this.sourcelikeToString(name).length - "NSString".length) : ""; return [ @@ -576,31 +577,31 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { name, " *", parameter, - ", NSStringEncoding encoding, NSError **error)", + ", NSStringEncoding encoding, NSError **error)" ]; } - private emitTopLevelFunctionDeclarations (_: Type, name: Name): void { + private emitTopLevelFunctionDeclarations(_: Type, name: Name): void { this.emitLine(this.topLevelFromDataPrototype(name), ";"); this.emitLine(this.topLevelFromJSONPrototype(name), ";"); this.emitLine(this.topLevelToDataPrototype(name, true), ";"); this.emitLine(this.topLevelToJSONPrototype(name, true), ";"); } - private emitTryCatchAsError (inTry: () => void, inCatch: () => void) { + private emitTryCatchAsError(inTry: () => void, inCatch: () => void) { this.emitLine("@try {"); this.indent(inTry); this.emitLine("} @catch (NSException *exception) {"); this.indent(() => { this.emitLine( - "*error = [NSError errorWithDomain:@\"JSONSerialization\" code:-1 userInfo:@{ @\"exception\": exception }];", + '*error = [NSError errorWithDomain:@"JSONSerialization" code:-1 userInfo:@{ @"exception": exception }];' ); inCatch(); }); this.emitLine("}"); } - private emitTopLevelFunctions (t: Type, name: Name): void { + private emitTopLevelFunctions(t: Type, name: Name): void { const parameter = this.variableNameForTopLevel(name); this.ensureBlankLine(); @@ -608,11 +609,11 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { this.emitTryCatchAsError( () => { this.emitLine( - "id json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:error];", + "id json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:error];" ); this.emitLine("return *error ? nil : ", this.fromDynamicExpression(t, "json"), ";"); }, - () => this.emitLine("return nil;"), + () => this.emitLine("return nil;") ); }); @@ -627,11 +628,11 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { () => { this.emitLine("id json = ", this.toDynamicExpression(t, parameter), ";"); this.emitLine( - "NSData *data = [NSJSONSerialization dataWithJSONObject:json options:kNilOptions error:error];", + "NSData *data = [NSJSONSerialization dataWithJSONObject:json options:kNilOptions error:error];" ); this.emitLine("return *error ? nil : data;"); }, - () => this.emitLine("return nil;"), + () => this.emitLine("return nil;") ); }); @@ -642,7 +643,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { }); } - private emitClassInterface (t: ClassType, className: Name): void { + private emitClassInterface(t: ClassType, className: Name): void { const isTopLevel = mapContains(this.topLevels, t); this.emitDescription(this.descriptionForType(t)); @@ -660,7 +661,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { attributes.push(this.memoryAttribute(property.type, property.type.isNullable)); return [ ["@property ", ["(", attributes.join(", "), ")"], " "], - [this.pointerAwareTypeName(property.type), name, ";"], + [this.pointerAwareTypeName(property.type), name, ";"] ]; }); @@ -668,11 +669,11 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { if (t.getProperties().size > 0) this.ensureBlankLine(); this.emitLine( - "+ (_Nullable instancetype)fromJSON:(NSString *)json encoding:(NSStringEncoding)encoding error:(NSError *_Nullable *)error;", + "+ (_Nullable instancetype)fromJSON:(NSString *)json encoding:(NSStringEncoding)encoding error:(NSError *_Nullable *)error;" ); this.emitLine("+ (_Nullable instancetype)fromData:(NSData *)data error:(NSError *_Nullable *)error;"); this.emitLine( - "- (NSString *_Nullable)toJSON:(NSStringEncoding)encoding error:(NSError *_Nullable *)error;", + "- (NSString *_Nullable)toJSON:(NSStringEncoding)encoding error:(NSError *_Nullable *)error;" ); this.emitLine("- (NSData *_Nullable)toData:(NSError *_Nullable *)error;"); } @@ -680,7 +681,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { this.emitLine("@end"); } - protected hasIrregularProperties (t: ClassType) { + protected hasIrregularProperties(t: ClassType) { let irregular = false; this.forEachClassProperty(t, "none", (name, jsonName) => { irregular = irregular || stringEscape(jsonName) !== this.sourcelikeToString(name); @@ -688,7 +689,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { return irregular; } - protected hasUnsafeProperties (t: ClassType) { + protected hasUnsafeProperties(t: ClassType) { let unsafe = false; this.forEachClassProperty(t, "none", (_, __, property) => { unsafe = unsafe || !this.implicitlyConvertsToJSON(property.type); @@ -697,7 +698,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { } // TODO Implement NSCopying - private emitClassImplementation (t: ClassType, className: Name): void { + private emitClassImplementation(t: ClassType, className: Name): void { const isTopLevel = mapContains(this.topLevels, t); const hasIrregularProperties = this.hasIrregularProperties(t); @@ -710,7 +711,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { this.emitLine("return properties = properties ? properties : @{"); this.indent(() => { this.forEachClassProperty(t, "none", (name, jsonName) => - this.emitLine(`@"${stringEscape(jsonName)}": @"`, name, "\","), + this.emitLine(`@"${stringEscape(jsonName)}": @"`, name, '",') ); }); this.emitLine("};"); @@ -722,14 +723,14 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { "+ (_Nullable instancetype)fromData:(NSData *)data error:(NSError *_Nullable *)error", () => { this.emitLine("return ", className, "FromData(data, error);"); - }, + } ); this.ensureBlankLine(); this.emitMethod( "+ (_Nullable instancetype)fromJSON:(NSString *)json encoding:(NSStringEncoding)encoding error:(NSError *_Nullable *)error", () => { this.emitLine("return ", className, "FromJSON(json, encoding, error);"); - }, + } ); this.ensureBlankLine(); } @@ -777,7 +778,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { this.emitLine( "id dict = [[self dictionaryWithValuesForKeys:", className, - ".properties.allValues] mutableCopy];", + ".properties.allValues] mutableCopy];" ); this.ensureBlankLine(); @@ -801,7 +802,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { if (!this.implicitlyConvertsToJSON(property.type)) { const key = stringEscape(jsonKey); const name = ["_", propertyName]; - this.emitLine("@\"", key, "\": ", this.toDynamicExpression(property.type, name), ","); + this.emitLine('@"', key, '": ', this.toDynamicExpression(property.type, name), ","); } }); }); @@ -822,7 +823,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { "- (NSString *_Nullable)toJSON:(NSStringEncoding)encoding error:(NSError *_Nullable *)error", () => { this.emitLine("return ", className, "ToJSON(self, encoding, error);"); - }, + } ); } } @@ -830,13 +831,13 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { this.emitLine("@end"); } - protected emitMark (label: string) { + protected emitMark(label: string) { this.ensureBlankLine(); this.emitLine(`#pragma mark - ${label}`); this.ensureBlankLine(); } - protected variableNameForTopLevel (name: Name): Sourcelike { + protected variableNameForTopLevel(name: Name): Sourcelike { const camelCaseName = modifySource(serialized => { // 1. remove class prefix serialized = serialized.slice(this._classPrefix.length); @@ -846,7 +847,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { return camelCaseName; } - private emitPseudoEnumInterface (enumType: EnumType, enumName: Name) { + private emitPseudoEnumInterface(enumType: EnumType, enumName: Name) { this.emitDescription(this.descriptionForType(enumType)); this.emitLine("@interface ", enumName, " : NSObject"); @@ -858,7 +859,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { this.emitLine("@end"); } - private emitPseudoEnumImplementation (enumType: EnumType, enumName: Name) { + private emitPseudoEnumImplementation(enumType: EnumType, enumName: Name) { this.emitLine("@implementation ", enumName); const instances = [enumName, ".", staticEnumValuesIdentifier]; @@ -871,11 +872,11 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { staticEnumValuesIdentifier, " ? ", staticEnumValuesIdentifier, - " : @{", + " : @{" ); this.indent(() => { this.forEachEnumCase(enumType, "none", (_, jsonValue) => { - const value = ["@\"", stringEscape(jsonValue), "\""]; + const value = ['@"', stringEscape(jsonValue), '"']; this.emitLine(value, ": [[", enumName, " alloc] initWithValue:", value, "],"); }); }); @@ -891,15 +892,15 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { name, " { return ", instances, - "[@\"", + '[@"', stringEscape(jsonValue), - "\"]; }", + '"]; }' ); }); this.ensureBlankLine(); this.emitMethod("+ (instancetype _Nullable)withValue:(NSString *)value", () => - this.emitLine("return ", instances, "[value];"), + this.emitLine("return ", instances, "[value];") ); this.ensureBlankLine(); @@ -913,7 +914,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { this.emitLine("@end"); } - protected emitSourceStructure (proposedFilename: string): void { + protected emitSourceStructure(proposedFilename: string): void { const fileMode = proposedFilename !== "stdout"; if (!fileMode) { // We don't have a filename, so we use a top-level name @@ -942,7 +943,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { " *", this.variableNameForTopLevel(topLevelName), " = ", - fromJsonExpression, + fromJsonExpression ); }); } @@ -956,7 +957,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { "none", (_: ClassType, className: Name) => this.emitLine("@class ", className, ";"), (_, enumName) => this.emitLine("@class ", enumName, ";"), - () => null, + () => null ); this.ensureBlankLine(); @@ -973,7 +974,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { this.forEachTopLevel( "leading-and-interposing", (t, n) => this.emitNonClassTopLevelTypedef(t, n), - t => !(t instanceof ClassType), + t => !(t instanceof ClassType) ); const hasTopLevelNonClassTypes = iterableSome(this.topLevels, ([_, t]) => !(t instanceof ClassType)); @@ -985,7 +986,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { (t, n) => this.emitTopLevelFunctionDeclarations(t, n), // Objective-C developers get freaked out by C functions, so we don't // declare them for top-level object types (we always need them for non-object types) - t => this._options.marshallingFunctions || !(t instanceof ClassType), + t => this._options.marshallingFunctions || !(t instanceof ClassType) ); } @@ -994,7 +995,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { "leading-and-interposing", (c: ClassType, className: Name) => this.emitClassInterface(c, className), () => null, - () => null, + () => null ); this.ensureBlankLine(); @@ -1015,7 +1016,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { this.ensureBlankLine(); this.emitExtraComments("nil → NSNull conversion for JSON dictionaries"); this.emitBlock("static id NSNullify(id _Nullable x)", () => - this.emitLine("return (x == nil || x == NSNull.null) ? NSNull.null : x;"), + this.emitLine("return (x == nil || x == NSNull.null) ? NSNull.null : x;") ); this.ensureBlankLine(); this.emitLine("NS_ASSUME_NONNULL_BEGIN"); @@ -1031,7 +1032,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { "leading-and-interposing", (c: ClassType, className: Name) => this.emitPrivateClassInterface(c, className), () => null, - () => null, + () => null ); if (this.haveEnums) { @@ -1039,7 +1040,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { this.ensureBlankLine(); this.emitExtraComments( "These enum-like reference types are needed so that enum", - "values can be contained by NSArray and NSDictionary.", + "values can be contained by NSArray and NSDictionary." ); this.ensureBlankLine(); } @@ -1059,7 +1060,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { "leading-and-interposing", (c: ClassType, className: Name) => this.emitClassImplementation(c, className), () => null, - () => null, + () => null ); if (!this._options.justTypes) { @@ -1071,20 +1072,20 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { } } - private get needsMap (): boolean { + private get needsMap(): boolean { // TODO this isn't complete (needs union support, for example) - function needsMap (t: Type): boolean { + function needsMap(t: Type): boolean { return ( t instanceof MapType || t instanceof ArrayType || - t instanceof ClassType && mapSome(t.getProperties(), p => needsMap(p.type)) + (t instanceof ClassType && mapSome(t.getProperties(), p => needsMap(p.type))) ); } return iterableSome(this.typeGraph.allTypesUnordered(), needsMap); } - protected emitMapFunction () { + protected emitMapFunction() { if (this.needsMap) { this.emitMultiline(`static id map(id collection, id (^f)(id value)) { id result = nil; diff --git a/packages/quicktype-core/src/language/Php.ts b/packages/quicktype-core/src/language/Php.ts index 87c9e2b1c..8a7eaa40b 100644 --- a/packages/quicktype-core/src/language/Php.ts +++ b/packages/quicktype-core/src/language/Php.ts @@ -21,7 +21,7 @@ import { splitIntoWords, standardUnicodeHexEscape, utf16ConcatMap, - utf16LegalizeCharacters, + utf16LegalizeCharacters } from "../support/Strings"; import { defined } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; @@ -35,28 +35,28 @@ export const phpOptions = { fastGet: new BooleanOption("fast-get", "getter without validation", false), withSet: new BooleanOption("with-set", "Create Setter", false), withClosing: new BooleanOption("with-closing", "PHP Closing Tag", false), - acronymStyle: acronymOption(AcronymStyleOptions.Pascal), + acronymStyle: acronymOption(AcronymStyleOptions.Pascal) }; export class PhpTargetLanguage extends TargetLanguage { - constructor () { + public constructor() { super("PHP", ["php"], "php"); } - protected getOptions (): Array> { + protected getOptions(): Array> { return _.values(phpOptions); } - get supportsUnionsWithBothNumberTypes (): boolean { + public get supportsUnionsWithBothNumberTypes(): boolean { return true; } - protected makeRenderer (renderContext: RenderContext, untypedOptionValues: { [name: string]: any, }): PhpRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): PhpRenderer { const options = getOptionValues(phpOptions, untypedOptionValues); return new PhpRenderer(this, renderContext, options); } - get stringTypeMapping (): StringTypeMapping { + public get stringTypeMapping(): StringTypeMapping { const mapping: Map = new Map(); mapping.set("date", "date"); // TODO is not implemented yet mapping.set("time", "time"); // TODO is not implemented yet @@ -68,22 +68,22 @@ export class PhpTargetLanguage extends TargetLanguage { export const stringEscape = utf16ConcatMap(escapeNonPrintableMapper(isAscii, standardUnicodeHexEscape)); -function isStartCharacter (codePoint: number): boolean { +function isStartCharacter(codePoint: number): boolean { if (codePoint === 0x5f) return true; // underscore return isAscii(codePoint) && isLetter(codePoint); } -function isPartCharacter (codePoint: number): boolean { - return isStartCharacter(codePoint) || isAscii(codePoint) && isDigit(codePoint); +function isPartCharacter(codePoint: number): boolean { + return isStartCharacter(codePoint) || (isAscii(codePoint) && isDigit(codePoint)); } const legalizeName = utf16LegalizeCharacters(isPartCharacter); -export function phpNameStyle ( +export function phpNameStyle( startWithUpper: boolean, upperUnderscore: boolean, original: string, - acronymsStyle: (s: string) => string = allUpperWordStyle, + acronymsStyle: (s: string) => string = allUpperWordStyle ): string { const words = splitIntoWords(original); return combineWords( @@ -94,7 +94,7 @@ export function phpNameStyle ( upperUnderscore || startWithUpper ? allUpperWordStyle : allLowerWordStyle, acronymsStyle, upperUnderscore ? "_" : "", - isStartCharacter, + isStartCharacter ); } @@ -116,78 +116,78 @@ export class PhpRenderer extends ConvenienceRenderer { protected readonly _converterKeywords: string[] = []; - constructor ( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - protected readonly _options: OptionValues, + protected readonly _options: OptionValues ) { super(targetLanguage, renderContext); } - protected forbiddenForObjectProperties (_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected makeNamedTypeNamer (): Namer { + protected makeNamedTypeNamer(): Namer { return this.getNameStyling("typeNamingFunction"); } - protected namerForObjectProperty (): Namer { + protected namerForObjectProperty(): Namer { return this.getNameStyling("propertyNamingFunction"); } - protected makeUnionMemberNamer (): Namer { + protected makeUnionMemberNamer(): Namer { return this.getNameStyling("propertyNamingFunction"); } - protected makeEnumCaseNamer (): Namer { + protected makeEnumCaseNamer(): Namer { return this.getNameStyling("enumCaseNamingFunction"); } - protected unionNeedsName (u: UnionType): boolean { + protected unionNeedsName(u: UnionType): boolean { return nullableFromUnion(u) === null; } - protected namedTypeToNameForTopLevel (type: Type): Type | undefined { + protected namedTypeToNameForTopLevel(type: Type): Type | undefined { return directlyReachableSingleNamedType(type); } - protected makeNamesForPropertyGetterAndSetter ( + protected makeNamesForPropertyGetterAndSetter( _c: ClassType, _className: Name, _p: ClassProperty, _jsonName: string, - name: Name, + name: Name ): FunctionNames { const getterName = new DependencyName( this.getNameStyling("propertyNamingFunction"), name.order, - lookup => `get_${lookup(name)}`, + lookup => `get_${lookup(name)}` ); const setterName = new DependencyName( this.getNameStyling("propertyNamingFunction"), name.order, - lookup => `set_${lookup(name)}`, + lookup => `set_${lookup(name)}` ); const validateName = new DependencyName( this.getNameStyling("propertyNamingFunction"), name.order, - lookup => `validate_${lookup(name)}`, + lookup => `validate_${lookup(name)}` ); const fromName = new DependencyName( this.getNameStyling("propertyNamingFunction"), name.order, - lookup => `from_${lookup(name)}`, + lookup => `from_${lookup(name)}` ); const toName = new DependencyName( this.getNameStyling("propertyNamingFunction"), name.order, - lookup => `to_${lookup(name)}`, + lookup => `to_${lookup(name)}` ); const sampleName = new DependencyName( this.getNameStyling("propertyNamingFunction"), name.order, - lookup => `sample_${lookup(name)}`, + lookup => `sample_${lookup(name)}` ); return { getter: getterName, @@ -195,16 +195,16 @@ export class PhpRenderer extends ConvenienceRenderer { validate: validateName, from: fromName, to: toName, - sample: sampleName, + sample: sampleName }; } - protected makePropertyDependencyNames ( + protected makePropertyDependencyNames( c: ClassType, className: Name, p: ClassProperty, jsonName: string, - name: Name, + name: Name ): Name[] { const getterAndSetterNames = this.makeNamesForPropertyGetterAndSetter(c, className, p, jsonName, name); this._gettersAndSettersForPropertyName.set(name, getterAndSetterNames); @@ -214,26 +214,26 @@ export class PhpRenderer extends ConvenienceRenderer { getterAndSetterNames.validate, getterAndSetterNames.to, getterAndSetterNames.from, - getterAndSetterNames.sample, + getterAndSetterNames.sample ]; } - private getNameStyling (convention: string): Namer { - const styling: { [key: string]: Namer, } = { + private getNameStyling(convention: string): Namer { + const styling: { [key: string]: Namer } = { typeNamingFunction: funPrefixNamer("types", n => - phpNameStyle(true, false, n, acronymStyle(this._options.acronymStyle)), + phpNameStyle(true, false, n, acronymStyle(this._options.acronymStyle)) ), propertyNamingFunction: funPrefixNamer("properties", n => - phpNameStyle(false, false, n, acronymStyle(this._options.acronymStyle)), + phpNameStyle(false, false, n, acronymStyle(this._options.acronymStyle)) ), enumCaseNamingFunction: funPrefixNamer("enum-cases", n => - phpNameStyle(true, true, n, acronymStyle(this._options.acronymStyle)), - ), + phpNameStyle(true, true, n, acronymStyle(this._options.acronymStyle)) + ) }; return styling[convention]; } - protected startFile (_basename: Sourcelike): void { + protected startFile(_basename: Sourcelike): void { this.ensureBlankLine(); if (!this._haveEmittedLeadingComments && this.leadingComments !== undefined) { this.emitComments(this.leadingComments); @@ -242,28 +242,28 @@ export class PhpRenderer extends ConvenienceRenderer { } } - protected finishFile (): void { + protected finishFile(): void { // empty } - protected emitFileHeader (fileName: Sourcelike, _imports: string[]): void { + protected emitFileHeader(fileName: Sourcelike, _imports: string[]): void { this.startFile(fileName); this.emitLine("// This is a autogenerated file:", fileName); this.ensureBlankLine(); } - public emitDescriptionBlock (lines: Sourcelike[]): void { + public emitDescriptionBlock(lines: Sourcelike[]): void { this.emitCommentLines(lines, { lineStart: " * ", beforeComment: "/**", afterComment: " */" }); } - public emitBlock (line: Sourcelike, f: () => void): void { + public emitBlock(line: Sourcelike, f: () => void): void { this.emitLine(line, " {"); this.indent(f); this.emitLine("}"); } - protected phpType (_reference: boolean, t: Type, isOptional = false, prefix = "?", suffix = ""): Sourcelike { - function optionalize (s: Sourcelike) { + protected phpType(_reference: boolean, t: Type, isOptional = false, prefix = "?", suffix = ""): Sourcelike { + function optionalize(s: Sourcelike) { return [isOptional ? prefix : "", s, isOptional ? suffix : ""]; } @@ -286,11 +286,11 @@ export class PhpRenderer extends ConvenienceRenderer { }, transformedStringType => { if (transformedStringType.kind === "time") { - throw Error("transformedStringType.kind === \"time\""); + throw Error('transformedStringType.kind === "time"'); } if (transformedStringType.kind === "date") { - throw Error("transformedStringType.kind === \"date\""); + throw Error('transformedStringType.kind === "date"'); } if (transformedStringType.kind === "date-time") { @@ -298,15 +298,15 @@ export class PhpRenderer extends ConvenienceRenderer { } if (transformedStringType.kind === "uuid") { - throw Error("transformedStringType.kind === \"uuid\""); + throw Error('transformedStringType.kind === "uuid"'); } return "string"; - }, + } ); } - protected phpDocConvertType (className: Name, t: Type): Sourcelike { + protected phpDocConvertType(className: Name, t: Type): Sourcelike { return matchType( t, _anyType => "any", @@ -332,12 +332,12 @@ export class PhpRenderer extends ConvenienceRenderer { return "DateTime"; } - throw Error("transformedStringType.kind === \"unknown\""); - }, + throw Error('transformedStringType.kind === "unknown"'); + } ); } - protected phpConvertType (className: Name, t: Type): Sourcelike { + protected phpConvertType(className: Name, t: Type): Sourcelike { return matchType( t, _anyType => "any", @@ -363,12 +363,12 @@ export class PhpRenderer extends ConvenienceRenderer { return "string"; } - throw Error("transformedStringType.kind === \"unknown\""); - }, + throw Error('transformedStringType.kind === "unknown"'); + } ); } - protected phpToObjConvert (className: Name, t: Type, lhs: Sourcelike[], args: Sourcelike[]) { + protected phpToObjConvert(className: Name, t: Type, lhs: Sourcelike[], args: Sourcelike[]) { matchType( t, _anyType => this.emitLine(...lhs, ...args, "; /*any*/"), @@ -416,21 +416,21 @@ export class PhpRenderer extends ConvenienceRenderer { return; } - throw Error("transformedStringType.kind === \"unknown\""); - }, + throw Error('transformedStringType.kind === "unknown"'); + } ); } - private transformDateTime (className: Name, attrName: Sourcelike, scopeAttrName: Sourcelike[]) { + private transformDateTime(className: Name, attrName: Sourcelike, scopeAttrName: Sourcelike[]) { this.emitBlock(["if (!is_a(", scopeAttrName, ", 'DateTime'))"], () => - this.emitLine("throw new Exception('Attribute Error:", className, "::", attrName, "');"), + this.emitLine("throw new Exception('Attribute Error:", className, "::", attrName, "');") ); // if (lhs !== undefined) { // this.emitLine(lhs, "$tmp;"); // } } - protected phpFromObjConvert (className: Name, t: Type, lhs: Sourcelike[], args: Sourcelike[]) { + protected phpFromObjConvert(className: Name, t: Type, lhs: Sourcelike[], args: Sourcelike[]) { matchType( t, _anyType => this.emitLine(...lhs, ...args, "; /*any*/"), @@ -481,18 +481,18 @@ export class PhpRenderer extends ConvenienceRenderer { return; } - throw Error("transformedStringType.kind === \"unknown\""); - }, + throw Error('transformedStringType.kind === "unknown"'); + } ); } - protected phpSampleConvert ( + protected phpSampleConvert( className: Name, t: Type, lhs: Sourcelike[], args: Sourcelike[], idx: number, - suffix: Sourcelike, + suffix: Sourcelike ) { matchType( t, @@ -510,7 +510,7 @@ export class PhpRenderer extends ConvenienceRenderer { "" + idx, ":", args, - "*/", + "*/" ), _nullType => this.emitLine(...lhs, "null", suffix, " /*", "" + idx, ":", args, "*/"), _boolType => this.emitLine(...lhs, "true", suffix, " /*", "" + idx, ":", args, "*/"), @@ -530,7 +530,7 @@ export class PhpRenderer extends ConvenienceRenderer { "" + idx, ":", args, - "*/", + "*/" ), arrayType => { this.emitLine(...lhs, " array("); @@ -549,7 +549,7 @@ export class PhpRenderer extends ConvenienceRenderer { "" + idx, ":", args, - "*/", + "*/" ), mapType => { this.emitBlock(["function sample(): stdClass"], () => { @@ -571,27 +571,27 @@ export class PhpRenderer extends ConvenienceRenderer { }, transformedStringType => { if (transformedStringType.kind === "date-time") { - const x = _.pad("" + (1 + idx % 31), 2, "0"); + const x = _.pad("" + (1 + (idx % 31)), 2, "0"); this.emitLine( ...lhs, "DateTime::createFromFormat(DateTimeInterface::ISO8601, '", `2020-12-${x}T12:${x}:${x}+00:00`, "')", - suffix, + suffix ); // this.emitLine("return sample();"); return; } - throw Error("transformedStringType.kind === \"unknown\""); - }, + throw Error('transformedStringType.kind === "unknown"'); + } ); } - private phpValidate (className: Name, t: Type, attrName: Sourcelike, scopeAttrName: string) { + private phpValidate(className: Name, t: Type, attrName: Sourcelike, scopeAttrName: string) { const is = (isfn: string, myT: Name = className) => { this.emitBlock(["if (!", isfn, "(", scopeAttrName, "))"], () => - this.emitLine("throw new Exception(\"Attribute Error:", myT, "::", attrName, "\");"), + this.emitLine('throw new Exception("Attribute Error:', myT, "::", attrName, '");') ); }; @@ -642,11 +642,11 @@ export class PhpRenderer extends ConvenienceRenderer { } throw Error(`transformedStringType.kind === ${transformedStringType.kind}`); - }, + } ); } - protected emitFromMethod (names: FunctionNames, p: ClassProperty, className: Name, _name: Name, desc?: string[]) { + protected emitFromMethod(names: FunctionNames, p: ClassProperty, className: Name, _name: Name, desc?: string[]) { this.emitLine("/**"); if (desc !== undefined) { this.emitLine(" * ", desc); @@ -665,16 +665,16 @@ export class PhpRenderer extends ConvenienceRenderer { "(", this.phpConvertType(className, p.type), " $value): ", - this.phpType(false, p.type), + this.phpType(false, p.type) ], () => { this.phpFromObjConvert(className, p.type, ["return "], ["$value"]); // this.emitLine("return $ret;"); - }, + } ); } - protected emitToMethod (names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc?: string[]) { + protected emitToMethod(names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc?: string[]) { this.emitLine("/**"); if (desc !== undefined) { this.emitLine(" * ", desc); @@ -692,7 +692,7 @@ export class PhpRenderer extends ConvenienceRenderer { }); } - protected emitValidateMethod (names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc?: string[]) { + protected emitValidateMethod(names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc?: string[]) { this.emitLine("/**"); if (desc !== undefined) { this.emitLine(" * ", desc); @@ -708,11 +708,11 @@ export class PhpRenderer extends ConvenienceRenderer { () => { this.phpValidate(className, p.type, name, "$value"); this.emitLine("return true;"); - }, + } ); } - protected emitGetMethod (names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc?: string[]) { + protected emitGetMethod(names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc?: string[]) { if (this._options.withGet) { this.emitLine("/**"); if (desc !== undefined) { @@ -739,7 +739,7 @@ export class PhpRenderer extends ConvenienceRenderer { className, "::", name, - "');", + "');" ); } else { this.emitLine("return $this->", name, ";"); @@ -748,7 +748,7 @@ export class PhpRenderer extends ConvenienceRenderer { } } - protected emitSetMethod (names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc?: string[]) { + protected emitSetMethod(names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc?: string[]) { if (this._options.withSet) { this.emitLine("/**"); if (desc !== undefined) { @@ -767,13 +767,13 @@ export class PhpRenderer extends ConvenienceRenderer { } } - protected emitSampleMethod ( + protected emitSampleMethod( names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc: string[] | undefined, - idx: number, + idx: number ) { if (this._options.withGet) { this.emitLine("/**"); @@ -791,7 +791,7 @@ export class PhpRenderer extends ConvenienceRenderer { } } - protected emitClassDefinition (c: ClassType, className: Name): void { + protected emitClassDefinition(c: ClassType, className: Name): void { this.emitFileHeader(className, []); this.emitBlock(["class ", className], () => { @@ -804,7 +804,7 @@ export class PhpRenderer extends ConvenienceRenderer { "; // json:", jsonName, " ", - p.type.isNullable ? "Optional" : "Required", + p.type.isNullable ? "Optional" : "Required" ); }); @@ -856,7 +856,7 @@ export class PhpRenderer extends ConvenienceRenderer { lines.forEach((line, jdx) => { this.emitLine(...line, lines.length === jdx + 1 ? ";" : ""); }); - }, + } ); this.ensureBlankLine(); @@ -866,7 +866,7 @@ export class PhpRenderer extends ConvenienceRenderer { " * @return stdClass\n", " * @throws Exception\n", " */\n", - "public function to(): stdClass ", + "public function to(): stdClass " ], () => { this.emitLine("$out = new stdClass();"); @@ -875,7 +875,7 @@ export class PhpRenderer extends ConvenienceRenderer { this.emitLine("$out->{'", jsonName, "'} = $this->", names.to, "();"); }); this.emitLine("return $out;"); - }, + } ); this.ensureBlankLine(); @@ -889,7 +889,7 @@ export class PhpRenderer extends ConvenienceRenderer { " * @throws Exception\n", " */\n", "public static function from(stdClass $obj): ", - className, + className ], () => { if (this._options.fastGet) { @@ -907,7 +907,7 @@ export class PhpRenderer extends ConvenienceRenderer { comma = ","; }); this.emitLine(");"); - }, + } ); this.ensureBlankLine(); this.emitBlock( @@ -921,33 +921,33 @@ export class PhpRenderer extends ConvenienceRenderer { comma = ","; }); this.emitLine(");"); - }, + } ); }); this.finishFile(); } - protected emitUnionAttributes (_u: UnionType, _unionName: Name): void { + protected emitUnionAttributes(_u: UnionType, _unionName: Name): void { // empty } - protected emitUnionSerializer (_u: UnionType, _unionName: Name): void { + protected emitUnionSerializer(_u: UnionType, _unionName: Name): void { // empty } - protected emitUnionDefinition (_u: UnionType, _unionName: Name): void { + protected emitUnionDefinition(_u: UnionType, _unionName: Name): void { throw Error("emitUnionDefinition not implemented"); } - protected emitEnumSerializationAttributes (_e: EnumType) { + protected emitEnumSerializationAttributes(_e: EnumType) { // Empty } - protected emitEnumDeserializationAttributes (_e: EnumType) { + protected emitEnumDeserializationAttributes(_e: EnumType) { // Empty } - protected emitEnumDefinition (e: EnumType, enumName: Name): void { + protected emitEnumDefinition(e: EnumType, enumName: Name): void { this.emitFileHeader(enumName, []); this.emitDescription(this.descriptionForType(e)); const caseNames: Sourcelike[] = []; @@ -986,7 +986,7 @@ export class PhpRenderer extends ConvenienceRenderer { "public static function to(", enumName, " $obj): ", - enumSerdeType, + enumSerdeType ], () => { this.emitLine("switch ($obj->enum) {"); @@ -1000,13 +1000,13 @@ export class PhpRenderer extends ConvenienceRenderer { name, "->enum: return '", stringEscape(jsonName), - "';", + "';" ); }); }); this.emitLine("}"); this.emitLine("throw new Exception('the give value is not an enum-value.');"); - }, + } ); this.ensureBlankLine(); this.emitEnumDeserializationAttributes(e); @@ -1021,7 +1021,7 @@ export class PhpRenderer extends ConvenienceRenderer { " * @throws Exception\n", " */\n", "public static function from($obj): ", - enumName, + enumName ], () => { this.emitLine("switch ($obj) {"); @@ -1032,8 +1032,8 @@ export class PhpRenderer extends ConvenienceRenderer { }); }); this.emitLine("}"); - this.emitLine("throw new Exception(\"Cannot deserialize ", enumName, "\");"); - }, + this.emitLine('throw new Exception("Cannot deserialize ', enumName, '");'); + } ); this.ensureBlankLine(); this.emitBlock( @@ -1044,20 +1044,20 @@ export class PhpRenderer extends ConvenienceRenderer { lines.push([enumName, "::$", name]); }); this.emitLine("return ", lines[0], ";"); - }, + } ); }); this.emitLine(enumName, "::init();"); this.finishFile(); } - protected emitSourceStructure (givenFilename: string): void { + protected emitSourceStructure(givenFilename: string): void { this.emitLine(" this.emitClassDefinition(c, n), (e, n) => this.emitEnumDefinition(e, n), - (u, n) => this.emitUnionDefinition(u, n), + (u, n) => this.emitUnionDefinition(u, n) ); if (this._options.withClosing) { this.emitLine("?>"); diff --git a/packages/quicktype-core/src/language/Pike.ts b/packages/quicktype-core/src/language/Pike.ts index 0e9716278..637bedcac 100644 --- a/packages/quicktype-core/src/language/Pike.ts +++ b/packages/quicktype-core/src/language/Pike.ts @@ -1,13 +1,13 @@ import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Name, type Namer} from "../Naming"; +import { type Name, type Namer } from "../Naming"; import { funPrefixNamer } from "../Naming"; import { type Option } from "../RendererOptions"; import { type RenderContext } from "../Renderer"; -import { type MultiWord, type Sourcelike} from "../Source"; +import { type MultiWord, type Sourcelike } from "../Source"; import { multiWord, parenIfNeeded, singleWord } from "../Source"; import { TargetLanguage } from "../TargetLanguage"; -import { type Type, type ClassType, type EnumType, type UnionType} from "../Type"; +import { type Type, type ClassType, type EnumType, type UnionType } from "../Type"; import { ArrayType, MapType, PrimitiveType } from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; import { legalizeCharacters, isLetterOrUnderscoreOrDigit, stringEscape, makeNameStyle } from "../support/Strings"; @@ -66,7 +66,7 @@ const keywords = [ "sscanf", "switch", "typeof", - "global", + "global" ]; const legalizeName = legalizeCharacters(isLetterOrUnderscoreOrDigit); @@ -75,21 +75,21 @@ const namingFunction = funPrefixNamer("genericNamer", makeNameStyle("underscore" const namedTypeNamingFunction = funPrefixNamer("typeNamer", makeNameStyle("pascal", legalizeName)); export class PikeTargetLanguage extends TargetLanguage { - constructor () { + public constructor() { super("Pike", ["pike", "pikelang"], "pmod"); } - protected getOptions (): Array> { + protected getOptions(): Array> { return []; } - protected makeRenderer (renderContext: RenderContext): PikeRenderer { + protected makeRenderer(renderContext: RenderContext): PikeRenderer { return new PikeRenderer(this, renderContext); } } export class PikeRenderer extends ConvenienceRenderer { - protected emitSourceStructure (): void { + protected emitSourceStructure(): void { this.emitInformationComment(); this.ensureBlankLine(); this.forEachTopLevel( @@ -100,54 +100,54 @@ export class PikeRenderer extends ConvenienceRenderer { this.emitTopLevelConverter(t, name); this.ensureBlankLine(); }, - t => this.namedTypeToNameForTopLevel(t) === undefined, + t => this.namedTypeToNameForTopLevel(t) === undefined ); this.ensureBlankLine(); this.forEachNamedType( "leading-and-interposing", (c: ClassType, className: Name) => this.emitClassDefinition(c, className), (e, n) => this.emitEnum(e, n), - (u, n) => this.emitUnion(u, n), + (u, n) => this.emitUnion(u, n) ); } - protected get enumCasesInGlobalNamespace (): boolean { + protected get enumCasesInGlobalNamespace(): boolean { return true; } - protected makeEnumCaseNamer (): Namer { + protected makeEnumCaseNamer(): Namer { return enumNamingFunction; } - protected makeNamedTypeNamer (): Namer { + protected makeNamedTypeNamer(): Namer { return namedTypeNamingFunction; } - protected makeUnionMemberNamer (): Namer { + protected makeUnionMemberNamer(): Namer { return namingFunction; } - protected namerForObjectProperty (): Namer { + protected namerForObjectProperty(): Namer { return namingFunction; } - protected forbiddenNamesForGlobalNamespace (): string[] { + protected forbiddenNamesForGlobalNamespace(): string[] { return [...keywords]; } - protected forbiddenForObjectProperties (_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForEnumCases (_e: EnumType, _enumName: Name): ForbiddenWordsInfo { + protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForUnionMembers (_u: UnionType, _unionName: Name): ForbiddenWordsInfo { + protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected sourceFor (t: Type): MultiWord { + protected sourceFor(t: Type): MultiWord { if (["class", "object", "enum"].includes(t.kind)) { return singleWord(this.nameForNamedType(t)); } @@ -177,11 +177,11 @@ export class PikeRenderer extends ConvenienceRenderer { } else { return singleWord(this.nameForNamedType(unionType)); } - }, + } ); } - protected emitClassDefinition (c: ClassType, className: Name): void { + protected emitClassDefinition(c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); this.emitBlock(["class ", className], () => { this.emitClassMembers(c); @@ -192,20 +192,20 @@ export class PikeRenderer extends ConvenienceRenderer { this.emitDecodingFunction(className, c); } - protected emitEnum (e: EnumType, enumName: Name): void { + protected emitEnum(e: EnumType, enumName: Name): void { this.emitBlock([e.kind, " ", enumName], () => { let table: Sourcelike[][] = []; this.forEachEnumCase(e, "none", (name, jsonName) => { table.push([ - [name, " = \"", stringEscape(jsonName), "\", "], - ["// json: \"", jsonName, "\""], + [name, ' = "', stringEscape(jsonName), '", '], + ['// json: "', jsonName, '"'] ]); }); this.emitTable(table); }); } - protected emitUnion (u: UnionType, unionName: Name): void { + protected emitUnion(u: UnionType, unionName: Name): void { const isMaybeWithSingleType = nullableFromUnion(u); if (isMaybeWithSingleType !== null) { @@ -227,7 +227,7 @@ export class PikeRenderer extends ConvenienceRenderer { types.map(r => r.map(sl => this.sourcelikeToString(sl))).join("|"), " ", unionName, - ";", + ";" ]); this.ensureBlankLine(); this.emitBlock([unionName, " ", unionName, "_from_JSON(mixed json)"], () => { @@ -235,17 +235,17 @@ export class PikeRenderer extends ConvenienceRenderer { }); } - private emitBlock (line: Sourcelike, f: () => void, opening: Sourcelike = " {", closing: Sourcelike = "}"): void { + private emitBlock(line: Sourcelike, f: () => void, opening: Sourcelike = " {", closing: Sourcelike = "}"): void { this.emitLine(line, opening); this.indent(f); this.emitLine(closing); } - private emitMappingBlock (line: Sourcelike, f: () => void): void { + private emitMappingBlock(line: Sourcelike, f: () => void): void { this.emitBlock(line, f, "([", "]);"); } - private emitClassMembers (c: ClassType): void { + private emitClassMembers(c: ClassType): void { let table: Sourcelike[][] = []; this.forEachClassProperty(c, "none", (name, jsonName, p) => { const pikeType = this.sourceFor(p.type).source; @@ -253,13 +253,13 @@ export class PikeRenderer extends ConvenienceRenderer { table.push([ [pikeType, " "], [name, "; "], - ["// json: \"", jsonName, "\""], + ['// json: "', jsonName, '"'] ]); }); this.emitTable(table); } - private emitInformationComment () { + private emitInformationComment() { this.emitCommentLines( [ "This source has been automatically generated by quicktype.", @@ -274,17 +274,17 @@ export class PikeRenderer extends ConvenienceRenderer { "It will return an instance of .", "Bear in mind that these functions have unexpected behavior,", "and will likely throw an error, if the JSON string does not", - "match the expected interface, even if the JSON itself is valid.", + "match the expected interface, even if the JSON itself is valid." ], - { lineStart: "// " }, + { lineStart: "// " } ); } - private emitTopLevelTypedef (t: Type, name: Name) { + private emitTopLevelTypedef(t: Type, name: Name) { this.emitLine("typedef ", this.sourceFor(t).source, " ", name, ";"); } - private emitTopLevelConverter (t: Type, name: Name) { + private emitTopLevelConverter(t: Type, name: Name) { this.emitBlock([name, " ", name, "_from_JSON(mixed json)"], () => { if (t instanceof PrimitiveType) { this.emitLine(["return json;"]); @@ -305,11 +305,11 @@ export class PikeRenderer extends ConvenienceRenderer { }); } - private emitEncodingFunction (c: ClassType) { + private emitEncodingFunction(c: ClassType) { this.emitBlock(["string encode_json()"], () => { this.emitMappingBlock(["mapping(string:mixed) json = "], () => { this.forEachClassProperty(c, "none", (name, jsonName) => { - this.emitLine(["\"", stringEscape(jsonName), "\" : ", name, ","]); + this.emitLine(['"', stringEscape(jsonName), '" : ', name, ","]); }); }); this.ensureBlankLine(); @@ -317,12 +317,12 @@ export class PikeRenderer extends ConvenienceRenderer { }); } - private emitDecodingFunction (className: Name, c: ClassType) { + private emitDecodingFunction(className: Name, c: ClassType) { this.emitBlock([className, " ", className, "_from_JSON(mixed json)"], () => { this.emitLine([className, " retval = ", className, "();"]); this.ensureBlankLine(); this.forEachClassProperty(c, "none", (name, jsonName) => { - this.emitLine(["retval.", name, " = json[\"", stringEscape(jsonName), "\"];"]); + this.emitLine(["retval.", name, ' = json["', stringEscape(jsonName), '"];']); }); this.ensureBlankLine(); this.emitLine(["return retval;"]); diff --git a/packages/quicktype-core/src/language/Python.ts b/packages/quicktype-core/src/language/Python.ts index 91cb653e4..5edc549b2 100644 --- a/packages/quicktype-core/src/language/Python.ts +++ b/packages/quicktype-core/src/language/Python.ts @@ -1,22 +1,13 @@ import { TargetLanguage } from "../TargetLanguage"; import { type StringTypeMapping } from "../TypeBuilder"; -import { - type TransformedStringTypeKind, - type PrimitiveStringTypeKind, - type Type, - type ClassProperty, -} from "../Type"; -import { - EnumType, - ClassType, - UnionType, -} from "../Type"; +import { type TransformedStringTypeKind, type PrimitiveStringTypeKind, type Type, type ClassProperty } from "../Type"; +import { EnumType, ClassType, UnionType } from "../Type"; import { type RenderContext } from "../Renderer"; -import { type Option, type OptionValues} from "../RendererOptions"; +import { type Option, type OptionValues } from "../RendererOptions"; import { getOptionValues, EnumOption, BooleanOption } from "../RendererOptions"; -import { type ForbiddenWordsInfo} from "../ConvenienceRenderer"; +import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; import { ConvenienceRenderer, topLevelNameOrder } from "../ConvenienceRenderer"; -import { type Namer, type Name} from "../Naming"; +import { type Namer, type Name } from "../Naming"; import { funPrefixNamer, DependencyName } from "../Naming"; import { splitIntoWords, @@ -26,14 +17,13 @@ import { allUpperWordStyle, allLowerWordStyle, stringEscape, - originalWord, + originalWord } from "../support/Strings"; import { assertNever, panic, defined } from "../support/Support"; -import { type Sourcelike, type MultiWord} from "../Source"; +import { type Sourcelike, type MultiWord } from "../Source"; import { multiWord, singleWord, parenIfNeeded, modifySource } from "../Source"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { - type Transformer} from "../Transformers"; +import { type Transformer } from "../Transformers"; import { followTargetType, transformationForType, @@ -44,7 +34,7 @@ import { ParseStringTransformer, UnionMemberMatchTransformer, StringifyTransformer, - EncodingTransformer, + EncodingTransformer } from "../Transformers"; import { arrayIntercalate, @@ -52,7 +42,7 @@ import { mapUpdateInto, iterableSome, mapSortBy, - iterableFirst, + iterableFirst } from "collection-utils"; import unicode from "unicode-properties"; @@ -71,7 +61,7 @@ const forbiddenTypeNames = [ "Type", "TypeVar", "T", - "EnumT", + "EnumT" ]; const forbiddenPropertyNames = [ "and", @@ -113,7 +103,7 @@ const forbiddenPropertyNames = [ "try", "while", "with", - "yield", + "yield" ]; export interface PythonFeatures { @@ -128,20 +118,20 @@ export const pythonOptions = { [ ["3.5", { typeHints: false, dataClasses: false }], ["3.6", { typeHints: true, dataClasses: false }], - ["3.7", { typeHints: true, dataClasses: true }], + ["3.7", { typeHints: true, dataClasses: true }] ], - "3.6", + "3.6" ), justTypes: new BooleanOption("just-types", "Classes only", false), - nicePropertyNames: new BooleanOption("nice-property-names", "Transform property names to be Pythonic", true), + nicePropertyNames: new BooleanOption("nice-property-names", "Transform property names to be Pythonic", true) }; export class PythonTargetLanguage extends TargetLanguage { - protected getOptions (): Array> { + protected getOptions(): Array> { return [pythonOptions.features, pythonOptions.justTypes, pythonOptions.nicePropertyNames]; } - get stringTypeMapping (): StringTypeMapping { + public get stringTypeMapping(): StringTypeMapping { const mapping: Map = new Map(); const dateTimeType = "date-time"; mapping.set("date", dateTimeType); @@ -153,15 +143,15 @@ export class PythonTargetLanguage extends TargetLanguage { return mapping; } - get supportsUnionsWithBothNumberTypes (): boolean { + public get supportsUnionsWithBothNumberTypes(): boolean { return true; } - get supportsOptionalClassProperties (): boolean { + public get supportsOptionalClassProperties(): boolean { return false; } - needsTransformerForType (t: Type): boolean { + public needsTransformerForType(t: Type): boolean { if (t instanceof UnionType) { return iterableSome(t.members, m => this.needsTransformerForType(m)); } @@ -169,7 +159,7 @@ export class PythonTargetLanguage extends TargetLanguage { return t.kind === "integer-string" || t.kind === "bool-string"; } - protected makeRenderer (renderContext: RenderContext, untypedOptionValues: { [name: string]: any, }): PythonRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): PythonRenderer { const options = getOptionValues(pythonOptions, untypedOptionValues); if (options.justTypes) { return new PythonRenderer(this, renderContext, options); @@ -179,20 +169,20 @@ export class PythonTargetLanguage extends TargetLanguage { } } -function isNormalizedStartCharacter3 (utf16Unit: number): boolean { +function isNormalizedStartCharacter3(utf16Unit: number): boolean { // FIXME: add Other_ID_Start - https://docs.python.org/3/reference/lexical_analysis.html#identifiers const category: string = unicode.getCategory(utf16Unit); return ["Lu", "Ll", "Lt", "Lm", "Lo", "Nl"].includes(category); } -function isNormalizedPartCharacter3 (utf16Unit: number): boolean { +function isNormalizedPartCharacter3(utf16Unit: number): boolean { // FIXME: add Other_ID_Continue - https://docs.python.org/3/reference/lexical_analysis.html#identifiers if (isNormalizedStartCharacter3(utf16Unit)) return true; const category: string = unicode.getCategory(utf16Unit); return ["Mn", "Mc", "Nd", "Pc"].includes(category); } -function isStartCharacter3 (utf16Unit: number): boolean { +function isStartCharacter3(utf16Unit: number): boolean { const s = String.fromCharCode(utf16Unit).normalize("NFKC"); const l = s.length; if (l === 0 || !isNormalizedStartCharacter3(s.charCodeAt(0))) return false; @@ -203,7 +193,7 @@ function isStartCharacter3 (utf16Unit: number): boolean { return true; } -function isPartCharacter3 (utf16Unit: number): boolean { +function isPartCharacter3(utf16Unit: number): boolean { const s = String.fromCharCode(utf16Unit).normalize("NFKC"); const l = s.length; for (let i = 0; i < l; i++) { @@ -215,7 +205,7 @@ function isPartCharacter3 (utf16Unit: number): boolean { const legalizeName3 = utf16LegalizeCharacters(isPartCharacter3); -function classNameStyle (original: string): string { +function classNameStyle(original: string): string { const words = splitIntoWords(original); return combineWords( words, @@ -225,11 +215,11 @@ function classNameStyle (original: string): string { allUpperWordStyle, allUpperWordStyle, "", - isStartCharacter3, + isStartCharacter3 ); } -function getWordStyle (uppercase: boolean, forceSnakeNameStyle: boolean) { +function getWordStyle(uppercase: boolean, forceSnakeNameStyle: boolean) { if (!forceSnakeNameStyle) { return originalWord; } @@ -237,7 +227,7 @@ function getWordStyle (uppercase: boolean, forceSnakeNameStyle: boolean) { return uppercase ? allUpperWordStyle : allLowerWordStyle; } -function snakeNameStyle (original: string, uppercase: boolean, forceSnakeNameStyle: boolean): string { +function snakeNameStyle(original: string, uppercase: boolean, forceSnakeNameStyle: boolean): string { const wordStyle = getWordStyle(uppercase, forceSnakeNameStyle); const separator = forceSnakeNameStyle ? "_" : ""; const words = splitIntoWords(original); @@ -249,103 +239,103 @@ export class PythonRenderer extends ConvenienceRenderer { private readonly declaredTypes: Set = new Set(); - constructor ( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - protected readonly pyOptions: OptionValues, + protected readonly pyOptions: OptionValues ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace (): string[] { + protected forbiddenNamesForGlobalNamespace(): string[] { return forbiddenTypeNames; } - protected forbiddenForObjectProperties (_: ClassType, _classNamed: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties(_: ClassType, _classNamed: Name): ForbiddenWordsInfo { return { names: forbiddenPropertyNames, includeGlobalForbidden: false }; } - protected makeNamedTypeNamer (): Namer { + protected makeNamedTypeNamer(): Namer { return funPrefixNamer("type", classNameStyle); } - protected namerForObjectProperty (): Namer { + protected namerForObjectProperty(): Namer { return funPrefixNamer("property", s => snakeNameStyle(s, false, this.pyOptions.nicePropertyNames)); } - protected makeUnionMemberNamer (): null { + protected makeUnionMemberNamer(): null { return null; } - protected makeEnumCaseNamer (): Namer { + protected makeEnumCaseNamer(): Namer { return funPrefixNamer("enum-case", s => snakeNameStyle(s, true, this.pyOptions.nicePropertyNames)); } - protected get commentLineStart (): string { + protected get commentLineStart(): string { return "# "; } - protected emitDescriptionBlock (lines: Sourcelike[]): void { + protected emitDescriptionBlock(lines: Sourcelike[]): void { if (lines.length === 1) { const docstring = modifySource(content => { - if (content.endsWith("\"")) { - return content.slice(0, -1) + "\\\""; + if (content.endsWith('"')) { + return content.slice(0, -1) + '\\"'; } return content; }, lines[0]); - this.emitComments([{ customLines: [docstring], lineStart: "\"\"\"", lineEnd: "\"\"\"" }]); + this.emitComments([{ customLines: [docstring], lineStart: '"""', lineEnd: '"""' }]); } else { this.emitCommentLines(lines, { - firstLineStart: "\"\"\"", + firstLineStart: '"""', lineStart: "", - afterComment: "\"\"\"", + afterComment: '"""' }); } } - protected get needsTypeDeclarationBeforeUse (): boolean { + protected get needsTypeDeclarationBeforeUse(): boolean { return true; } - protected canBeForwardDeclared (t: Type): boolean { + protected canBeForwardDeclared(t: Type): boolean { const kind = t.kind; return kind === "class" || kind === "enum"; } - protected emitBlock (line: Sourcelike, f: () => void): void { + protected emitBlock(line: Sourcelike, f: () => void): void { this.emitLine(line); this.indent(f); } - protected string (s: string): Sourcelike { - const openQuote = "\""; - return [openQuote, stringEscape(s), "\""]; + protected string(s: string): Sourcelike { + const openQuote = '"'; + return [openQuote, stringEscape(s), '"']; } - protected withImport (module: string, name: string): Sourcelike { + protected withImport(module: string, name: string): Sourcelike { if (this.pyOptions.features.typeHints || module !== "typing") { // FIXME: This is ugly. We should rather not generate that import in the first // place, but right now we just make the type source and then throw it away. It's // not a performance issue, so it's fine, I just bemoan this special case, and // potential others down the road. - mapUpdateInto(this.imports, module, s => s ? setUnionInto(s, [name]) : new Set([name])); + mapUpdateInto(this.imports, module, s => (s ? setUnionInto(s, [name]) : new Set([name]))); } return name; } - protected withTyping (name: string): Sourcelike { + protected withTyping(name: string): Sourcelike { return this.withImport("typing", name); } - protected namedType (t: Type): Sourcelike { + protected namedType(t: Type): Sourcelike { const name = this.nameForNamedType(t); if (this.declaredTypes.has(t)) return name; return ["'", name, "'"]; } - protected pythonType (t: Type, _isRootTypeDef = false): Sourcelike { + protected pythonType(t: Type, _isRootTypeDef = false): Sourcelike { const actualType = followTargetType(t); return matchType( @@ -380,7 +370,7 @@ export class PythonRenderer extends ConvenienceRenderer { "[Union[", arrayIntercalate(", ", memberTypes), "]]", - ...rest, + ...rest ]; } else { return [this.withTyping("Optional"), "[", defined(iterableFirst(memberTypes)), "]", ...rest]; @@ -399,11 +389,11 @@ export class PythonRenderer extends ConvenienceRenderer { } return panic(`Transformed type ${transformedStringType.kind} not supported`); - }, + } ); } - protected declarationLine (t: Type): Sourcelike { + protected declarationLine(t: Type): Sourcelike { if (t instanceof ClassType) { return ["class ", this.nameForNamedType(t), ":"]; } @@ -423,7 +413,7 @@ export class PythonRenderer extends ConvenienceRenderer { this.declaredTypes.add(t); } - protected emitClassMembers (t: ClassType): void { + protected emitClassMembers(t: ClassType): void { if (this.pyOptions.features.dataClasses) return; const args: Sourcelike[] = []; @@ -440,11 +430,11 @@ export class PythonRenderer extends ConvenienceRenderer { this.emitLine("self.", name, " = ", name); }); } - }, + } ); } - protected typeHint (...sl: Sourcelike[]): Sourcelike { + protected typeHint(...sl: Sourcelike[]): Sourcelike { if (this.pyOptions.features.typeHints) { return sl; } @@ -452,28 +442,28 @@ export class PythonRenderer extends ConvenienceRenderer { return []; } - protected typingDecl (name: Sourcelike, type: string): Sourcelike { + protected typingDecl(name: Sourcelike, type: string): Sourcelike { return [name, this.typeHint(": ", this.withTyping(type))]; } - protected typingReturn (type: string): Sourcelike { + protected typingReturn(type: string): Sourcelike { return this.typeHint(" -> ", this.withTyping(type)); } - protected sortClassProperties ( + protected sortClassProperties( properties: ReadonlyMap, - propertyNames: ReadonlyMap, + propertyNames: ReadonlyMap ): ReadonlyMap { if (this.pyOptions.features.dataClasses) { return mapSortBy(properties, (p: ClassProperty) => { - return p.type instanceof UnionType && nullableFromUnion(p.type) != null || p.isOptional ? 1 : 0; + return (p.type instanceof UnionType && nullableFromUnion(p.type) != null) || p.isOptional ? 1 : 0; }); } else { return super.sortClassProperties(properties, propertyNames); } } - protected emitClass (t: ClassType): void { + protected emitClass(t: ClassType): void { if (this.pyOptions.features.dataClasses) { this.emitLine("@", this.withImport("dataclasses", "dataclass")); } @@ -496,7 +486,7 @@ export class PythonRenderer extends ConvenienceRenderer { }); } - protected emitEnum (t: EnumType): void { + protected emitEnum(t: EnumType): void { this.declareType(t, () => { this.forEachEnumCase(t, "none", (name, jsonName) => { this.emitLine([name, " = ", this.string(jsonName)]); @@ -504,21 +494,21 @@ export class PythonRenderer extends ConvenienceRenderer { }); } - protected emitImports (): void { + protected emitImports(): void { this.imports.forEach((names, module) => { this.emitLine("from ", module, " import ", Array.from(names).join(", ")); }); } - protected emitSupportCode (): void { + protected emitSupportCode(): void { return; } - protected emitClosingCode (): void { + protected emitClosingCode(): void { return; } - protected emitSourceStructure (_givenOutputFilename: string): void { + protected emitSourceStructure(_givenOutputFilename: string): void { const declarationLines = this.gatherSource(() => { this.forEachNamedType( ["interposing", 2], @@ -526,7 +516,7 @@ export class PythonRenderer extends ConvenienceRenderer { e => this.emitEnum(e), _u => { return; - }, + } ); }); @@ -586,9 +576,9 @@ export interface ValueOrLambda { // // * If `input` is a value, the result is `f(input)`. // * If `input` is a lambda, the result is `lambda x: f(input(x))` -function compose (input: ValueOrLambda, f: (arg: Sourcelike) => Sourcelike): ValueOrLambda; -function compose (input: ValueOrLambda, f: ValueOrLambda): ValueOrLambda; -function compose (input: ValueOrLambda, f: ValueOrLambda | ((arg: Sourcelike) => Sourcelike)): ValueOrLambda { +function compose(input: ValueOrLambda, f: (arg: Sourcelike) => Sourcelike): ValueOrLambda; +function compose(input: ValueOrLambda, f: ValueOrLambda): ValueOrLambda; +function compose(input: ValueOrLambda, f: ValueOrLambda | ((arg: Sourcelike) => Sourcelike)): ValueOrLambda { if (typeof f === "function") { if (input.value !== undefined) { // `input` is a value, so just apply `f` to its source form. @@ -623,7 +613,7 @@ function compose (input: ValueOrLambda, f: ValueOrLambda | ((arg: Sourcelike) => // `input` is a lambda, so the result is `lambda x: f(input(x))`. return { lambda: multiWord("", "lambda x: ", parenIfNeeded(f.lambda), "(", parenIfNeeded(input.lambda), "(x))"), - value: undefined, + value: undefined }; } @@ -635,7 +625,7 @@ const identity: ValueOrLambda = { value: undefined }; // If `vol` is a lambda, return it in its source form. If it's // a value, return a `lambda` that returns the value. -function makeLambda (vol: ValueOrLambda): MultiWord { +function makeLambda(vol: ValueOrLambda): MultiWord { if (vol.lambda !== undefined) { if (vol.value === undefined) { return vol.lambda; @@ -651,7 +641,7 @@ function makeLambda (vol: ValueOrLambda): MultiWord { // If `vol` is a value, return the value in its source form. // Calling this with `vol` being a lambda is not allowed. -function makeValue (vol: ValueOrLambda): Sourcelike { +function makeValue(vol: ValueOrLambda): Sourcelike { if (vol.value === undefined) { return panic("Cannot make value from lambda without value"); } @@ -667,7 +657,7 @@ export class JSONPythonRenderer extends PythonRenderer { private readonly _deserializerFunctions = new Set(); private readonly _converterNamer = funPrefixNamer("converter", s => - snakeNameStyle(s, false, this.pyOptions.nicePropertyNames), + snakeNameStyle(s, false, this.pyOptions.nicePropertyNames) ); private readonly _topLevelConverterNames = new Map(); @@ -678,7 +668,7 @@ export class JSONPythonRenderer extends PythonRenderer { private _haveDateutil = false; - protected emitTypeVar (tvar: string, constraints: Sourcelike): void { + protected emitTypeVar(tvar: string, constraints: Sourcelike): void { if (!this.pyOptions.features.typeHints) { return; } @@ -686,7 +676,7 @@ export class JSONPythonRenderer extends PythonRenderer { this.emitLine(tvar, " = ", this.withTyping("TypeVar"), "(", this.string(tvar), constraints, ")"); } - protected typeVar (): string { + protected typeVar(): string { this._haveTypeVar = true; // FIXME: This is ugly, but the code that requires the type variables, in // `emitImports` actually runs after imports have been imported. The proper @@ -698,7 +688,7 @@ export class JSONPythonRenderer extends PythonRenderer { return "T"; } - protected enumTypeVar (): string { + protected enumTypeVar(): string { this._haveEnumTypeVar = true; // See the comment above. this.withTyping("TypeVar"); @@ -706,7 +696,7 @@ export class JSONPythonRenderer extends PythonRenderer { return "EnumT"; } - protected cast (type: Sourcelike, v: Sourcelike): Sourcelike { + protected cast(type: Sourcelike, v: Sourcelike): Sourcelike { if (!this.pyOptions.features.typeHints) { return v; } @@ -714,7 +704,7 @@ export class JSONPythonRenderer extends PythonRenderer { return [this.withTyping("cast"), "(", type, ", ", v, ")"]; } - protected emitNoneConverter (): void { + protected emitNoneConverter(): void { // FIXME: We can't return the None type here because mypy thinks that means // We're not returning any value, when we're actually returning `None`. this.emitBlock( @@ -722,39 +712,39 @@ export class JSONPythonRenderer extends PythonRenderer { () => { this.emitLine("assert x is None"); this.emitLine("return x"); - }, + } ); } - protected emitBoolConverter (): void { + protected emitBoolConverter(): void { this.emitBlock(["def from_bool(", this.typingDecl("x", "Any"), ")", this.typeHint(" -> bool"), ":"], () => { this.emitLine("assert isinstance(x, bool)"); this.emitLine("return x"); }); } - protected emitIntConverter (): void { + protected emitIntConverter(): void { this.emitBlock(["def from_int(", this.typingDecl("x", "Any"), ")", this.typeHint(" -> int"), ":"], () => { this.emitLine("assert isinstance(x, int) and not isinstance(x, bool)"); this.emitLine("return x"); }); } - protected emitFromFloatConverter (): void { + protected emitFromFloatConverter(): void { this.emitBlock(["def from_float(", this.typingDecl("x", "Any"), ")", this.typeHint(" -> float"), ":"], () => { this.emitLine("assert isinstance(x, (float, int)) and not isinstance(x, bool)"); this.emitLine("return float(x)"); }); } - protected emitToFloatConverter (): void { + protected emitToFloatConverter(): void { this.emitBlock(["def to_float(", this.typingDecl("x", "Any"), ")", this.typeHint(" -> float"), ":"], () => { this.emitLine("assert isinstance(x, float)"); this.emitLine("return x"); }); } - protected emitStrConverter (): void { + protected emitStrConverter(): void { this.emitBlock(["def from_str(", this.typingDecl("x", "Any"), ")", this.typeHint(" -> str"), ":"], () => { const strType = "str"; this.emitLine("assert isinstance(x, ", strType, ")"); @@ -762,7 +752,7 @@ export class JSONPythonRenderer extends PythonRenderer { }); } - protected emitToEnumConverter (): void { + protected emitToEnumConverter(): void { const tvar = this.enumTypeVar(); this.emitBlock( [ @@ -772,16 +762,16 @@ export class JSONPythonRenderer extends PythonRenderer { this.typingDecl("x", "Any"), ")", this.typeHint(" -> ", tvar), - ":", + ":" ], () => { this.emitLine("assert isinstance(x, c)"); this.emitLine("return x.value"); - }, + } ); } - protected emitListConverter (): void { + protected emitListConverter(): void { const tvar = this.typeVar(); this.emitBlock( [ @@ -791,16 +781,16 @@ export class JSONPythonRenderer extends PythonRenderer { this.typingDecl("x", "Any"), ")", this.typeHint(" -> ", this.withTyping("List"), "[", tvar, "]"), - ":", + ":" ], () => { this.emitLine("assert isinstance(x, list)"); this.emitLine("return [f(y) for y in x]"); - }, + } ); } - protected emitToClassConverter (): void { + protected emitToClassConverter(): void { const tvar = this.typeVar(); this.emitBlock( [ @@ -810,16 +800,16 @@ export class JSONPythonRenderer extends PythonRenderer { this.typingDecl("x", "Any"), ")", this.typeHint(" -> dict"), - ":", + ":" ], () => { this.emitLine("assert isinstance(x, c)"); this.emitLine("return ", this.cast(this.withTyping("Any"), "x"), ".to_dict()"); - }, + } ); } - protected emitDictConverter (): void { + protected emitDictConverter(): void { const tvar = this.typeVar(); this.emitBlock( [ @@ -829,18 +819,18 @@ export class JSONPythonRenderer extends PythonRenderer { this.typingDecl("x", "Any"), ")", this.typeHint(" -> ", this.withTyping("Dict"), "[str, ", tvar, "]"), - ":", + ":" ], () => { this.emitLine("assert isinstance(x, dict)"); this.emitLine("return { k: f(v) for (k, v) in x.items() }"); - }, + } ); } // This is not easily idiomatically typeable in Python. See // https://stackoverflow.com/questions/51066468/computed-types-in-mypy/51084497 - protected emitUnionConverter (): void { + protected emitUnionConverter(): void { this.emitMultiline(`def from_union(fs, x): for f in fs: try: @@ -850,34 +840,34 @@ export class JSONPythonRenderer extends PythonRenderer { assert False`); } - protected emitFromDatetimeConverter (): void { + protected emitFromDatetimeConverter(): void { this.emitBlock( [ "def from_datetime(", this.typingDecl("x", "Any"), ")", this.typeHint(" -> ", this.withImport("datetime", "datetime")), - ":", + ":" ], () => { this._haveDateutil = true; this.emitLine("return dateutil.parser.parse(x)"); - }, + } ); } - protected emitFromStringifiedBoolConverter (): void { + protected emitFromStringifiedBoolConverter(): void { this.emitBlock( ["def from_stringified_bool(x", this.typeHint(": str"), ")", this.typeHint(" -> bool"), ":"], () => { - this.emitBlock("if x == \"true\":", () => this.emitLine("return True")); - this.emitBlock("if x == \"false\":", () => this.emitLine("return False")); + this.emitBlock('if x == "true":', () => this.emitLine("return True")); + this.emitBlock('if x == "false":', () => this.emitLine("return False")); this.emitLine("assert False"); - }, + } ); } - protected emitIsTypeConverter (): void { + protected emitIsTypeConverter(): void { const tvar = this.typeVar(); this.emitBlock( [ @@ -887,58 +877,86 @@ export class JSONPythonRenderer extends PythonRenderer { this.typingDecl("x", "Any"), ")", this.typeHint(" -> ", tvar), - ":", + ":" ], () => { this.emitLine("assert isinstance(x, t)"); this.emitLine("return x"); - }, + } ); } - protected emitConverter (cf: ConverterFunction): void { + protected emitConverter(cf: ConverterFunction): void { switch (cf) { - case "none": - { this.emitNoneConverter(); return; } + case "none": { + this.emitNoneConverter(); + return; + } - case "bool": - { this.emitBoolConverter(); return; } + case "bool": { + this.emitBoolConverter(); + return; + } - case "int": - { this.emitIntConverter(); return; } + case "int": { + this.emitIntConverter(); + return; + } - case "from-float": - { this.emitFromFloatConverter(); return; } + case "from-float": { + this.emitFromFloatConverter(); + return; + } - case "to-float": - { this.emitToFloatConverter(); return; } + case "to-float": { + this.emitToFloatConverter(); + return; + } - case "str": - { this.emitStrConverter(); return; } + case "str": { + this.emitStrConverter(); + return; + } - case "to-enum": - { this.emitToEnumConverter(); return; } + case "to-enum": { + this.emitToEnumConverter(); + return; + } - case "list": - { this.emitListConverter(); return; } + case "list": { + this.emitListConverter(); + return; + } - case "to-class": - { this.emitToClassConverter(); return; } + case "to-class": { + this.emitToClassConverter(); + return; + } - case "dict": - { this.emitDictConverter(); return; } + case "dict": { + this.emitDictConverter(); + return; + } - case "union": - { this.emitUnionConverter(); return; } + case "union": { + this.emitUnionConverter(); + return; + } - case "from-datetime": - { this.emitFromDatetimeConverter(); return; } + case "from-datetime": { + this.emitFromDatetimeConverter(); + return; + } - case "from-stringified-bool": - { this.emitFromStringifiedBoolConverter(); return; } + case "from-stringified-bool": { + this.emitFromStringifiedBoolConverter(); + return; + } - case "is-type": - { this.emitIsTypeConverter(); return; } + case "is-type": { + this.emitIsTypeConverter(); + return; + } default: return assertNever(cf); @@ -946,7 +964,7 @@ export class JSONPythonRenderer extends PythonRenderer { } // Return the name of the Python converter function `cf`. - protected conv (cf: ConverterFunction): Sourcelike { + protected conv(cf: ConverterFunction): Sourcelike { this._deserializerFunctions.add(cf); const name = cf.replace(/-/g, "_"); if (cf.startsWith("from-") || cf.startsWith("to-") || cf.startsWith("is-")) return name; @@ -954,11 +972,11 @@ export class JSONPythonRenderer extends PythonRenderer { } // Applies the converter function to `arg` - protected convFn (cf: ConverterFunction, arg: ValueOrLambda): ValueOrLambda { + protected convFn(cf: ConverterFunction, arg: ValueOrLambda): ValueOrLambda { return compose(arg, { lambda: singleWord(this.conv(cf)), value: undefined }); } - protected typeObject (t: Type): Sourcelike { + protected typeObject(t: Type): Sourcelike { const s = matchType( t, _anyType => undefined, @@ -982,7 +1000,7 @@ export class JSONPythonRenderer extends PythonRenderer { } return undefined; - }, + } ); if (s === undefined) { return panic(`No type object for ${t.kind}`); @@ -991,7 +1009,7 @@ export class JSONPythonRenderer extends PythonRenderer { return s; } - protected transformer (inputTransformer: ValueOrLambda, xfer: Transformer, targetType: Type): ValueOrLambda { + protected transformer(inputTransformer: ValueOrLambda, xfer: Transformer, targetType: Type): ValueOrLambda { const consume = (consumer: Transformer | undefined, vol: ValueOrLambda) => { if (consumer === undefined) { return vol; @@ -1012,7 +1030,7 @@ export class JSONPythonRenderer extends PythonRenderer { arrayIntercalate(", ", lambdas), "], ", v, - ")", + ")" ]); } else if (xfer instanceof DecodingTransformer) { const consumer = xfer.consumer; @@ -1083,7 +1101,7 @@ export class JSONPythonRenderer extends PythonRenderer { // Returns the code to deserialize `value` as type `t`. If `t` has // an associated transformer, the code for that transformer is // returned. - protected deserializer (value: ValueOrLambda, t: Type): ValueOrLambda { + protected deserializer(value: ValueOrLambda, t: Type): ValueOrLambda { const xf = transformationForType(t); if (xf !== undefined) { return this.transformer(value, xf.transformer, xf.targetType); @@ -1104,12 +1122,12 @@ export class JSONPythonRenderer extends PythonRenderer { makeLambda(this.deserializer(identity, arrayType.items)).source, ", ", v, - ")", + ")" ]), classType => compose(value, { lambda: singleWord(this.nameForNamedType(classType), ".from_dict"), - value: undefined, + value: undefined }), mapType => compose(value, v => [ @@ -1118,13 +1136,13 @@ export class JSONPythonRenderer extends PythonRenderer { makeLambda(this.deserializer(identity, mapType.values)).source, ", ", v, - ")", + ")" ]), enumType => compose(value, { lambda: singleWord(this.nameForNamedType(enumType)), value: undefined }), unionType => { // FIXME: handle via transformers const deserializers = Array.from(unionType.members).map( - m => makeLambda(this.deserializer(identity, m)).source, + m => makeLambda(this.deserializer(identity, m)).source ); return compose(value, v => [ this.conv("union"), @@ -1132,7 +1150,7 @@ export class JSONPythonRenderer extends PythonRenderer { arrayIntercalate(", ", deserializers), "], ", v, - ")", + ")" ]); }, transformedStringType => { @@ -1146,11 +1164,11 @@ export class JSONPythonRenderer extends PythonRenderer { } return panic(`Transformed type ${transformedStringType.kind} not supported`); - }, + } ); } - protected serializer (value: ValueOrLambda, t: Type): ValueOrLambda { + protected serializer(value: ValueOrLambda, t: Type): ValueOrLambda { const xf = transformationForType(t); if (xf !== undefined) { const reverse = xf.reverse; @@ -1172,7 +1190,7 @@ export class JSONPythonRenderer extends PythonRenderer { makeLambda(this.serializer(identity, arrayType.items)).source, ", ", v, - ")", + ")" ]), classType => compose(value, v => [this.conv("to-class"), "(", this.nameForNamedType(classType), ", ", v, ")"]), @@ -1183,12 +1201,12 @@ export class JSONPythonRenderer extends PythonRenderer { makeLambda(this.serializer(identity, mapType.values)).source, ", ", v, - ")", + ")" ]), enumType => compose(value, v => [this.conv("to-enum"), "(", this.nameForNamedType(enumType), ", ", v, ")"]), unionType => { const serializers = Array.from(unionType.members).map( - m => makeLambda(this.serializer(identity, m)).source, + m => makeLambda(this.serializer(identity, m)).source ); return compose(value, v => [ this.conv("union"), @@ -1196,7 +1214,7 @@ export class JSONPythonRenderer extends PythonRenderer { arrayIntercalate(", ", serializers), "], ", v, - ")", + ")" ]); }, transformedStringType => { @@ -1209,11 +1227,11 @@ export class JSONPythonRenderer extends PythonRenderer { } return panic(`Transformed type ${transformedStringType.kind} not supported`); - }, + } ); } - protected emitClassMembers (t: ClassType): void { + protected emitClassMembers(t: ClassType): void { super.emitClassMembers(t); this.ensureBlankLine(); @@ -1231,7 +1249,7 @@ export class JSONPythonRenderer extends PythonRenderer { args.push(name); }); this.emitLine("return ", className, "(", arrayIntercalate(", ", args), ")"); - }, + } ); this.ensureBlankLine(); @@ -1245,7 +1263,7 @@ export class JSONPythonRenderer extends PythonRenderer { "result[", this.string(jsonName), "] = ", - makeValue(this.serializer(property, cp.type)), + makeValue(this.serializer(property, cp.type)) ); }); } else { @@ -1253,7 +1271,7 @@ export class JSONPythonRenderer extends PythonRenderer { "result[", this.string(jsonName), "] = ", - makeValue(this.serializer(property, cp.type)), + makeValue(this.serializer(property, cp.type)) ); } }); @@ -1261,7 +1279,7 @@ export class JSONPythonRenderer extends PythonRenderer { }); } - protected emitImports (): void { + protected emitImports(): void { super.emitImports(); if (this._haveDateutil) { this.emitLine("import dateutil.parser"); @@ -1279,32 +1297,32 @@ export class JSONPythonRenderer extends PythonRenderer { } } - protected emitSupportCode (): void { + protected emitSupportCode(): void { const map = Array.from(this._deserializerFunctions).map(f => [f, f] as [ConverterFunction, ConverterFunction]); this.forEachWithBlankLines(map, ["interposing", 2], cf => { this.emitConverter(cf); }); } - protected makeTopLevelDependencyNames (_t: Type, topLevelName: Name): DependencyName[] { + protected makeTopLevelDependencyNames(_t: Type, topLevelName: Name): DependencyName[] { const fromDict = new DependencyName( this._converterNamer, topLevelNameOrder, - l => `${l(topLevelName)}_from_dict`, + l => `${l(topLevelName)}_from_dict` ); const toDict = new DependencyName(this._converterNamer, topLevelNameOrder, l => `${l(topLevelName)}_to_dict`); this._topLevelConverterNames.set(topLevelName, { fromDict, toDict }); return [fromDict, toDict]; } - protected emitDefaultLeadingComments (): void { + protected emitDefaultLeadingComments(): void { this.ensureBlankLine(); if (this._haveDateutil) { this.emitCommentLines([ "This code parses date/times, so please", "", " pip install python-dateutil", - "", + "" ]); } @@ -1314,7 +1332,7 @@ export class JSONPythonRenderer extends PythonRenderer { " import json", "", "and then, to convert JSON from a string, do", - "", + "" ]); this.forEachTopLevel("none", (_, name) => { const { fromDict } = defined(this._topLevelConverterNames.get(name)); @@ -1322,7 +1340,7 @@ export class JSONPythonRenderer extends PythonRenderer { }); } - protected emitClosingCode (): void { + protected emitClosingCode(): void { this.forEachTopLevel(["interposing", 2], (t, name) => { const { fromDict, toDict } = defined(this._topLevelConverterNames.get(name)); const pythonType = this.pythonType(t); @@ -1330,14 +1348,14 @@ export class JSONPythonRenderer extends PythonRenderer { ["def ", fromDict, "(", this.typingDecl("s", "Any"), ")", this.typeHint(" -> ", pythonType), ":"], () => { this.emitLine("return ", makeValue(this.deserializer({ value: "s" }, t))); - }, + } ); this.ensureBlankLine(2); this.emitBlock( ["def ", toDict, "(x", this.typeHint(": ", pythonType), ")", this.typingReturn("Any"), ":"], () => { this.emitLine("return ", makeValue(this.serializer({ value: "x" }, t))); - }, + } ); }); } diff --git a/packages/quicktype-core/src/language/Rust.ts b/packages/quicktype-core/src/language/Rust.ts index fe5941cdc..9c69ed654 100644 --- a/packages/quicktype-core/src/language/Rust.ts +++ b/packages/quicktype-core/src/language/Rust.ts @@ -121,7 +121,7 @@ export class RustTargetLanguage extends TargetLanguage { return new RustRenderer(this, renderContext, getOptionValues(rustOptions, untypedOptionValues)); } - constructor() { + public constructor() { super("Rust", ["rust", "rs", "rustlang"], "rs"); } @@ -267,7 +267,7 @@ const standardUnicodeRustEscape = (codePoint: number): string => { const rustStringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, standardUnicodeRustEscape)); export class RustRenderer extends ConvenienceRenderer { - constructor( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues diff --git a/packages/quicktype-core/src/language/Scala3.ts b/packages/quicktype-core/src/language/Scala3.ts index c173aed7c..843c2ad4d 100644 --- a/packages/quicktype-core/src/language/Scala3.ts +++ b/packages/quicktype-core/src/language/Scala3.ts @@ -193,7 +193,7 @@ const upperNamingFunction = funPrefixNamer("upper", s => scalaNameStyle(true, s) const lowerNamingFunction = funPrefixNamer("lower", s => scalaNameStyle(false, s)); export class Scala3Renderer extends ConvenienceRenderer { - constructor( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, protected readonly _scalaOptions: OptionValues @@ -250,10 +250,10 @@ export class Scala3Renderer extends ConvenienceRenderer { delimiter === "curly" ? ["{", "}"] : delimiter === "paren" - ? ["(", ")"] - : delimiter === "none" - ? ["", ""] - : ["{", "})"]; + ? ["(", ")"] + : delimiter === "none" + ? ["", ""] + : ["{", "})"]; this.emitLine(line, " ", open); this.indent(f); this.emitLine(close); @@ -551,7 +551,7 @@ export class Smithy4sRenderer extends Scala3Renderer { } export class CirceRenderer extends Scala3Renderer { - seenUnionTypes: string[] = []; + private seenUnionTypes: string[] = []; protected circeEncoderForType(t: Type, _ = false, noOptional = false, paramName: string = ""): Sourcelike { return matchType( @@ -737,7 +737,7 @@ export class CirceRenderer extends Scala3Renderer { } export class Scala3TargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super("Scala3", ["scala3"], "scala"); } @@ -745,11 +745,11 @@ export class Scala3TargetLanguage extends TargetLanguage { return [scala3Options.framework, scala3Options.packageName]; } - get supportsOptionalClassProperties(): boolean { + public get supportsOptionalClassProperties(): boolean { return true; } - get supportsUnionsWithBothNumberTypes(): boolean { + public get supportsUnionsWithBothNumberTypes(): boolean { return true; } diff --git a/packages/quicktype-core/src/language/Smithy4s.ts b/packages/quicktype-core/src/language/Smithy4s.ts index 816da3125..0b28a824e 100644 --- a/packages/quicktype-core/src/language/Smithy4s.ts +++ b/packages/quicktype-core/src/language/Smithy4s.ts @@ -153,7 +153,7 @@ const upperNamingFunction = funPrefixNamer("upper", s => scalaNameStyle(true, s) const lowerNamingFunction = funPrefixNamer("lower", s => scalaNameStyle(false, s)); export class Smithy4sRenderer extends ConvenienceRenderer { - constructor( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, protected readonly _scalaOptions: OptionValues @@ -210,10 +210,10 @@ export class Smithy4sRenderer extends ConvenienceRenderer { delimiter === "curly" ? ["{", "}"] : delimiter === "paren" - ? ["(", ")"] - : delimiter === "none" - ? ["", ""] - : ["{", "})"]; + ? ["(", ")"] + : delimiter === "none" + ? ["", ""] + : ["{", "})"]; this.emitLine(line, " ", open); this.indent(f); this.emitLine(close); @@ -521,7 +521,7 @@ export class Smithy4sRenderer extends ConvenienceRenderer { } export class SmithyTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super("Smithy", ["Smithy"], "smithy"); } @@ -529,11 +529,11 @@ export class SmithyTargetLanguage extends TargetLanguage { return [SmithyOptions.framework, SmithyOptions.packageName]; } - get supportsOptionalClassProperties(): boolean { + public get supportsOptionalClassProperties(): boolean { return true; } - get supportsUnionsWithBothNumberTypes(): boolean { + public get supportsUnionsWithBothNumberTypes(): boolean { return true; } diff --git a/packages/quicktype-core/src/language/Swift.ts b/packages/quicktype-core/src/language/Swift.ts index bc8cd35ca..25cf19e02 100644 --- a/packages/quicktype-core/src/language/Swift.ts +++ b/packages/quicktype-core/src/language/Swift.ts @@ -9,19 +9,15 @@ import { type TypeKind, type ClassProperty, type TransformedStringTypeKind, - type PrimitiveStringTypeKind, -} from "../Type"; -import { - EnumType, - ArrayType, - MapType, + type PrimitiveStringTypeKind } from "../Type"; +import { EnumType, ArrayType, MapType } from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { type Name, type Namer} from "../Naming"; +import { type Name, type Namer } from "../Naming"; import { funPrefixNamer } from "../Naming"; -import { type Option, type OptionValues} from "../RendererOptions"; +import { type Option, type OptionValues } from "../RendererOptions"; import { BooleanOption, EnumOption, StringOption, getOptionValues } from "../RendererOptions"; -import { type Sourcelike} from "../Source"; +import { type Sourcelike } from "../Source"; import { maybeAnnotated, modifySource } from "../Source"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; @@ -41,7 +37,7 @@ import { allLowerWordStyle, allUpperWordStyle, camelCase, - addPrefixIfNecessary, + addPrefixIfNecessary } from "../support/Strings"; import { type RenderContext, type ForEachPosition } from "../Renderer"; import { type StringTypeMapping } from "../TypeBuilder"; @@ -60,7 +56,7 @@ export const swiftOptions = { namedTypePrefix: new StringOption("type-prefix", "Prefix for type names", "PREFIX", "", "secondary"), useClasses: new EnumOption("struct-or-class", "Structs or classes", [ ["struct", false], - ["class", true], + ["class", true] ]), mutableProperties: new BooleanOption("mutable-properties", "Use var instead of let for object properties", false), acronymStyle: acronymOption(AcronymStyleOptions.Pascal), @@ -69,16 +65,16 @@ export const swiftOptions = { "Code density", [ ["dense", true], - ["normal", false], + ["normal", false] ], "dense", - "secondary", + "secondary" ), linux: new BooleanOption("support-linux", "Support Linux", false, "secondary"), objcSupport: new BooleanOption( "objective-c-support", "Objects inherit from NSObject and @objcMembers is added to classes", - false, + false ), optionalEnums: new BooleanOption("optional-enums", "If no matching case is found enum value is set to null", false), swift5Support: new BooleanOption("swift-5-support", "Renders output in a Swift 5 compatible mode", false), @@ -86,17 +82,17 @@ export const swiftOptions = { multiFileOutput: new BooleanOption( "multi-file-output", "Renders each top-level object in its own Swift file", - false, + false ), accessLevel: new EnumOption( "access-level", "Access level", [ ["internal", "internal"], - ["public", "public"], + ["public", "public"] ], "internal", - "secondary", + "secondary" ), protocol: new EnumOption( "protocol", @@ -104,11 +100,11 @@ export const swiftOptions = { [ ["none", { equatable: false, hashable: false }], ["equatable", { equatable: true, hashable: false }], - ["hashable", { equatable: false, hashable: true }], + ["hashable", { equatable: false, hashable: true }] ], "none", - "secondary", - ), + "secondary" + ) }; // These are all recognized by Swift as ISO8601 date-times: @@ -125,7 +121,7 @@ export const swiftOptions = { const swiftDateTimeRegex = /^\d+-\d+-\d+T\d+:\d+:\d+([zZ]|[+-]\d+(:\d+)?)$/; class SwiftDateTimeRecognizer extends DefaultDateTimeRecognizer { - isDateTime (str: string): boolean { + public isDateTime(str: string): boolean { return swiftDateTimeRegex.exec(str) !== null; } } @@ -138,11 +134,11 @@ export interface SwiftProperty { } export class SwiftTargetLanguage extends TargetLanguage { - constructor () { + public constructor() { super("Swift", ["swift", "swift4"], "swift"); } - protected getOptions (): Array> { + protected getOptions(): Array> { return [ swiftOptions.justTypes, swiftOptions.useClasses, @@ -160,29 +156,29 @@ export class SwiftTargetLanguage extends TargetLanguage { swiftOptions.sendable, swiftOptions.swift5Support, swiftOptions.multiFileOutput, - swiftOptions.mutableProperties, + swiftOptions.mutableProperties ]; } - get stringTypeMapping (): StringTypeMapping { + public get stringTypeMapping(): StringTypeMapping { const mapping: Map = new Map(); mapping.set("date-time", "date-time"); return mapping; } - get supportsOptionalClassProperties (): boolean { + public get supportsOptionalClassProperties(): boolean { return true; } - get supportsUnionsWithBothNumberTypes (): boolean { + public get supportsUnionsWithBothNumberTypes(): boolean { return true; } - protected makeRenderer (renderContext: RenderContext, untypedOptionValues: { [name: string]: any, }): SwiftRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): SwiftRenderer { return new SwiftRenderer(this, renderContext, getOptionValues(swiftOptions, untypedOptionValues)); } - get dateTimeRecognizer (): DateTimeRecognizer { + public get dateTimeRecognizer(): DateTimeRecognizer { return new SwiftDateTimeRecognizer(); } } @@ -286,24 +282,24 @@ const keywords = [ "convertDict", "convertDouble", "jsonString", - "jsonData", + "jsonData" ]; -function isPartCharacter (codePoint: number): boolean { +function isPartCharacter(codePoint: number): boolean { return isLetterOrUnderscore(codePoint) || isNumeric(codePoint); } -function isStartCharacter (codePoint: number): boolean { +function isStartCharacter(codePoint: number): boolean { return isPartCharacter(codePoint) && !isDigit(codePoint); } const legalizeName = legalizeCharacters(isPartCharacter); -function swiftNameStyle ( +function swiftNameStyle( prefix: string, isUpper: boolean, original: string, - acronymsStyle: (s: string) => string = allUpperWordStyle, + acronymsStyle: (s: string) => string = allUpperWordStyle ): string { const words = splitIntoWords(original); const combined = combineWords( @@ -314,12 +310,12 @@ function swiftNameStyle ( isUpper ? allUpperWordStyle : allLowerWordStyle, acronymsStyle, "", - isStartCharacter, + isStartCharacter ); return addPrefixIfNecessary(prefix, combined); } -function unicodeEscape (codePoint: number): string { +function unicodeEscape(codePoint: number): string { return "\\u{" + intToHex(codePoint, 0) + "}"; } @@ -332,15 +328,15 @@ export class SwiftRenderer extends ConvenienceRenderer { private _needNull = false; - constructor ( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues, + private readonly _options: OptionValues ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace (): string[] { + protected forbiddenNamesForGlobalNamespace(): string[] { if (this._options.alamofire) { return ["DataRequest", ...keywords]; } @@ -348,73 +344,73 @@ export class SwiftRenderer extends ConvenienceRenderer { return keywords; } - protected forbiddenForObjectProperties (_c: ClassType, _classNamed: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties(_c: ClassType, _classNamed: Name): ForbiddenWordsInfo { return { names: ["fromURL", "json"], includeGlobalForbidden: true }; } - protected forbiddenForEnumCases (_e: EnumType, _enumName: Name): ForbiddenWordsInfo { + protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForUnionMembers (_u: UnionType, _unionName: Name): ForbiddenWordsInfo { + protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected makeNamedTypeNamer (): Namer { + protected makeNamedTypeNamer(): Namer { return funPrefixNamer("upper", s => - swiftNameStyle(this._options.namedTypePrefix, true, s, acronymStyle(this._options.acronymStyle)), + swiftNameStyle(this._options.namedTypePrefix, true, s, acronymStyle(this._options.acronymStyle)) ); } - protected namerForObjectProperty (): Namer { + protected namerForObjectProperty(): Namer { return this.lowerNamingFunction; } - protected makeUnionMemberNamer (): Namer { + protected makeUnionMemberNamer(): Namer { return this.lowerNamingFunction; } - protected makeEnumCaseNamer (): Namer { + protected makeEnumCaseNamer(): Namer { return this.lowerNamingFunction; } - protected isImplicitCycleBreaker (t: Type): boolean { + protected isImplicitCycleBreaker(t: Type): boolean { const kind = t.kind; return kind === "array" || kind === "map"; } - protected emitDescriptionBlock (lines: Sourcelike[]): void { + protected emitDescriptionBlock(lines: Sourcelike[]): void { this.emitCommentLines(lines, { lineStart: "/// " }); } - private emitBlock (line: Sourcelike, f: () => void): void { + private emitBlock(line: Sourcelike, f: () => void): void { this.emitLine(line, " {"); this.indent(f); this.emitLine("}"); } - private emitBlockWithAccess (line: Sourcelike, f: () => void): void { + private emitBlockWithAccess(line: Sourcelike, f: () => void): void { this.emitBlock([this.accessLevel, line], f); } - private justTypesCase (justTypes: Sourcelike, notJustTypes: Sourcelike): Sourcelike { + private justTypesCase(justTypes: Sourcelike, notJustTypes: Sourcelike): Sourcelike { if (this._options.justTypes) return justTypes; else return notJustTypes; } - private get lowerNamingFunction () { + private get lowerNamingFunction() { return funPrefixNamer("lower", s => swiftNameStyle("", false, s, acronymStyle(this._options.acronymStyle))); } - protected swiftPropertyType (p: ClassProperty): Sourcelike { - if (p.isOptional || this._options.optionalEnums && p.type.kind === "enum") { + protected swiftPropertyType(p: ClassProperty): Sourcelike { + if (p.isOptional || (this._options.optionalEnums && p.type.kind === "enum")) { return [this.swiftType(p.type, true, true), "?"]; } else { return this.swiftType(p.type, true); } } - protected swiftType (t: Type, withIssues = false, noOptional = false): Sourcelike { + protected swiftType(t: Type, withIssues = false, noOptional = false): Sourcelike { const optional = noOptional ? "" : "?"; return matchType( t, @@ -423,7 +419,7 @@ export class SwiftRenderer extends ConvenienceRenderer { return maybeAnnotated( withIssues, anyTypeIssueAnnotation, - this.justTypesCase(["Any", optional], "JSONAny"), + this.justTypesCase(["Any", optional], "JSONAny") ); }, _nullType => { @@ -431,7 +427,7 @@ export class SwiftRenderer extends ConvenienceRenderer { return maybeAnnotated( withIssues, nullTypeIssueAnnotation, - this.justTypesCase("NSNull", ["JSONNull", optional]), + this.justTypesCase("NSNull", ["JSONNull", optional]) ); }, _boolType => "Bool", @@ -453,11 +449,11 @@ export class SwiftRenderer extends ConvenienceRenderer { } else { return panic(`Transformed string type ${transformedStringType.kind} not supported`); } - }, + } ); } - protected proposedUnionMemberNameForTypeKind (kind: TypeKind): string | null { + protected proposedUnionMemberNameForTypeKind(kind: TypeKind): string | null { if (kind === "enum") { return "enumeration"; } @@ -469,7 +465,7 @@ export class SwiftRenderer extends ConvenienceRenderer { return null; } - private renderSingleFileHeaderComments (): void { + private renderSingleFileHeaderComments(): void { this.emitLineOnce("// This file was generated from JSON Schema using quicktype, do not modify it directly."); this.emitLineOnce("// To parse the JSON, add this file to your project and do:"); this.emitLineOnce("//"); @@ -480,7 +476,7 @@ export class SwiftRenderer extends ConvenienceRenderer { modifySource(camelCase, topLevelName), " = try ", topLevelName, - "(json)", + "(json)" ); } else { this.emitLineOnce( @@ -489,19 +485,19 @@ export class SwiftRenderer extends ConvenienceRenderer { " = ", "try? JSONDecoder().decode(", topLevelName, - ".self, from: jsonData)", + ".self, from: jsonData)" ); } }); } - private renderHeader (type: Type, name: Name): void { + private renderHeader(type: Type, name: Name): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } else if (!this._options.justTypes) { if (this._options.multiFileOutput) { this.emitLineOnce( - "// This file was generated from JSON Schema using quicktype, do not modify it directly.", + "// This file was generated from JSON Schema using quicktype, do not modify it directly." ); this.emitLineOnce("// To parse the JSON, add this file to your project and do:"); this.emitLineOnce("//"); @@ -514,7 +510,7 @@ export class SwiftRenderer extends ConvenienceRenderer { " = ", "try? newJSONDecoder().decode(", name, - ".self, from: jsonData)", + ".self, from: jsonData)" ); } } @@ -534,10 +530,10 @@ export class SwiftRenderer extends ConvenienceRenderer { this.emitLine("//"); this.emitLine("// Hashable or Equatable:"); this.emitLine( - "// The compiler will not be able to synthesize the implementation of Hashable or Equatable", + "// The compiler will not be able to synthesize the implementation of Hashable or Equatable" ); this.emitLine( - "// for types that require the use of JSONAny, nor will the implementation of Hashable be", + "// for types that require the use of JSONAny, nor will the implementation of Hashable be" ); this.emitLine("// synthesized for types that have collections (such as arrays or dictionaries)."); } @@ -556,11 +552,11 @@ export class SwiftRenderer extends ConvenienceRenderer { this.ensureBlankLine(); } - private renderTopLevelAlias (t: Type, name: Name): void { + private renderTopLevelAlias(t: Type, name: Name): void { this.emitLine(this.accessLevel, "typealias ", name, " = ", this.swiftType(t, true)); } - protected getProtocolsArray (kind: "struct" | "class" | "enum"): string[] { + protected getProtocolsArray(kind: "struct" | "class" | "enum"): string[] { const protocols: string[] = []; // [Michael Fey (@MrRooni), 2019-4-24] Technically NSObject isn't a "protocol" in this instance, but this felt like the best place to slot in this superclass declaration. @@ -589,9 +585,9 @@ export class SwiftRenderer extends ConvenienceRenderer { return protocols; } - private getProtocolString ( + private getProtocolString( kind: "struct" | "class" | "enum", - baseClass: string | undefined = undefined, + baseClass: string | undefined = undefined ): Sourcelike { let protocols = this.getProtocolsArray(kind); if (baseClass) { @@ -601,8 +597,8 @@ export class SwiftRenderer extends ConvenienceRenderer { return protocols.length > 0 ? ": " + protocols.join(", ") : ""; } - private getEnumPropertyGroups (c: ClassType) { - type PropertyGroup = Array<{ label?: string, name: Name, }>; + private getEnumPropertyGroups(c: ClassType) { + type PropertyGroup = Array<{ label?: string; name: Name }>; let groups: PropertyGroup[] = []; let group: PropertyGroup = []; @@ -631,13 +627,13 @@ export class SwiftRenderer extends ConvenienceRenderer { } /// Access level with trailing space (e.g. "public "), or empty string - private get accessLevel (): string { + private get accessLevel(): string { return this._options.accessLevel === "internal" ? "" // internal is default, so we don't have to emit it : this._options.accessLevel + " "; } - private get objcMembersDeclaration (): string { + private get objcMembersDeclaration(): string { if (this._options.objcSupport) { return "@objcMembers "; } @@ -646,7 +642,7 @@ export class SwiftRenderer extends ConvenienceRenderer { } /// startFile takes a file name, appends ".swift" to it and sets it as the current filename. - protected startFile (basename: Sourcelike): void { + protected startFile(basename: Sourcelike): void { if (this._options.multiFileOutput === false) { return; } @@ -658,7 +654,7 @@ export class SwiftRenderer extends ConvenienceRenderer { } /// endFile pushes the current file name onto the collection of finished files and then resets the current file name. These finished files are used in index.ts to write the output. - protected endFile (): void { + protected endFile(): void { if (this._options.multiFileOutput === false) { return; } @@ -667,18 +663,18 @@ export class SwiftRenderer extends ConvenienceRenderer { this._currentFilename = undefined; } - protected propertyLinesDefinition (name: Name, parameter: ClassProperty): Sourcelike { + protected propertyLinesDefinition(name: Name, parameter: ClassProperty): Sourcelike { const useMutableProperties = this._options.mutableProperties; return [ this.accessLevel, useMutableProperties ? "var " : "let ", name, ": ", - this.swiftPropertyType(parameter), + this.swiftPropertyType(parameter) ]; } - private renderClassDefinition (c: ClassType, className: Name): void { + private renderClassDefinition(c: ClassType, className: Name): void { this.startFile(className); this.renderHeader(c, className); @@ -710,10 +706,10 @@ export class SwiftRenderer extends ConvenienceRenderer { ? "@OptionallyDecodable " : "", this.accessLevel, - useMutableProperties || this._options.optionalEnums && lastProperty.type.kind === "enum" + useMutableProperties || (this._options.optionalEnums && lastProperty.type.kind === "enum") ? "var " - : "let ", - ], + : "let " + ] ]; lastNames.forEach((n, i) => { if (i > 0) sources.push(", "); @@ -768,11 +764,11 @@ export class SwiftRenderer extends ConvenienceRenderer { for (const group of groups) { const { name, label } = group[0]; if (this._options.explicitCodingKeys && label !== undefined) { - this.emitLine("case ", name, " = \"", label, "\""); + this.emitLine("case ", name, ' = "', label, '"'); } else { const names = arrayIntercalate( ", ", - group.map(p => p.name), + group.map(p => p.name) ); this.emitLine("case ", names); } @@ -826,7 +822,7 @@ export class SwiftRenderer extends ConvenienceRenderer { this.endFile(); } - protected initializableProperties (c: ClassType): SwiftProperty[] { + protected initializableProperties(c: ClassType): SwiftProperty[] { const properties: SwiftProperty[] = []; this.forEachClassProperty(c, "none", (name, jsonName, parameter, position) => { const property = { name, jsonName, parameter, position }; @@ -835,7 +831,7 @@ export class SwiftRenderer extends ConvenienceRenderer { return properties; } - private emitNewEncoderDecoder (): void { + private emitNewEncoderDecoder(): void { this.emitBlock("func newJSONDecoder() -> JSONDecoder", () => { this.emitLine("let decoder = JSONDecoder()"); if (!this._options.linux) { @@ -885,7 +881,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); }); } - private emitConvenienceInitializersExtension (c: ClassType, className: Name): void { + private emitConvenienceInitializersExtension(c: ClassType, className: Name): void { const isClass = this._options.useClasses || this.isCycleBreakerType(c); const convenience = isClass ? "convenience " : ""; @@ -916,10 +912,10 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); [convenience, "init(_ json: String, using encoding: String.Encoding = .utf8) throws"], () => { this.emitBlock("guard let data = json.data(using: encoding) else", () => { - this.emitLine("throw NSError(domain: \"JSONDecoding\", code: 0, userInfo: nil)"); + this.emitLine('throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)'); }); this.emitLine("try self.init(data: data)"); - }, + } ); this.ensureBlankLine(); this.emitBlock([convenience, "init(fromURL url: URL) throws"], () => { @@ -941,7 +937,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); }); } - private renderEnumDefinition (e: EnumType, enumName: Name): void { + private renderEnumDefinition(e: EnumType, enumName: Name): void { this.startFile(enumName); this.emitLineOnce("import Foundation"); @@ -959,7 +955,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); } else { this.emitBlockWithAccess(["enum ", enumName, protocolString], () => { this.forEachEnumCase(e, "none", (name, jsonName) => { - this.emitLine("case ", name, " = \"", stringEscape(jsonName), "\""); + this.emitLine("case ", name, ' = "', stringEscape(jsonName), '"'); }); }); } @@ -967,13 +963,13 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); this.endFile(); } - private renderUnionDefinition (u: UnionType, unionName: Name): void { + private renderUnionDefinition(u: UnionType, unionName: Name): void { this.startFile(unionName); this.emitLineOnce("import Foundation"); this.ensureBlankLine(); - function sortBy (t: Type): string { + function sortBy(t: Type): string { const kind = t.kind; if (kind === "class") return kind; return "_" + kind; @@ -1040,7 +1036,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); this.endFile(); } - private emitTopLevelMapAndArrayConvenienceInitializerExtensions (t: Type, name: Name): void { + private emitTopLevelMapAndArrayConvenienceInitializerExtensions(t: Type, name: Name): void { let extensionSource: Sourcelike; if (t instanceof ArrayType) { @@ -1058,7 +1054,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); this.ensureBlankLine(); this.emitBlock("init(_ json: String, using encoding: String.Encoding = .utf8) throws", () => { this.emitBlock("guard let data = json.data(using: encoding) else", () => { - this.emitLine("throw NSError(domain: \"JSONDecoding\", code: 0, userInfo: nil)"); + this.emitLine('throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)'); }); this.emitLine("try self.init(data: data)"); }); @@ -1077,13 +1073,13 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); }); } - private emitDecodingError (name: Name): void { + private emitDecodingError(name: Name): void { this.emitLine( "throw DecodingError.typeMismatch(", name, - ".self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: \"Wrong type for ", + '.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for ', name, - "\"))", + '"))' ); } @@ -1095,17 +1091,17 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); this.forEachTopLevel( "leading", (t: Type, name: Name) => this.renderTopLevelAlias(t, name), - t => this.namedTypeToNameForTopLevel(t) === undefined, + t => this.namedTypeToNameForTopLevel(t) === undefined ); if (this._options.convenienceInitializers) { this.ensureBlankLine(); this.forEachTopLevel("leading-and-interposing", (t: Type, name: Name) => - this.emitTopLevelMapAndArrayConvenienceInitializerExtensions(t, name), + this.emitTopLevelMapAndArrayConvenienceInitializerExtensions(t, name) ); } - if (!this._options.justTypes && this._options.convenienceInitializers || this._options.alamofire) { + if ((!this._options.justTypes && this._options.convenienceInitializers) || this._options.alamofire) { this.ensureBlankLine(); this.emitMark("Helper functions for creating encoders and decoders", true); this.ensureBlankLine(); @@ -1400,7 +1396,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); this.endFile(); }; - private emitConvenienceMutator (c: ClassType, className: Name) { + private emitConvenienceMutator(c: ClassType, className: Name) { this.emitLine("func with("); this.indent(() => { this.forEachClassProperty(c, "none", (name, _, p, position) => { @@ -1409,7 +1405,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); ": ", this.swiftPropertyType(p), "? = nil", - position !== "only" && position !== "last" ? "," : "", + position !== "only" && position !== "last" ? "," : "" ); }); }); @@ -1423,7 +1419,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); name, " ?? self.", name, - position !== "only" && position !== "last" ? "," : "", + position !== "only" && position !== "last" ? "," : "" ); }); }); @@ -1431,11 +1427,11 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); }); } - protected emitMark (line: Sourcelike, horizontalLine = false) { + protected emitMark(line: Sourcelike, horizontalLine = false) { this.emitLine("// MARK:", horizontalLine ? " - " : " ", line); } - protected emitSourceStructure (): void { + protected emitSourceStructure(): void { if (this._options.multiFileOutput === false) { this.renderSingleFileHeaderComments(); } @@ -1444,7 +1440,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); "leading-and-interposing", (c: ClassType, className: Name) => this.renderClassDefinition(c, className), (e: EnumType, enumName: Name) => this.renderEnumDefinition(e, enumName), - (u: UnionType, unionName: Name) => this.renderUnionDefinition(u, unionName), + (u: UnionType, unionName: Name) => this.renderUnionDefinition(u, unionName) ); if (!this._options.justTypes) { @@ -1452,7 +1448,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); } } - private emitAlamofireExtension () { + private emitAlamofireExtension() { this.ensureBlankLine(); this.emitBlockWithAccess("extension DataRequest", () => { this @@ -1481,11 +1477,11 @@ fileprivate func responseDecodable(queue: DispatchQueue? = nil, co name, "(queue: DispatchQueue? = nil, completionHandler: @escaping (DataResponse<", name, - ">) -> Void) -> Self", + ">) -> Void) -> Self" ], () => { this.emitLine("return responseDecodable(queue: queue, completionHandler: completionHandler)"); - }, + } ); }); }); diff --git a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts index 2629cff39..772260388 100644 --- a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts +++ b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts @@ -16,7 +16,7 @@ import { isLetterOrUnderscore, splitIntoWords, stringEscape, - utf16StringEscape, + utf16StringEscape } from "../support/Strings"; import { TargetLanguage } from "../TargetLanguage"; import { legalizeName } from "./JavaScript"; @@ -25,48 +25,50 @@ import { panic } from "../support/Support"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; export const typeScriptEffectSchemaOptions = { - justSchema: new BooleanOption("just-schema", "Schema only", false), + justSchema: new BooleanOption("just-schema", "Schema only", false) }; export class TypeScriptEffectSchemaTargetLanguage extends TargetLanguage { - protected getOptions (): Array> { + protected getOptions(): Array> { return []; } - constructor ( + public constructor( displayName: string = "TypeScript Effect Schema", names: string[] = ["typescript-effect-schema"], - extension: string = "ts", + extension: string = "ts" ) { super(displayName, names, extension); } - protected makeRenderer ( + protected makeRenderer( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any, }, + untypedOptionValues: { [name: string]: any } ): TypeScriptEffectSchemaRenderer { return new TypeScriptEffectSchemaRenderer( this, renderContext, - getOptionValues(typeScriptEffectSchemaOptions, untypedOptionValues), + getOptionValues(typeScriptEffectSchemaOptions, untypedOptionValues) ); } } export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { - constructor ( + private emittedObjects = new Set(); + + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues, + private readonly _options: OptionValues ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace (): string[] { + protected forbiddenNamesForGlobalNamespace(): string[] { return ["Class", "Date", "Object", "String", "Array", "JSON", "Error"]; } - protected nameStyle (original: string, upper: boolean): string { + protected nameStyle(original: string, upper: boolean): string { const acronyms = acronymStyle(AcronymStyleOptions.Camel); const words = splitIntoWords(original); return combineWords( @@ -77,43 +79,41 @@ export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { upper ? s => capitalize(acronyms(s)) : allLowerWordStyle, acronyms, "", - isLetterOrUnderscore, + isLetterOrUnderscore ); } - protected makeNamedTypeNamer (): Namer { + protected makeNamedTypeNamer(): Namer { return funPrefixNamer("types", s => this.nameStyle(s, true)); } - protected makeUnionMemberNamer (): Namer { + protected makeUnionMemberNamer(): Namer { return funPrefixNamer("properties", s => this.nameStyle(s, true)); } - protected namerForObjectProperty (): Namer { + protected namerForObjectProperty(): Namer { return funPrefixNamer("properties", s => this.nameStyle(s, true)); } - protected makeEnumCaseNamer (): Namer { + protected makeEnumCaseNamer(): Namer { return funPrefixNamer("enum-cases", s => this.nameStyle(s, false)); } - private importStatement (lhs: Sourcelike, moduleName: Sourcelike): Sourcelike { + private importStatement(lhs: Sourcelike, moduleName: Sourcelike): Sourcelike { return ["import ", lhs, " from ", moduleName, ";"]; } - protected emitImports (): void { + protected emitImports(): void { this.ensureBlankLine(); - this.emitLine(this.importStatement("* as S", "\"@effect/schema/Schema\"")); + this.emitLine(this.importStatement("* as S", '"@effect/schema/Schema"')); } - typeMapTypeForProperty (p: ClassProperty): Sourcelike { + private typeMapTypeForProperty(p: ClassProperty): Sourcelike { const typeMap = this.typeMapTypeFor(p.type); return p.isOptional ? ["S.optional(", typeMap, ")"] : typeMap; } - emittedObjects = new Set(); - - typeMapTypeFor (t: Type, required: boolean = true): Sourcelike { + private typeMapTypeFor(t: Type, required: boolean = true): Sourcelike { if (t.kind === "class" || t.kind === "object" || t.kind === "enum") { const name = this.nameForNamedType(t); if (this.emittedObjects.has(name)) { @@ -137,13 +137,13 @@ export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { _enumType => panic("Should already be handled."), unionType => { const children = Array.from(unionType.getChildren()).map((type: Type) => - this.typeMapTypeFor(type, false), + this.typeMapTypeFor(type, false) ); return ["S.union(", ...arrayIntercalate(", ", children), ")"]; }, _transformedStringType => { return "S.string"; - }, + } ); if (required) { @@ -153,10 +153,10 @@ export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { return match; } - private emitObject (name: Name, t: ObjectType) { + private emitObject(name: Name, t: ObjectType) { this.emittedObjects.add(name); this.ensureBlankLine(); - this.emitLine("\nexport class ", name, " extends S.Class<", name, ">(\"", name, "\")({"); + this.emitLine("\nexport class ", name, " extends S.Class<", name, '>("', name, '")({'); this.indent(() => { this.forEachClassProperty(t, "none", (_, jsonName, property) => { this.emitLine(`"${utf16StringEscape(jsonName)}"`, ": ", this.typeMapTypeForProperty(property), ","); @@ -165,15 +165,15 @@ export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { this.emitLine("}) {}"); } - private emitEnum (e: EnumType, enumName: Name): void { + private emitEnum(e: EnumType, enumName: Name): void { this.emittedObjects.add(enumName); this.ensureBlankLine(); this.emitDescription(this.descriptionForType(e)); this.emitLine("\nexport const ", enumName, " = ", "S.literal("); this.indent(() => this.forEachEnumCase(e, "none", (_, jsonName) => { - this.emitLine("\"", stringEscape(jsonName), "\","); - }), + this.emitLine('"', stringEscape(jsonName), '",'); + }) ); this.emitLine(");"); if (!this._options.justSchema) { @@ -181,7 +181,7 @@ export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { } } - protected walkObjectNames (type: ObjectType) { + protected walkObjectNames(type: ObjectType) { const names: Name[] = []; const recurse = (type: Type) => { @@ -208,7 +208,7 @@ export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { return names; } - protected emitSchemas (): void { + protected emitSchemas(): void { this.ensureBlankLine(); this.forEachEnum("leading-and-interposing", (u: EnumType, enumName: Name) => { @@ -253,7 +253,7 @@ export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { order.forEach(i => this.emitGatheredSource(this.gatherSource(() => this.emitObject(mapKey[i], mapValue[i])))); } - protected emitSourceStructure (): void { + protected emitSourceStructure(): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } diff --git a/packages/quicktype-core/src/language/TypeScriptFlow.ts b/packages/quicktype-core/src/language/TypeScriptFlow.ts index f3dcb0765..e7a12f58c 100644 --- a/packages/quicktype-core/src/language/TypeScriptFlow.ts +++ b/packages/quicktype-core/src/language/TypeScriptFlow.ts @@ -1,22 +1,16 @@ -import { type Type, type ClassType} from "../Type"; +import { type Type, type ClassType } from "../Type"; import { ArrayType, UnionType, EnumType } from "../Type"; import { matchType, nullableFromUnion, isNamedType } from "../TypeUtils"; import { utf16StringEscape, camelCase } from "../support/Strings"; -import { type Sourcelike, type MultiWord} from "../Source"; +import { type Sourcelike, type MultiWord } from "../Source"; import { modifySource, singleWord, parenIfNeeded, multiWord } from "../Source"; -import { type Name, type Namer} from "../Naming"; +import { type Name, type Namer } from "../Naming"; import { funPrefixNamer } from "../Naming"; -import { type Option, type OptionValues} from "../RendererOptions"; +import { type Option, type OptionValues } from "../RendererOptions"; import { BooleanOption, getOptionValues } from "../RendererOptions"; -import { - type JavaScriptTypeAnnotations} from "./JavaScript"; -import { - javaScriptOptions, - JavaScriptTargetLanguage, - JavaScriptRenderer, - legalizeName, -} from "./JavaScript"; +import { type JavaScriptTypeAnnotations } from "./JavaScript"; +import { javaScriptOptions, JavaScriptTargetLanguage, JavaScriptRenderer, legalizeName } from "./JavaScript"; import { defined, panic } from "../support/Support"; import { type TargetLanguage } from "../TargetLanguage"; import { type RenderContext } from "../Renderer"; @@ -31,9 +25,9 @@ export const tsFlowOptions = Object.assign({}, javaScriptOptions, { preferConstValues: new BooleanOption( "prefer-const-values", "Use string instead of enum for string enums with single value", - false, + false ), - readonly: new BooleanOption("readonly", "Use readonly type members", false), + readonly: new BooleanOption("readonly", "Use readonly type members", false) }); const tsFlowTypeAnnotations = { @@ -42,11 +36,11 @@ const tsFlowTypeAnnotations = { anyMap: ": { [k: string]: any }", string: ": string", stringArray: ": string[]", - boolean: ": boolean", + boolean: ": boolean" }; export abstract class TypeScriptFlowBaseTargetLanguage extends JavaScriptTargetLanguage { - protected getOptions (): Array> { + protected getOptions(): Array> { return [ tsFlowOptions.justTypes, tsFlowOptions.nicePropertyNames, @@ -59,34 +53,34 @@ export abstract class TypeScriptFlowBaseTargetLanguage extends JavaScriptTargetL tsFlowOptions.preferUnions, tsFlowOptions.preferTypes, tsFlowOptions.preferConstValues, - tsFlowOptions.readonly, + tsFlowOptions.readonly ]; } - get supportsOptionalClassProperties (): boolean { + public get supportsOptionalClassProperties(): boolean { return true; } - protected abstract makeRenderer ( + protected abstract makeRenderer( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any, } + untypedOptionValues: { [name: string]: any } ): JavaScriptRenderer; } export class TypeScriptTargetLanguage extends TypeScriptFlowBaseTargetLanguage { - constructor () { + public constructor() { super("TypeScript", ["typescript", "ts", "tsx"], "ts"); } - protected makeRenderer ( + protected makeRenderer( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any, }, + untypedOptionValues: { [name: string]: any } ): TypeScriptRenderer { return new TypeScriptRenderer(this, renderContext, getOptionValues(tsFlowOptions, untypedOptionValues)); } } -function quotePropertyName (original: string): string { +function quotePropertyName(original: string): string { const escaped = utf16StringEscape(original); const quoted = `"${escaped}"`; @@ -104,15 +98,15 @@ function quotePropertyName (original: string): string { } export abstract class TypeScriptFlowBaseRenderer extends JavaScriptRenderer { - constructor ( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - protected readonly _tsFlowOptions: OptionValues, + protected readonly _tsFlowOptions: OptionValues ) { super(targetLanguage, renderContext, _tsFlowOptions); } - protected namerForObjectProperty (): Namer { + protected namerForObjectProperty(): Namer { if (this._tsFlowOptions.nicePropertyNames) { return funPrefixNamer("properties", s => this.nameStyle(s, false)); } else { @@ -120,7 +114,7 @@ export abstract class TypeScriptFlowBaseRenderer extends JavaScriptRenderer { } } - protected sourceFor (t: Type): MultiWord { + protected sourceFor(t: Type): MultiWord { if (this._tsFlowOptions.preferConstValues && t.kind === "enum" && t instanceof EnumType && t.cases.size === 1) { const item = t.cases.values().next().value; return singleWord(`"${utf16StringEscape(item)}"`); @@ -141,7 +135,7 @@ export abstract class TypeScriptFlowBaseRenderer extends JavaScriptRenderer { arrayType => { const itemType = this.sourceFor(arrayType.items); if ( - arrayType.items instanceof UnionType && !this._tsFlowOptions.declareUnions || + (arrayType.items instanceof UnionType && !this._tsFlowOptions.declareUnions) || arrayType.items instanceof ArrayType ) { return singleWord(["Array<", itemType.source, ">"]); @@ -166,15 +160,15 @@ export abstract class TypeScriptFlowBaseRenderer extends JavaScriptRenderer { } return singleWord("string"); - }, + } ); } - protected abstract emitEnum (e: EnumType, enumName: Name): void; + protected abstract emitEnum(e: EnumType, enumName: Name): void; - protected abstract emitClassBlock (c: ClassType, className: Name): void; + protected abstract emitClassBlock(c: ClassType, className: Name): void; - protected emitClassBlockBody (c: ClassType): void { + protected emitClassBlockBody(c: ClassType): void { this.emitPropertyTable(c, (name, _jsonName, p) => { const t = p.type; @@ -187,7 +181,7 @@ export abstract class TypeScriptFlowBaseRenderer extends JavaScriptRenderer { return [ [propertyName, p.isOptional ? "?" : "", ": "], - [this.sourceFor(t).source, ";"], + [this.sourceFor(t).source, ";"] ]; }); @@ -197,12 +191,12 @@ export abstract class TypeScriptFlowBaseRenderer extends JavaScriptRenderer { } } - private emitClass (c: ClassType, className: Name) { + private emitClass(c: ClassType, className: Name) { this.emitDescription(this.descriptionForType(c)); this.emitClassBlock(c, className); } - emitUnion (u: UnionType, unionName: Name) { + protected emitUnion(u: UnionType, unionName: Name) { if (!this._tsFlowOptions.declareUnions) { return; } @@ -213,54 +207,54 @@ export abstract class TypeScriptFlowBaseRenderer extends JavaScriptRenderer { this.emitLine("export type ", unionName, " = ", children.source, ";"); } - protected emitTypes (): void { + protected emitTypes(): void { this.forEachNamedType( "leading-and-interposing", (c: ClassType, n: Name) => this.emitClass(c, n), (e, n) => this.emitEnum(e, n), - (u, n) => this.emitUnion(u, n), + (u, n) => this.emitUnion(u, n) ); } - protected emitUsageComments (): void { + protected emitUsageComments(): void { if (this._tsFlowOptions.justTypes) return; super.emitUsageComments(); } - protected deserializerFunctionLine (t: Type, name: Name): Sourcelike { + protected deserializerFunctionLine(t: Type, name: Name): Sourcelike { const jsonType = this._tsFlowOptions.rawType === "json" ? "string" : "any"; return ["function to", name, "(json: ", jsonType, "): ", this.sourceFor(t).source]; } - protected serializerFunctionLine (t: Type, name: Name): Sourcelike { + protected serializerFunctionLine(t: Type, name: Name): Sourcelike { const camelCaseName = modifySource(camelCase, name); const returnType = this._tsFlowOptions.rawType === "json" ? "string" : "any"; return ["function ", camelCaseName, "ToJson(value: ", this.sourceFor(t).source, "): ", returnType]; } - protected get moduleLine (): string | undefined { + protected get moduleLine(): string | undefined { return undefined; } - protected get castFunctionLines (): [string, string] { + protected get castFunctionLines(): [string, string] { return ["function cast(val: any, typ: any): T", "function uncast(val: T, typ: any): any"]; } - protected get typeAnnotations (): JavaScriptTypeAnnotations { + protected get typeAnnotations(): JavaScriptTypeAnnotations { throw new Error("not implemented"); } - protected emitConvertModule (): void { + protected emitConvertModule(): void { if (this._tsFlowOptions.justTypes) return; super.emitConvertModule(); } - protected emitConvertModuleHelpers (): void { + protected emitConvertModuleHelpers(): void { if (this._tsFlowOptions.justTypes) return; super.emitConvertModuleHelpers(); } - protected emitModuleExports (): void { + protected emitModuleExports(): void { if (this._tsFlowOptions.justTypes) { return; } else { @@ -270,46 +264,46 @@ export abstract class TypeScriptFlowBaseRenderer extends JavaScriptRenderer { } export class TypeScriptRenderer extends TypeScriptFlowBaseRenderer { - protected forbiddenNamesForGlobalNamespace (): string[] { + protected forbiddenNamesForGlobalNamespace(): string[] { return ["Array", "Date"]; } - protected deserializerFunctionLine (t: Type, name: Name): Sourcelike { + protected deserializerFunctionLine(t: Type, name: Name): Sourcelike { const jsonType = this._tsFlowOptions.rawType === "json" ? "string" : "any"; return ["public static to", name, "(json: ", jsonType, "): ", this.sourceFor(t).source]; } - protected serializerFunctionLine (t: Type, name: Name): Sourcelike { + protected serializerFunctionLine(t: Type, name: Name): Sourcelike { const camelCaseName = modifySource(camelCase, name); const returnType = this._tsFlowOptions.rawType === "json" ? "string" : "any"; return ["public static ", camelCaseName, "ToJson(value: ", this.sourceFor(t).source, "): ", returnType]; } - protected get moduleLine (): string | undefined { + protected get moduleLine(): string | undefined { return "export class Convert"; } - protected get typeAnnotations (): JavaScriptTypeAnnotations { + protected get typeAnnotations(): JavaScriptTypeAnnotations { return Object.assign({ never: ": never" }, tsFlowTypeAnnotations); } - protected emitModuleExports (): void { + protected emitModuleExports(): void { return; } - protected emitUsageImportComment (): void { + protected emitUsageImportComment(): void { const topLevelNames: Sourcelike[] = []; this.forEachTopLevel( "none", (_t, name) => { topLevelNames.push(", ", name); }, - isNamedType, + isNamedType ); - this.emitLine("// import { Convert", topLevelNames, " } from \"./file\";"); + this.emitLine("// import { Convert", topLevelNames, ' } from "./file";'); } - protected emitEnum (e: EnumType, enumName: Name): void { + protected emitEnum(e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); // enums with only one value are emitted as constants @@ -335,7 +329,7 @@ export class TypeScriptRenderer extends TypeScriptFlowBaseRenderer { } } - protected emitClassBlock (c: ClassType, className: Name): void { + protected emitClassBlock(c: ClassType, className: Name): void { this.emitBlock( this._tsFlowOptions.preferTypes ? ["export type ", className, " = "] @@ -343,36 +337,36 @@ export class TypeScriptRenderer extends TypeScriptFlowBaseRenderer { "", () => { this.emitClassBlockBody(c); - }, + } ); } } export class FlowTargetLanguage extends TypeScriptFlowBaseTargetLanguage { - constructor () { + public constructor() { super("Flow", ["flow"], "js"); } - protected makeRenderer (renderContext: RenderContext, untypedOptionValues: { [name: string]: any, }): FlowRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): FlowRenderer { return new FlowRenderer(this, renderContext, getOptionValues(tsFlowOptions, untypedOptionValues)); } } export class FlowRenderer extends TypeScriptFlowBaseRenderer { - protected forbiddenNamesForGlobalNamespace (): string[] { + protected forbiddenNamesForGlobalNamespace(): string[] { return ["Class", "Date", "Object", "String", "Array", "JSON", "Error"]; } - protected get typeAnnotations (): JavaScriptTypeAnnotations { + protected get typeAnnotations(): JavaScriptTypeAnnotations { return Object.assign({ never: "" }, tsFlowTypeAnnotations); } - protected emitEnum (e: EnumType, enumName: Name): void { + protected emitEnum(e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); const lines: string[][] = []; this.forEachEnumCase(e, "none", (_, jsonName) => { const maybeOr = lines.length === 0 ? " " : "| "; - lines.push([maybeOr, "\"", utf16StringEscape(jsonName), "\""]); + lines.push([maybeOr, '"', utf16StringEscape(jsonName), '"']); }); defined(lines[lines.length - 1]).push(";"); @@ -384,13 +378,13 @@ export class FlowRenderer extends TypeScriptFlowBaseRenderer { }); } - protected emitClassBlock (c: ClassType, className: Name): void { + protected emitClassBlock(c: ClassType, className: Name): void { this.emitBlock(["export type ", className, " = "], ";", () => { this.emitClassBlockBody(c); }); } - protected emitSourceStructure () { + protected emitSourceStructure() { this.emitLine("// @flow"); this.ensureBlankLine(); super.emitSourceStructure(); diff --git a/packages/quicktype-core/src/language/TypeScriptZod.ts b/packages/quicktype-core/src/language/TypeScriptZod.ts index 75b9e7f96..abc84f71e 100644 --- a/packages/quicktype-core/src/language/TypeScriptZod.ts +++ b/packages/quicktype-core/src/language/TypeScriptZod.ts @@ -1,10 +1,10 @@ import { type StringTypeMapping } from "TypeBuilder"; import { arrayIntercalate } from "collection-utils"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Name, type Namer} from "../Naming"; +import { type Name, type Namer } from "../Naming"; import { funPrefixNamer } from "../Naming"; import { type RenderContext } from "../Renderer"; -import { type Option, type OptionValues} from "../RendererOptions"; +import { type Option, type OptionValues } from "../RendererOptions"; import { BooleanOption, getOptionValues } from "../RendererOptions"; import { type Sourcelike } from "../Source"; import { TargetLanguage } from "../TargetLanguage"; @@ -13,14 +13,9 @@ import { type EnumType, type PrimitiveStringTypeKind, type TransformedStringTypeKind, - type Type, -} from "../Type"; -import { - ArrayType, - ClassType, - ObjectType, - SetOperationType, + type Type } from "../Type"; +import { ArrayType, ClassType, ObjectType, SetOperationType } from "../Type"; import { matchType } from "../TypeUtils"; import { AcronymStyleOptions, acronymStyle } from "../support/Acronyms"; import { @@ -31,65 +26,65 @@ import { isLetterOrUnderscore, splitIntoWords, stringEscape, - utf16StringEscape, + utf16StringEscape } from "../support/Strings"; import { panic } from "../support/Support"; import { legalizeName } from "./JavaScript"; export const typeScriptZodOptions = { - justSchema: new BooleanOption("just-schema", "Schema only", false), + justSchema: new BooleanOption("just-schema", "Schema only", false) }; export class TypeScriptZodTargetLanguage extends TargetLanguage { - protected getOptions (): Array> { + protected getOptions(): Array> { return []; } - constructor ( + public constructor( displayName: string = "TypeScript Zod", names: string[] = ["typescript-zod"], - extension: string = "ts", + extension: string = "ts" ) { super(displayName, names, extension); } - get stringTypeMapping (): StringTypeMapping { + public get stringTypeMapping(): StringTypeMapping { const mapping: Map = new Map(); const dateTimeType = "date-time"; mapping.set("date-time", dateTimeType); return mapping; } - get supportsOptionalClassProperties (): boolean { + public get supportsOptionalClassProperties(): boolean { return true; } - protected makeRenderer ( + protected makeRenderer( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any, }, + untypedOptionValues: { [name: string]: any } ): TypeScriptZodRenderer { return new TypeScriptZodRenderer( this, renderContext, - getOptionValues(typeScriptZodOptions, untypedOptionValues), + getOptionValues(typeScriptZodOptions, untypedOptionValues) ); } } export class TypeScriptZodRenderer extends ConvenienceRenderer { - constructor ( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - protected readonly _options: OptionValues, + protected readonly _options: OptionValues ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace (): string[] { + protected forbiddenNamesForGlobalNamespace(): string[] { return ["Class", "Date", "Object", "String", "Array", "JSON", "Error"]; } - protected nameStyle (original: string, upper: boolean): string { + protected nameStyle(original: string, upper: boolean): string { const acronyms = acronymStyle(AcronymStyleOptions.Camel); const words = splitIntoWords(original); return combineWords( @@ -100,41 +95,41 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { upper ? s => capitalize(acronyms(s)) : allLowerWordStyle, acronyms, "", - isLetterOrUnderscore, + isLetterOrUnderscore ); } - protected makeNamedTypeNamer (): Namer { + protected makeNamedTypeNamer(): Namer { return funPrefixNamer("types", s => this.nameStyle(s, true)); } - protected makeUnionMemberNamer (): Namer { + protected makeUnionMemberNamer(): Namer { return funPrefixNamer("properties", s => this.nameStyle(s, true)); } - protected namerForObjectProperty (): Namer { + protected namerForObjectProperty(): Namer { return funPrefixNamer("properties", s => this.nameStyle(s, true)); } - protected makeEnumCaseNamer (): Namer { + protected makeEnumCaseNamer(): Namer { return funPrefixNamer("enum-cases", s => this.nameStyle(s, false)); } - protected importStatement (lhs: Sourcelike, moduleName: Sourcelike): Sourcelike { + protected importStatement(lhs: Sourcelike, moduleName: Sourcelike): Sourcelike { return ["import ", lhs, " from ", moduleName, ";"]; } - protected emitImports (): void { + protected emitImports(): void { this.ensureBlankLine(); - this.emitLine(this.importStatement("* as z", "\"zod\"")); + this.emitLine(this.importStatement("* as z", '"zod"')); } - protected typeMapTypeForProperty (p: ClassProperty): Sourcelike { + protected typeMapTypeForProperty(p: ClassProperty): Sourcelike { const typeMap = this.typeMapTypeFor(p.type); return p.isOptional ? [typeMap, ".optional()"] : typeMap; } - protected typeMapTypeFor (t: Type, required: boolean = true): Sourcelike { + protected typeMapTypeFor(t: Type, required: boolean = true): Sourcelike { if (["class", "object", "enum"].includes(t.kind)) { return [this.nameForNamedType(t), "Schema"]; } @@ -153,7 +148,7 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { _enumType => panic("Should already be handled."), unionType => { const children = Array.from(unionType.getChildren()).map((type: Type) => - this.typeMapTypeFor(type, false), + this.typeMapTypeFor(type, false) ); return ["z.union([", ...arrayIntercalate(", ", children), "])"]; }, @@ -163,7 +158,7 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { } return "z.string()"; - }, + } ); if (required) { @@ -173,7 +168,7 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { return match; } - protected emitObject (name: Name, t: ObjectType) { + protected emitObject(name: Name, t: ObjectType) { this.ensureBlankLine(); this.emitLine("\nexport const ", name, "Schema = ", "z.object({"); this.indent(() => { @@ -187,14 +182,14 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { } } - protected emitEnum (e: EnumType, enumName: Name): void { + protected emitEnum(e: EnumType, enumName: Name): void { this.ensureBlankLine(); this.emitDescription(this.descriptionForType(e)); this.emitLine("\nexport const ", enumName, "Schema = ", "z.enum(["); this.indent(() => this.forEachEnumCase(e, "none", (_, jsonName) => { - this.emitLine("\"", stringEscape(jsonName), "\","); - }), + this.emitLine('"', stringEscape(jsonName), '",'); + }) ); this.emitLine("]);"); if (!this._options.justSchema) { @@ -209,7 +204,7 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { * Primitive types don't need defining and enums are output before other types, hence, * these are ignored. */ - static extractUnderlyingTyperefs (type: Type): number[] { + private static extractUnderlyingTyperefs(type: Type): number[] { let typeRefs: number[] = []; // Ignore enums and primitives if (!type.isPrimitive() && type.kind != "enum") { @@ -249,7 +244,7 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { return typeRefs; } - protected emitSchemas (): void { + protected emitSchemas(): void { this.ensureBlankLine(); this.forEachEnum("leading-and-interposing", (u: EnumType, enumName: Name) => { @@ -315,7 +310,7 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { foundAllChildren = foundAllChildren && found; } else { console.error( - "A child type reference was not found amongst all Object definitions! TypeRef: " + childRef, + "A child type reference was not found amongst all Object definitions! TypeRef: " + childRef ); } }); @@ -335,7 +330,9 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { if (passNum > MAX_PASSES) { // giving up order.push(...deferredIndices); - console.warn("Exceeded maximum number of passes when determining output order, output may contain forward references"); + console.warn( + "Exceeded maximum number of passes when determining output order, output may contain forward references" + ); } } while (indices.length > 0 && passNum <= MAX_PASSES); @@ -343,7 +340,7 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { order.forEach(i => this.emitGatheredSource(this.gatherSource(() => this.emitObject(mapName[i], mapType[i])))); } - protected emitSourceStructure (): void { + protected emitSourceStructure(): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } diff --git a/packages/quicktype-core/src/language/ruby/index.ts b/packages/quicktype-core/src/language/ruby/index.ts index 42868baa7..1776a3964 100644 --- a/packages/quicktype-core/src/language/ruby/index.ts +++ b/packages/quicktype-core/src/language/ruby/index.ts @@ -1,13 +1,13 @@ import unicode from "unicode-properties"; -import { type Sourcelike} from "../../Source"; +import { type Sourcelike } from "../../Source"; import { modifySource } from "../../Source"; import { type Name } from "../../Naming"; import { Namer } from "../../Naming"; import { type ForbiddenWordsInfo } from "../../ConvenienceRenderer"; import { ConvenienceRenderer } from "../../ConvenienceRenderer"; import { TargetLanguage } from "../../TargetLanguage"; -import { type Option, type OptionValues} from "../../RendererOptions"; +import { type Option, type OptionValues } from "../../RendererOptions"; import { BooleanOption, EnumOption, getOptionValues, StringOption } from "../../RendererOptions"; import * as keywords from "./keywords"; @@ -30,11 +30,11 @@ import { escapeNonPrintableMapper, intToHex, snakeCase, - isLetterOrUnderscore, + isLetterOrUnderscore } from "../../support/Strings"; import { type RenderContext } from "../../Renderer"; -function unicodeEscape (codePoint: number): string { +function unicodeEscape(codePoint: number): string { return "\\u{" + intToHex(codePoint, 0) + "}"; } @@ -51,43 +51,43 @@ export const rubyOptions = { strictness: new EnumOption("strictness", "Type strictness", [ ["strict", Strictness.Strict], ["coercible", Strictness.Coercible], - ["none", Strictness.None], + ["none", Strictness.None] ]), - namespace: new StringOption("namespace", "Specify a wrapping Namespace", "NAME", "", "secondary"), + namespace: new StringOption("namespace", "Specify a wrapping Namespace", "NAME", "", "secondary") }; export class RubyTargetLanguage extends TargetLanguage { - constructor () { + public constructor() { super("Ruby", ["ruby"], "rb"); } - protected getOptions (): Array> { + protected getOptions(): Array> { return [rubyOptions.justTypes, rubyOptions.strictness, rubyOptions.namespace]; } - get supportsOptionalClassProperties (): boolean { + public get supportsOptionalClassProperties(): boolean { return true; } - protected get defaultIndentation (): string { + protected get defaultIndentation(): string { return " "; } - protected makeRenderer (renderContext: RenderContext, untypedOptionValues: { [name: string]: any, }): RubyRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): RubyRenderer { return new RubyRenderer(this, renderContext, getOptionValues(rubyOptions, untypedOptionValues)); } } const isStartCharacter = isLetterOrUnderscore; -function isPartCharacter (utf16Unit: number): boolean { +function isPartCharacter(utf16Unit: number): boolean { const category: string = unicode.getCategory(utf16Unit); return ["Nd", "Pc", "Mn", "Mc"].includes(category) || isStartCharacter(utf16Unit); } const legalizeName = legalizeCharacters(isPartCharacter); -function simpleNameStyle (original: string, uppercase: boolean): string { +function simpleNameStyle(original: string, uppercase: boolean): string { if (/^[0-9]+$/.test(original)) { original = original + "N"; } @@ -101,11 +101,11 @@ function simpleNameStyle (original: string, uppercase: boolean): string { allUpperWordStyle, allUpperWordStyle, "", - isStartCharacter, + isStartCharacter ); } -function memberNameStyle (original: string): string { +function memberNameStyle(original: string): string { const words = splitIntoWords(original); return combineWords( words, @@ -115,56 +115,56 @@ function memberNameStyle (original: string): string { allLowerWordStyle, allLowerWordStyle, "_", - isStartCharacter, + isStartCharacter ); } export class RubyRenderer extends ConvenienceRenderer { - constructor ( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues, + private readonly _options: OptionValues ) { super(targetLanguage, renderContext); } - protected get commentLineStart (): string { + protected get commentLineStart(): string { return "# "; } - protected get needsTypeDeclarationBeforeUse (): boolean { + protected get needsTypeDeclarationBeforeUse(): boolean { return true; } - protected canBeForwardDeclared (t: Type): boolean { + protected canBeForwardDeclared(t: Type): boolean { return "class" === t.kind; } - protected forbiddenNamesForGlobalNamespace (): string[] { + protected forbiddenNamesForGlobalNamespace(): string[] { return keywords.globals.concat(["Types", "JSON", "Dry", "Constructor", "Self"]); } - protected forbiddenForObjectProperties (_c: ClassType, _classNamed: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties(_c: ClassType, _classNamed: Name): ForbiddenWordsInfo { return { names: forbiddenForObjectProperties, includeGlobalForbidden: true }; } - protected makeNamedTypeNamer (): Namer { + protected makeNamedTypeNamer(): Namer { return new Namer("types", n => simpleNameStyle(n, true), []); } - protected namerForObjectProperty (): Namer { + protected namerForObjectProperty(): Namer { return new Namer("properties", memberNameStyle, []); } - protected makeUnionMemberNamer (): Namer { + protected makeUnionMemberNamer(): Namer { return new Namer("properties", memberNameStyle, []); } - protected makeEnumCaseNamer (): Namer { + protected makeEnumCaseNamer(): Namer { return new Namer("enum-cases", n => simpleNameStyle(n, true), []); } - private dryType (t: Type, isOptional = false): Sourcelike { + private dryType(t: Type, isOptional = false): Sourcelike { const optional = isOptional ? ".optional" : ""; return matchType( t, @@ -185,11 +185,11 @@ export class RubyRenderer extends ConvenienceRenderer { } return ["Types.Instance(", this.nameForNamedType(unionType), ")", optional]; - }, + } ); } - private exampleUse (t: Type, exp: Sourcelike, depth = 6, optional = false): Sourcelike { + private exampleUse(t: Type, exp: Sourcelike, depth = 6, optional = false): Sourcelike { if (depth-- <= 0) { return exp; } @@ -206,7 +206,7 @@ export class RubyRenderer extends ConvenienceRenderer { _stringType => exp, arrayType => this.exampleUse(arrayType.items, [exp, safeNav, ".first"], depth), classType => { - let info: { name: Name, prop: ClassProperty, } | undefined; + let info: { name: Name; prop: ClassProperty } | undefined; this.forEachClassProperty(classType, "none", (name, _json, prop) => { if (["class", "map", "array"].includes(prop.type.kind)) { info = { name, prop }; @@ -220,7 +220,7 @@ export class RubyRenderer extends ConvenienceRenderer { return exp; }, - mapType => this.exampleUse(mapType.values, [exp, safeNav, "[\"…\"]"], depth), + mapType => this.exampleUse(mapType.values, [exp, safeNav, '["…"]'], depth), enumType => { let name: Name | undefined; // FIXME: This is a terrible way to get the first enum case name. @@ -246,12 +246,12 @@ export class RubyRenderer extends ConvenienceRenderer { } return exp; - }, + } ); } - private jsonSample (t: Type): Sourcelike { - function inner () { + private jsonSample(t: Type): Sourcelike { + function inner() { if (t instanceof ArrayType) { return "[…]"; } else if (t instanceof MapType) { @@ -266,7 +266,7 @@ export class RubyRenderer extends ConvenienceRenderer { return `"${inner()}"`; } - private fromDynamic (t: Type, e: Sourcelike, optional = false, castPrimitives = false): Sourcelike { + private fromDynamic(t: Type, e: Sourcelike, optional = false, castPrimitives = false): Sourcelike { const primitiveCast = [this.dryType(t, optional), "[", e, "]"]; const primitive = castPrimitives ? primitiveCast : e; const safeAccess = optional ? "&" : ""; @@ -290,7 +290,7 @@ export class RubyRenderer extends ConvenienceRenderer { this.fromDynamic(mapType.values, "v", false, true), "] }", safeAccess, - ".to_h", + ".to_h" ], enumType => { const expression = ["Types::", this.nameForNamedType(enumType), "[", e, "]"]; @@ -304,11 +304,11 @@ export class RubyRenderer extends ConvenienceRenderer { const expression = [this.nameForNamedType(unionType), ".from_dynamic!(", e, ")"]; return optional ? [e, " ? ", expression, " : nil"] : expression; - }, + } ); } - private toDynamic (t: Type, e: Sourcelike, optional = false): Sourcelike { + private toDynamic(t: Type, e: Sourcelike, optional = false): Sourcelike { if (this.marshalsImplicitlyToDynamic(t)) { return e; } @@ -336,11 +336,11 @@ export class RubyRenderer extends ConvenienceRenderer { } return [e, optional ? "&" : "", ".to_dynamic"]; - }, + } ); } - private marshalsImplicitlyToDynamic (t: Type): boolean { + private marshalsImplicitlyToDynamic(t: Type): boolean { return matchType( t, _anyType => true, @@ -360,14 +360,14 @@ export class RubyRenderer extends ConvenienceRenderer { } return false; - }, + } ); } // This is only to be used to allow class properties to possibly // marshal implicitly. They are allowed to do this because they will // be checked in Dry::Struct.new - private propertyTypeMarshalsImplicitlyFromDynamic (t: Type): boolean { + private propertyTypeMarshalsImplicitlyFromDynamic(t: Type): boolean { return matchType( t, _anyType => true, @@ -388,17 +388,17 @@ export class RubyRenderer extends ConvenienceRenderer { } return false; - }, + } ); } - private emitBlock (source: Sourcelike, emit: () => void) { + private emitBlock(source: Sourcelike, emit: () => void) { this.emitLine(source); this.indent(emit); this.emitLine("end"); } - private emitModule (emit: () => void) { + private emitModule(emit: () => void) { const emitModuleInner = (moduleName: string) => { const [firstModule, ...subModules] = moduleName.split("::"); if (subModules.length > 0) { @@ -417,7 +417,7 @@ export class RubyRenderer extends ConvenienceRenderer { } } - private emitClass (c: ClassType, className: Name) { + private emitClass(c: ClassType, className: Name) { this.emitDescription(this.descriptionForType(c)); this.emitBlock(["class ", className, " < Dry::Struct"], () => { let table: Sourcelike[][] = []; @@ -427,7 +427,7 @@ export class RubyRenderer extends ConvenienceRenderer { const description = this.descriptionForClassProperty(c, jsonName); const attribute = [ ["attribute :", name, ","], - [" ", this.dryType(p.type), p.isOptional ? ".optional" : ""], + [" ", this.dryType(p.type), p.isOptional ? ".optional" : ""] ]; if (description !== undefined) { if (table.length > 0) { @@ -462,20 +462,20 @@ export class RubyRenderer extends ConvenienceRenderer { this.forEachClassProperty(c, "none", (name, jsonName, p) => { const dynamic = p.isOptional ? // If key is not found in hash, this will be nil - `d["${stringEscape(jsonName)}"]` + `d["${stringEscape(jsonName)}"]` : // This will raise a runtime error if the key is not found in the hash - `d.fetch("${stringEscape(jsonName)}")`; + `d.fetch("${stringEscape(jsonName)}")`; if (this.propertyTypeMarshalsImplicitlyFromDynamic(p.type)) { inits.push([ [name, ": "], - [dynamic, ","], + [dynamic, ","] ]); } else { const expression = this.fromDynamic(p.type, dynamic, p.isOptional); inits.push([ [name, ": "], - [expression, ","], + [expression, ","] ]); } }); @@ -509,7 +509,7 @@ export class RubyRenderer extends ConvenienceRenderer { }); } - private emitEnum (e: EnumType, enumName: Name) { + private emitEnum(e: EnumType, enumName: Name) { this.emitDescription(this.descriptionForType(e)); this.emitBlock(["module ", enumName], () => { const table: Sourcelike[][] = []; @@ -520,7 +520,7 @@ export class RubyRenderer extends ConvenienceRenderer { }); } - private emitUnion (u: UnionType, unionName: Name) { + private emitUnion(u: UnionType, unionName: Name) { this.emitDescription(this.descriptionForType(u)); this.emitBlock(["class ", unionName, " < Dry::Struct"], () => { const table: Sourcelike[][] = []; @@ -557,7 +557,7 @@ export class RubyRenderer extends ConvenienceRenderer { this.emitLine("end"); } }); - this.emitLine("raise \"Invalid union\""); + this.emitLine('raise "Invalid union"'); }); this.ensureBlankLine(); @@ -592,7 +592,7 @@ export class RubyRenderer extends ConvenienceRenderer { }); } - private emitTypesModule () { + private emitTypesModule() { this.emitBlock(["module Types"], () => { this.emitLine("include Dry.Types(default: :nominal)"); @@ -607,7 +607,7 @@ export class RubyRenderer extends ConvenienceRenderer { bool: has.bool || t.kind === "bool", hash: has.hash || t.kind === "map" || t.kind === "class", string: has.string || t.kind === "string" || t.kind === "enum", - double: has.double || t.kind === "double", + double: has.double || t.kind === "double" }; }); if (has.int) declarations.push([["Integer"], [` = ${this._options.strictness}Integer`]]); @@ -621,7 +621,7 @@ export class RubyRenderer extends ConvenienceRenderer { if (has.double) declarations.push([ ["Double"], - [` = ${this._options.strictness}Float | ${this._options.strictness}Integer`], + [` = ${this._options.strictness}Float | ${this._options.strictness}Integer`] ]); } @@ -640,7 +640,7 @@ export class RubyRenderer extends ConvenienceRenderer { }); } - protected emitSourceStructure () { + protected emitSourceStructure() { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } else if (!this._options.justTypes) { @@ -682,7 +682,7 @@ export class RubyRenderer extends ConvenienceRenderer { "leading-and-interposing", (c: ClassType, n: Name) => this.emitClass(c, n), (e, n) => this.emitEnum(e, n), - (u, n) => this.emitUnion(u, n), + (u, n) => this.emitUnion(u, n) ); if (!this._options.justTypes) { @@ -702,7 +702,7 @@ export class RubyRenderer extends ConvenienceRenderer { this.emitLine( self, " = ", - this.fromDynamic(topLevel, "JSON.parse(json, quirks_mode: true)"), + this.fromDynamic(topLevel, "JSON.parse(json, quirks_mode: true)") ); this.emitBlock([self, ".define_singleton_method(:to_json) do"], () => { this.emitLine("JSON.generate(", this.toDynamic(topLevel, "self"), ")"); @@ -710,7 +710,7 @@ export class RubyRenderer extends ConvenienceRenderer { this.emitLine(self); } else { this.emitLine( - this.fromDynamic(topLevel, "JSON.parse(json, quirks_mode: true)"), + this.fromDynamic(topLevel, "JSON.parse(json, quirks_mode: true)") ); } }); @@ -721,7 +721,7 @@ export class RubyRenderer extends ConvenienceRenderer { classDeclaration(); }); }, - t => this.namedTypeToNameForTopLevel(t) === undefined, + t => this.namedTypeToNameForTopLevel(t) === undefined ); } }); diff --git a/packages/quicktype-core/src/rewrites/CombineClasses.ts b/packages/quicktype-core/src/rewrites/CombineClasses.ts index a89826f7c..4dac053fb 100644 --- a/packages/quicktype-core/src/rewrites/CombineClasses.ts +++ b/packages/quicktype-core/src/rewrites/CombineClasses.ts @@ -1,4 +1,4 @@ -import { type Type, type ClassProperty} from "../Type"; +import { type Type, type ClassProperty } from "../Type"; import { ClassType, setOperationCasesEqual } from "../Type"; import { nonNullTypeCases, combineTypeAttributesOfTypes } from "../TypeUtils"; @@ -18,11 +18,11 @@ interface Clique { // FIXME: Allow some type combinations to unify, like different enums, // enums with strings, integers with doubles, maps with objects of // the correct type. -function typeSetsCanBeCombined (s1: Iterable, s2: Iterable): boolean { +function typeSetsCanBeCombined(s1: Iterable, s2: Iterable): boolean { return setOperationCasesEqual(s1, s2, true, (a, b) => a.structurallyCompatible(b, true)); } -function canBeCombined (c1: ClassType, c2: ClassType, onlyWithSameProperties: boolean): boolean { +function canBeCombined(c1: ClassType, c2: ClassType, onlyWithSameProperties: boolean): boolean { const p1 = c1.getProperties(); const p2 = c2.getProperties(); if (onlyWithSameProperties) { @@ -83,7 +83,7 @@ function canBeCombined (c1: ClassType, c2: ClassType, onlyWithSameProperties: bo return true; } -function tryAddToClique (c: ClassType, clique: Clique, onlyWithSameProperties: boolean): boolean { +function tryAddToClique(c: ClassType, clique: Clique, onlyWithSameProperties: boolean): boolean { for (const prototype of clique.prototypes) { if (prototype.structurallyCompatible(c)) { clique.members.push(c); @@ -102,13 +102,13 @@ function tryAddToClique (c: ClassType, clique: Clique, onlyWithSameProperties: b return false; } -function findSimilarityCliques ( +function findSimilarityCliques( graph: TypeGraph, onlyWithSameProperties: boolean, - includeFixedClasses: boolean, + includeFixedClasses: boolean ): ClassType[][] { const classCandidates = Array.from(graph.allNamedTypesSeparated().objects).filter( - o => o instanceof ClassType && (includeFixedClasses || !o.isFixed), + o => o instanceof ClassType && (includeFixedClasses || !o.isFixed) ) as ClassType[]; const cliques: Clique[] = []; @@ -138,22 +138,22 @@ function findSimilarityCliques ( return cliques.map(clique => clique.members).filter(cl => cl.length > 1); } -export function combineClasses ( +export function combineClasses( ctx: RunContext, graph: TypeGraph, alphabetizeProperties: boolean, conflateNumbers: boolean, onlyWithSameProperties: boolean, - debugPrintReconstitution: boolean, + debugPrintReconstitution: boolean ): TypeGraph { const cliques = ctx.time(" find similarity cliques", () => - findSimilarityCliques(graph, onlyWithSameProperties, false), + findSimilarityCliques(graph, onlyWithSameProperties, false) ); - function makeCliqueClass ( + function makeCliqueClass( clique: ReadonlySet, builder: GraphRewriteBuilder, - forwardingRef: TypeRef, + forwardingRef: TypeRef ): TypeRef { assert(clique.size > 0, "Clique can't be empty"); const attributes = combineTypeAttributesOfTypes("union", clique); @@ -163,7 +163,7 @@ export function combineClasses ( builder, unionBuilderForUnification(builder, false, false, conflateNumbers), conflateNumbers, - forwardingRef, + forwardingRef ); } @@ -173,6 +173,6 @@ export function combineClasses ( alphabetizeProperties, cliques, debugPrintReconstitution, - makeCliqueClass, + makeCliqueClass ); } diff --git a/packages/quicktype-core/src/rewrites/ExpandStrings.ts b/packages/quicktype-core/src/rewrites/ExpandStrings.ts index 7f2bff226..0482f0032 100644 --- a/packages/quicktype-core/src/rewrites/ExpandStrings.ts +++ b/packages/quicktype-core/src/rewrites/ExpandStrings.ts @@ -6,7 +6,7 @@ import { setUnion, setIntersect, setIsSuperset, - areEqual, + areEqual } from "collection-utils"; import { type PrimitiveType } from "../Type"; @@ -30,31 +30,31 @@ interface EnumInfo { numValues: number; } -function isOwnEnum ({ numValues, cases }: EnumInfo): boolean { +function isOwnEnum({ numValues, cases }: EnumInfo): boolean { return numValues >= MIN_LENGTH_FOR_ENUM && cases.size < Math.sqrt(numValues); } -function enumCasesOverlap ( +function enumCasesOverlap( newCases: ReadonlySet, existingCases: ReadonlySet, - newAreSubordinate: boolean, + newAreSubordinate: boolean ): boolean { const smaller = newAreSubordinate ? newCases.size : Math.min(newCases.size, existingCases.size); const overlap = setIntersect(newCases, existingCases).size; return overlap >= smaller * REQUIRED_OVERLAP; } -function isAlwaysEmptyString (cases: string[]): boolean { +function isAlwaysEmptyString(cases: string[]): boolean { return cases.length === 1 && cases[0] === ""; } -export function expandStrings (ctx: RunContext, graph: TypeGraph, inference: EnumInference): TypeGraph { +export function expandStrings(ctx: RunContext, graph: TypeGraph, inference: EnumInference): TypeGraph { const stringTypeMapping = ctx.stringTypeMapping; const allStrings = Array.from(graph.allTypesUnordered()).filter( - t => t.kind === "string" && stringTypesForType(t as PrimitiveType).isRestricted, + t => t.kind === "string" && stringTypesForType(t as PrimitiveType).isRestricted ) as PrimitiveType[]; - function makeEnumInfo (t: PrimitiveType): EnumInfo | undefined { + function makeEnumInfo(t: PrimitiveType): EnumInfo | undefined { const stringTypes = stringTypesForType(t); const mappedStringTypes = stringTypes.applyStringTypeMapping(stringTypeMapping); if (!mappedStringTypes.isRestricted) return undefined; @@ -85,7 +85,7 @@ export function expandStrings (ctx: RunContext, graph: TypeGraph, inference: Enu enumInfos.set(t, enumInfo); } - function findOverlap (newCases: ReadonlySet, newAreSubordinate: boolean): number { + function findOverlap(newCases: ReadonlySet, newAreSubordinate: boolean): number { return enumSets.findIndex(s => enumCasesOverlap(newCases, s, newAreSubordinate)); } @@ -139,10 +139,10 @@ export function expandStrings (ctx: RunContext, graph: TypeGraph, inference: Enu } } - function replaceString ( + function replaceString( group: ReadonlySet, builder: GraphRewriteBuilder, - forwardingRef: TypeRef, + forwardingRef: TypeRef ): TypeRef { assert(group.size === 1); const t = defined(iterableFirst(group)); @@ -191,6 +191,6 @@ export function expandStrings (ctx: RunContext, graph: TypeGraph, inference: Enu false, allStrings.map(t => [t]), ctx.debugPrintReconstitution, - replaceString, + replaceString ); } diff --git a/packages/quicktype-core/src/rewrites/FlattenStrings.ts b/packages/quicktype-core/src/rewrites/FlattenStrings.ts index 18ce4da1b..fa43717e5 100644 --- a/packages/quicktype-core/src/rewrites/FlattenStrings.ts +++ b/packages/quicktype-core/src/rewrites/FlattenStrings.ts @@ -10,23 +10,23 @@ import { combineTypeAttributes } from "../attributes/TypeAttributes"; // A union needs replacing if it contains more than one string type, one of them being // a basic string type. -function unionNeedsReplacing (u: UnionType): ReadonlySet | undefined { +function unionNeedsReplacing(u: UnionType): ReadonlySet | undefined { const stringMembers = u.stringTypeMembers; if (stringMembers.size <= 1) return undefined; const stringType = u.findMember("string"); if (stringType === undefined) return undefined; assert( !stringTypesForType(stringType as PrimitiveType).isRestricted, - "We must only flatten strings if we have no restriced strings", + "We must only flatten strings if we have no restriced strings" ); return stringMembers; } // Replaces all string types in an enum with the basic string type. -function replaceUnion ( +function replaceUnion( group: ReadonlySet, builder: GraphRewriteBuilder, - forwardingRef: TypeRef, + forwardingRef: TypeRef ): TypeRef { assert(group.size === 1); const u = defined(iterableFirst(group)); @@ -42,7 +42,7 @@ function replaceUnion ( return builder.getStringType( combineTypeAttributes("union", stringAttributes, u.getAttributes()), undefined, - forwardingRef, + forwardingRef ); } @@ -50,10 +50,10 @@ function replaceUnion ( return builder.getUnionType(u.getAttributes(), new Set(types), forwardingRef); } -export function flattenStrings ( +export function flattenStrings( graph: TypeGraph, stringTypeMapping: StringTypeMapping, - debugPrintReconstitution: boolean, + debugPrintReconstitution: boolean ): TypeGraph { const allUnions = graph.allNamedTypesSeparated().unions; const unionsToReplace = Array.from(allUnions) @@ -65,6 +65,6 @@ export function flattenStrings ( false, unionsToReplace, debugPrintReconstitution, - replaceUnion, + replaceUnion ); } diff --git a/packages/quicktype-core/src/rewrites/FlattenUnions.ts b/packages/quicktype-core/src/rewrites/FlattenUnions.ts index b9ef1d41e..a834002e8 100644 --- a/packages/quicktype-core/src/rewrites/FlattenUnions.ts +++ b/packages/quicktype-core/src/rewrites/FlattenUnions.ts @@ -1,8 +1,8 @@ import { setFilter, iterableSome } from "collection-utils"; -import { type TypeGraph, type TypeRef} from "../TypeGraph"; +import { type TypeGraph, type TypeRef } from "../TypeGraph"; import { derefTypeRef } from "../TypeGraph"; -import { type Type} from "../Type"; +import { type Type } from "../Type"; import { UnionType, IntersectionType } from "../Type"; import { makeGroupsToFlatten } from "../TypeUtils"; import { assert } from "../support/Support"; @@ -12,16 +12,16 @@ import { unifyTypes, UnifyUnionBuilder } from "../UnifyClasses"; import { messageAssert } from "../Messages"; import { emptyTypeAttributes } from "../attributes/TypeAttributes"; -export function flattenUnions ( +export function flattenUnions( graph: TypeGraph, stringTypeMapping: StringTypeMapping, conflateNumbers: boolean, makeObjectTypes: boolean, - debugPrintReconstitution: boolean, + debugPrintReconstitution: boolean ): [TypeGraph, boolean] { let needsRepeat = false; - function replace (types: ReadonlySet, builder: GraphRewriteBuilder, forwardingRef: TypeRef): TypeRef { + function replace(types: ReadonlySet, builder: GraphRewriteBuilder, forwardingRef: TypeRef): TypeRef { const unionBuilder = new UnifyUnionBuilder(builder, makeObjectTypes, true, trefs => { assert(trefs.length > 0, "Must have at least one type to build union"); trefs = trefs.map(tref => builder.reconstituteType(derefTypeRef(tref, graph))); diff --git a/packages/quicktype-core/src/rewrites/InferMaps.ts b/packages/quicktype-core/src/rewrites/InferMaps.ts index 0092d1dbf..43e30182c 100644 --- a/packages/quicktype-core/src/rewrites/InferMaps.ts +++ b/packages/quicktype-core/src/rewrites/InferMaps.ts @@ -1,6 +1,6 @@ import { iterableFirst, iterableEvery, setMap } from "collection-utils"; -import { type Type, type ClassProperty} from "../Type"; +import { type Type, type ClassProperty } from "../Type"; import { ClassType, setOperationCasesEqual, isPrimitiveStringTypeKind } from "../Type"; import { removeNullFromType } from "../TypeUtils"; import { defined, panic } from "../support/Support"; @@ -8,7 +8,7 @@ import { type TypeGraph, type TypeRef } from "../TypeGraph"; import { type StringTypeMapping } from "../TypeBuilder"; import { type GraphRewriteBuilder } from "../GraphRewriting"; import { unifyTypes, unionBuilderForUnification } from "../UnifyClasses"; -import { type MarkovChain} from "../MarkovChain"; +import { type MarkovChain } from "../MarkovChain"; import { load, evaluate } from "../MarkovChain"; const mapSizeThreshold = 20; @@ -16,7 +16,7 @@ const stringMapSizeThreshold = 50; let markovChain: MarkovChain | undefined = undefined; -function nameProbability (name: string): number { +function nameProbability(name: string): number { if (markovChain === undefined) { markovChain = load(); } @@ -24,7 +24,7 @@ function nameProbability (name: string): number { return evaluate(markovChain, name); } -function shouldBeMap (properties: ReadonlyMap): ReadonlySet | undefined { +function shouldBeMap(properties: ReadonlyMap): ReadonlySet | undefined { // Only classes with a certain number of properties are inferred // as maps. const numProperties = properties.size; @@ -108,16 +108,16 @@ function shouldBeMap (properties: ReadonlyMap): ReadonlyS return allCases; } -export function inferMaps ( +export function inferMaps( graph: TypeGraph, stringTypeMapping: StringTypeMapping, conflateNumbers: boolean, - debugPrintReconstitution: boolean, + debugPrintReconstitution: boolean ): TypeGraph { - function replaceClass ( + function replaceClass( setOfOneClass: ReadonlySet, builder: GraphRewriteBuilder, - forwardingRef: TypeRef, + forwardingRef: TypeRef ): TypeRef { const c = defined(iterableFirst(setOfOneClass)); const properties = c.getProperties(); @@ -140,9 +140,9 @@ export function inferMaps ( c.getAttributes(), builder, unionBuilderForUnification(builder, false, false, conflateNumbers), - conflateNumbers, + conflateNumbers ), - forwardingRef, + forwardingRef ); } @@ -156,6 +156,6 @@ export function inferMaps ( false, classesToReplace.map(c => [c]), debugPrintReconstitution, - replaceClass, + replaceClass ); } diff --git a/packages/quicktype-core/src/rewrites/ReplaceObjectType.ts b/packages/quicktype-core/src/rewrites/ReplaceObjectType.ts index e225c3c42..99acbc145 100644 --- a/packages/quicktype-core/src/rewrites/ReplaceObjectType.ts +++ b/packages/quicktype-core/src/rewrites/ReplaceObjectType.ts @@ -7,34 +7,34 @@ import { type ObjectType, type ClassProperty } from "../Type"; import { defined } from "../support/Support"; import { emptyTypeAttributes } from "../attributes/TypeAttributes"; -export function replaceObjectType ( +export function replaceObjectType( graph: TypeGraph, stringTypeMapping: StringTypeMapping, _conflateNumbers: boolean, leaveFullObjects: boolean, - debugPrintReconstitution: boolean, + debugPrintReconstitution: boolean ): TypeGraph { - function replace ( + function replace( setOfOneType: ReadonlySet, builder: GraphRewriteBuilder, - forwardingRef: TypeRef, + forwardingRef: TypeRef ): TypeRef { const o = defined(iterableFirst(setOfOneType)); const attributes = o.getAttributes(); const properties = o.getProperties(); const additionalProperties = o.getAdditionalProperties(); - function reconstituteProperties (): ReadonlyMap { + function reconstituteProperties(): ReadonlyMap { return mapMap(properties, cp => - builder.makeClassProperty(builder.reconstituteTypeRef(cp.typeRef), cp.isOptional), + builder.makeClassProperty(builder.reconstituteTypeRef(cp.typeRef), cp.isOptional) ); } - function makeClass (): TypeRef { + function makeClass(): TypeRef { return builder.getUniqueClassType(attributes, true, reconstituteProperties(), forwardingRef); } - function reconstituteAdditionalProperties (): TypeRef { + function reconstituteAdditionalProperties(): TypeRef { return builder.reconstituteType(defined(additionalProperties)); } diff --git a/packages/quicktype-core/src/rewrites/ResolveIntersections.ts b/packages/quicktype-core/src/rewrites/ResolveIntersections.ts index 22f2984cb..a3a3016be 100644 --- a/packages/quicktype-core/src/rewrites/ResolveIntersections.ts +++ b/packages/quicktype-core/src/rewrites/ResolveIntersections.ts @@ -9,7 +9,7 @@ import { setMap, iterableFind, setIntersect, - setUnionInto, + setUnionInto } from "collection-utils"; import { type TypeGraph, type TypeRef } from "../TypeGraph"; @@ -17,10 +17,7 @@ import { type StringTypeMapping, type TypeBuilder } from "../TypeBuilder"; import { type GraphRewriteBuilder, type TypeLookerUp } from "../GraphRewriting"; import { type UnionTypeProvider, type TypeAttributeMap } from "../UnionBuilder"; import { UnionBuilder } from "../UnionBuilder"; -import { - type Type, - type PrimitiveTypeKind, - type TypeKind} from "../Type"; +import { type Type, type PrimitiveTypeKind, type TypeKind } from "../Type"; import { IntersectionType, UnionType, @@ -28,32 +25,28 @@ import { isPrimitiveTypeKind, isNumberTypeKind, GenericClassProperty, - ObjectType, + ObjectType } from "../Type"; import { setOperationMembersRecursively, matchTypeExhaustive, makeGroupsToFlatten } from "../TypeUtils"; import { assert, defined, panic, mustNotHappen } from "../support/Support"; -import { - type TypeAttributes} from "../attributes/TypeAttributes"; -import { - combineTypeAttributes, - emptyTypeAttributes, - makeTypeAttributesInferred, -} from "../attributes/TypeAttributes"; +import { type TypeAttributes } from "../attributes/TypeAttributes"; +import { combineTypeAttributes, emptyTypeAttributes, makeTypeAttributesInferred } from "../attributes/TypeAttributes"; -function canResolve (t: IntersectionType): boolean { +function canResolve(t: IntersectionType): boolean { const members = setOperationMembersRecursively(t, undefined)[0]; if (members.size <= 1) return true; return iterableEvery(members, m => !(m instanceof UnionType) || m.isCanonical); } -function attributesForTypes (types: ReadonlySet): TypeAttributeMap { +function attributesForTypes(types: ReadonlySet): TypeAttributeMap { return mapMapEntries(types.entries(), t => [t.kind, t.getAttributes()] as [T, TypeAttributes]); } type PropertyMap = Map>>; class IntersectionAccumulator -implements UnionTypeProvider, [PropertyMap, ReadonlySet | undefined] | undefined> { + implements UnionTypeProvider, [PropertyMap, ReadonlySet | undefined] | undefined> +{ private _primitiveTypes: Set | undefined; private readonly _primitiveAttributes: TypeAttributeMap = new Map(); @@ -81,7 +74,7 @@ implements UnionTypeProvider, [PropertyMap, ReadonlySet private _lostTypeAttributes = false; - private updatePrimitiveTypes (members: Iterable): void { + private updatePrimitiveTypes(members: Iterable): void { const types = setFilter(members, t => isPrimitiveTypeKind(t.kind)); const attributes = attributesForTypes(types); mapMergeWithInto(this._primitiveAttributes, (a, b) => combineTypeAttributes("intersect", a, b), attributes); @@ -103,7 +96,7 @@ implements UnionTypeProvider, [PropertyMap, ReadonlySet } } - private updateArrayItemTypes (members: Iterable): void { + private updateArrayItemTypes(members: Iterable): void { const maybeArray = iterableFind(members, t => t instanceof ArrayType) as ArrayType | undefined; if (maybeArray === undefined) { this._arrayItemTypes = false; @@ -119,7 +112,7 @@ implements UnionTypeProvider, [PropertyMap, ReadonlySet } } - private updateObjectProperties (members: Iterable): void { + private updateObjectProperties(members: Iterable): void { const maybeObject = iterableFind(members, t => t instanceof ObjectType) as ObjectType | undefined; if (maybeObject === undefined) { this._objectProperties = undefined; @@ -130,7 +123,7 @@ implements UnionTypeProvider, [PropertyMap, ReadonlySet this._objectAttributes = combineTypeAttributes( "intersect", this._objectAttributes, - maybeObject.getAttributes(), + maybeObject.getAttributes() ); const objectAdditionalProperties = maybeObject.getAdditionalProperties(); @@ -141,7 +134,7 @@ implements UnionTypeProvider, [PropertyMap, ReadonlySet const allPropertyNames = setUnionInto( new Set(this._objectProperties.keys()), - maybeObject.getProperties().keys(), + maybeObject.getProperties().keys() ); for (const name of allPropertyNames) { const existing = defined(this._objectProperties).get(name); @@ -150,13 +143,13 @@ implements UnionTypeProvider, [PropertyMap, ReadonlySet if (existing !== undefined && newProperty !== undefined) { const cp = new GenericClassProperty( existing.typeData.add(newProperty.type), - existing.isOptional && newProperty.isOptional, + existing.isOptional && newProperty.isOptional ); defined(this._objectProperties).set(name, cp); } else if (existing !== undefined && objectAdditionalProperties !== undefined) { const cp = new GenericClassProperty( existing.typeData.add(objectAdditionalProperties), - existing.isOptional, + existing.isOptional ); defined(this._objectProperties).set(name, cp); } else if (existing !== undefined) { @@ -180,13 +173,13 @@ implements UnionTypeProvider, [PropertyMap, ReadonlySet } } - private addUnionSet (members: Iterable): void { + private addUnionSet(members: Iterable): void { this.updatePrimitiveTypes(members); this.updateArrayItemTypes(members); this.updateObjectProperties(members); } - addType (t: Type): TypeAttributes { + public addType(t: Type): TypeAttributes { let attributes = t.getAttributes(); matchTypeExhaustive( t, @@ -209,16 +202,16 @@ implements UnionTypeProvider, [PropertyMap, ReadonlySet unionType => { attributes = combineTypeAttributes( "intersect", - [attributes].concat(Array.from(unionType.members).map(m => m.getAttributes())), + [attributes].concat(Array.from(unionType.members).map(m => m.getAttributes())) ); this.addUnionSet(unionType.members); }, - transformedStringType => this.addUnionSet([transformedStringType]), + transformedStringType => this.addUnionSet([transformedStringType]) ); return makeTypeAttributesInferred(attributes); } - get arrayData (): ReadonlySet { + public get arrayData(): ReadonlySet { if (this._arrayItemTypes === undefined || this._arrayItemTypes === false) { return panic("This should not be called if the type can't be an array"); } @@ -226,7 +219,7 @@ implements UnionTypeProvider, [PropertyMap, ReadonlySet return this._arrayItemTypes; } - get objectData (): [PropertyMap, ReadonlySet | undefined] | undefined { + public get objectData(): [PropertyMap, ReadonlySet | undefined] | undefined { if (this._objectProperties === undefined) { assert(this._additionalPropertyTypes === undefined); return undefined; @@ -235,13 +228,13 @@ implements UnionTypeProvider, [PropertyMap, ReadonlySet return [this._objectProperties, this._additionalPropertyTypes]; } - get enumCases (): ReadonlySet { + public get enumCases(): ReadonlySet { return panic("We don't support enums in intersections"); } - getMemberKinds (): TypeAttributeMap { + public getMemberKinds(): TypeAttributeMap { const kinds: TypeAttributeMap = mapMap(defined(this._primitiveTypes).entries(), k => - defined(this._primitiveAttributes.get(k)), + defined(this._primitiveAttributes.get(k)) ); const maybeDoubleAttributes = this._primitiveAttributes.get("double"); // If double was eliminated, add its attributes to integer @@ -267,19 +260,19 @@ implements UnionTypeProvider, [PropertyMap, ReadonlySet return kinds; } - get lostTypeAttributes (): boolean { + public get lostTypeAttributes(): boolean { return this._lostTypeAttributes; } } class IntersectionUnionBuilder extends UnionBuilder< -TypeBuilder & TypeLookerUp, -ReadonlySet, -[PropertyMap, ReadonlySet | undefined] | undefined + TypeBuilder & TypeLookerUp, + ReadonlySet, + [PropertyMap, ReadonlySet | undefined] | undefined > { private _createdNewIntersections = false; - private makeIntersection (members: ReadonlySet, attributes: TypeAttributes): TypeRef { + private makeIntersection(members: ReadonlySet, attributes: TypeAttributes): TypeRef { const reconstitutedMembers = setMap(members, t => this.typeBuilder.reconstituteTypeRef(t.typeRef)); const first = defined(iterableFirst(reconstitutedMembers)); @@ -292,14 +285,14 @@ ReadonlySet, return this.typeBuilder.getUniqueIntersectionType(attributes, reconstitutedMembers); } - get createdNewIntersections (): boolean { + public get createdNewIntersections(): boolean { return this._createdNewIntersections; } - protected makeObject ( + protected makeObject( maybeData: [PropertyMap, ReadonlySet | undefined] | undefined, typeAttributes: TypeAttributes, - forwardingRef: TypeRef | undefined, + forwardingRef: TypeRef | undefined ): TypeRef { if (maybeData === undefined) { return panic("Either properties or additional properties must be given to make an object type"); @@ -307,7 +300,7 @@ ReadonlySet, const [propertyTypes, maybeAdditionalProperties] = maybeData; const properties = mapMap(propertyTypes, cp => - this.typeBuilder.makeClassProperty(this.makeIntersection(cp.typeData, emptyTypeAttributes), cp.isOptional), + this.typeBuilder.makeClassProperty(this.makeIntersection(cp.typeData, emptyTypeAttributes), cp.isOptional) ); const additionalProperties = maybeAdditionalProperties === undefined @@ -316,10 +309,10 @@ ReadonlySet, return this.typeBuilder.getUniqueObjectType(typeAttributes, properties, additionalProperties, forwardingRef); } - protected makeArray ( + protected makeArray( arrays: ReadonlySet, typeAttributes: TypeAttributes, - forwardingRef: TypeRef | undefined, + forwardingRef: TypeRef | undefined ): TypeRef { // FIXME: attributes const itemsType = this.makeIntersection(arrays, emptyTypeAttributes); @@ -328,18 +321,18 @@ ReadonlySet, } } -export function resolveIntersections ( +export function resolveIntersections( graph: TypeGraph, stringTypeMapping: StringTypeMapping, - debugPrintReconstitution: boolean, + debugPrintReconstitution: boolean ): [TypeGraph, boolean] { let needsRepeat = false; - function replace (types: ReadonlySet, builder: GraphRewriteBuilder, forwardingRef: TypeRef): TypeRef { + function replace(types: ReadonlySet, builder: GraphRewriteBuilder, forwardingRef: TypeRef): TypeRef { const intersections = setFilter(types, t => t instanceof IntersectionType) as Set; const [members, intersectionAttributes] = setOperationMembersRecursively( Array.from(intersections), - "intersect", + "intersect" ); if (members.size === 0) { const t = builder.getPrimitiveType("any", intersectionAttributes, forwardingRef); @@ -354,8 +347,8 @@ export function resolveIntersections ( const extraAttributes = makeTypeAttributesInferred( combineTypeAttributes( "intersect", - Array.from(members).map(t => accumulator.addType(t)), - ), + Array.from(members).map(t => accumulator.addType(t)) + ) ); const attributes = combineTypeAttributes("intersect", intersectionAttributes, extraAttributes); @@ -372,7 +365,7 @@ export function resolveIntersections ( // See for example the intersections-nested.schema example. const allIntersections = setFilter( graph.allTypesUnordered(), - t => t instanceof IntersectionType, + t => t instanceof IntersectionType ) as Set; const resolvableIntersections = setFilter(allIntersections, canResolve); const groups = makeGroupsToFlatten(resolvableIntersections, undefined); diff --git a/packages/quicktype-core/src/support/Chance.ts b/packages/quicktype-core/src/support/Chance.ts index 72b58a0fb..74f8162ac 100644 --- a/packages/quicktype-core/src/support/Chance.ts +++ b/packages/quicktype-core/src/support/Chance.ts @@ -1,3 +1,4 @@ +/* eslint-disable */ // Mersenne Twister from https://gist.github.com/banksean/300494 /* A C-program for MT19937, with initialization improved 2002/1/26. @@ -48,7 +49,7 @@ class MersenneTwister { private mti: number; - constructor (seed: number) { + public constructor(seed: number) { if (seed === undefined) { // kept random number same size as time used previously to ensure no unexpected results downstream seed = Math.floor(Math.random() * Math.pow(10, 13)); @@ -68,12 +69,12 @@ class MersenneTwister { } /* initializes mt[N] with a seed */ - private init_genrand (s: number) { + private init_genrand(s: number) { this.mt[0] = s >>> 0; for (this.mti = 1; this.mti < this.N; this.mti++) { - s = this.mt[this.mti - 1] ^ this.mt[this.mti - 1] >>> 30; + s = this.mt[this.mti - 1] ^ (this.mt[this.mti - 1] >>> 30); this.mt[this.mti] = - (((s & 0xffff0000) >>> 16) * 1812433253 << 16) + (s & 0x0000ffff) * 1812433253 + this.mti; + ((((s & 0xffff0000) >>> 16) * 1812433253) << 16) + (s & 0x0000ffff) * 1812433253 + this.mti; /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ /* In the previous versions, MSBs of the seed affect */ /* only MSBs of the array mt[]. */ @@ -84,7 +85,7 @@ class MersenneTwister { } /* generates a random number on [0,0xffffffff]-interval */ - private genrand_int32 () { + private genrand_int32() { let y; let mag01 = [0x0, this.MATRIX_A]; /* mag01[x] = x * MATRIX_A for x=0,1 */ @@ -99,17 +100,17 @@ class MersenneTwister { } for (kk = 0; kk < this.N - this.M; kk++) { - y = this.mt[kk] & this.UPPER_MASK | this.mt[kk + 1] & this.LOWER_MASK; - this.mt[kk] = this.mt[kk + this.M] ^ y >>> 1 ^ mag01[y & 0x1]; + y = (this.mt[kk] & this.UPPER_MASK) | (this.mt[kk + 1] & this.LOWER_MASK); + this.mt[kk] = this.mt[kk + this.M] ^ (y >>> 1) ^ mag01[y & 0x1]; } for (; kk < this.N - 1; kk++) { - y = this.mt[kk] & this.UPPER_MASK | this.mt[kk + 1] & this.LOWER_MASK; - this.mt[kk] = this.mt[kk + (this.M - this.N)] ^ y >>> 1 ^ mag01[y & 0x1]; + y = (this.mt[kk] & this.UPPER_MASK) | (this.mt[kk + 1] & this.LOWER_MASK); + this.mt[kk] = this.mt[kk + (this.M - this.N)] ^ (y >>> 1) ^ mag01[y & 0x1]; } - y = this.mt[this.N - 1] & this.UPPER_MASK | this.mt[0] & this.LOWER_MASK; - this.mt[this.N - 1] = this.mt[this.M - 1] ^ y >>> 1 ^ mag01[y & 0x1]; + y = (this.mt[this.N - 1] & this.UPPER_MASK) | (this.mt[0] & this.LOWER_MASK); + this.mt[this.N - 1] = this.mt[this.M - 1] ^ (y >>> 1) ^ mag01[y & 0x1]; this.mti = 0; } @@ -118,15 +119,15 @@ class MersenneTwister { /* Tempering */ y ^= y >>> 11; - y ^= y << 7 & 0x9d2c5680; - y ^= y << 15 & 0xefc60000; + y ^= (y << 7) & 0x9d2c5680; + y ^= (y << 15) & 0xefc60000; y ^= y >>> 18; return y >>> 0; } /* generates a random number on [0,1)-real-interval */ - random () { + random() { return this.genrand_int32() * (1.0 / 4294967296.0); /* divided by 2^32 */ } @@ -136,12 +137,12 @@ class MersenneTwister { export class Chance { private readonly mt: MersenneTwister; - constructor (readonly seed: number) { + public constructor(readonly seed: number) { // If no generator function was provided, use our MT this.mt = new MersenneTwister(this.seed); } - random (): number { + random(): number { return this.mt.random(); } @@ -156,7 +157,7 @@ export class Chance { * @returns {Number} a single random integer number * @throws {RangeError} min cannot be greater than max */ - integer (options: { max: number, min: number, }): number { + integer(options: { max: number; min: number }): number { return Math.floor(this.random() * (options.max - options.min + 1) + options.min); } @@ -171,7 +172,7 @@ export class Chance { * @returns {Number} a single random integer number * @throws {RangeError} min cannot be greater than max */ - natural (options: { max: number, }): number { + natural(options: { max: number }): number { return this.integer({ min: 0, max: options.max }); } @@ -183,18 +184,18 @@ export class Chance { return arr[this.natural({ max: arr.length - 1 })]; } - animal (): string { + animal(): string { // if user does not put in any animal type, will return a random animal regardless const animalTypeArray = ["desert", "forest", "ocean", "zoo", "farm", "pet", "grassland"]; return this.pick(animals[this.pick(animalTypeArray)]); } - city (): string { + city(): string { return this.pick(cities); } } -const animals: { [kind: string]: string[], } = { +const animals: { [kind: string]: string[] } = { // list of ocean animals comes from https://owlcation.com/stem/list-of-ocean-animals ocean: [ "Acantharea", @@ -489,7 +490,7 @@ const animals: { [kind: string]: string[], } = { "Yellow Tube Sponge", "Yellowfin Tuna", "Zebrashark", - "Zooplankton", + "Zooplankton" ], // list of desert, grassland, and forest animals comes from http://www.skyenimals.com/ desert: [ @@ -582,7 +583,7 @@ const animals: { [kind: string]: string[], } = { "Vulture", "Waxwing", "Xerus", - "Zebra", + "Zebra" ], grassland: [ "Aardvark", @@ -725,7 +726,7 @@ const animals: { [kind: string]: string[], } = { "Thornbill", "Thrush", "Toad", - "Tortoise", + "Tortoise" ], forest: [ "Agouti", @@ -921,7 +922,7 @@ const animals: { [kind: string]: string[], } = { "Wolf", "Wombat", "Woodchuck", - "Woodpecker", + "Woodpecker" ], // list of farm animals comes from https://www.buzzle.com/articles/farm-animals-list.html farm: [ @@ -952,7 +953,7 @@ const animals: { [kind: string]: string[], } = { "Silkworm", "Turkey", "Yak", - "Zebu", + "Zebu" ], // list of pet animals comes from https://www.dogbreedinfo.com/pets/pet.htm pet: [ @@ -998,7 +999,7 @@ const animals: { [kind: string]: string[], } = { "Sugar Gliders", "Tarantula", "Turkeys", - "Turtles", + "Turtles" ], // list of zoo animals comes from https://bronxzoo.com/animals zoo: [ @@ -1068,8 +1069,8 @@ const animals: { [kind: string]: string[], } = { "Tufted Puffin", "White Cheeked Gibbon", "White-throated Bee Eater", - "Zebra", - ], + "Zebra" + ] }; // Source: https://en.wikipedia.org/wiki/List_of_population_centers_by_latitude @@ -2170,5 +2171,5 @@ const cities: string[] = [ "Villa Las Estrellas", "Esperanza", "Rothera", - "Concordia", + "Concordia" ]; diff --git a/packages/quicktype-core/src/support/Comments.ts b/packages/quicktype-core/src/support/Comments.ts index d7d8a5194..38dd96415 100644 --- a/packages/quicktype-core/src/support/Comments.ts +++ b/packages/quicktype-core/src/support/Comments.ts @@ -9,13 +9,13 @@ export interface CommentOptions { } interface DescriptionBlockCommentConfig { - descriptionBlock: Sourcelike[]; + descriptionBlock: Sourcelike[]; } interface InlineCommentConfig { - lines: Sourcelike[]; + lines: Sourcelike[]; } type CustomCommentConfig = CommentOptions & { - customLines: Sourcelike[], + customLines: Sourcelike[]; }; export type CommentConfig = DescriptionBlockCommentConfig | InlineCommentConfig | CustomCommentConfig; diff --git a/packages/quicktype-core/src/support/Converters.ts b/packages/quicktype-core/src/support/Converters.ts index a06301747..1e9a46250 100644 --- a/packages/quicktype-core/src/support/Converters.ts +++ b/packages/quicktype-core/src/support/Converters.ts @@ -5,15 +5,15 @@ export enum ConvertersOptions { TopLevel = "top-level" } -export function convertersOption () { +export function convertersOption() { return new EnumOption( "converters", "Which converters to generate (top-level by default)", [ [ConvertersOptions.TopLevel, ConvertersOptions.TopLevel], - [ConvertersOptions.AllObjects, ConvertersOptions.AllObjects], + [ConvertersOptions.AllObjects, ConvertersOptions.AllObjects] ], ConvertersOptions.TopLevel, - "secondary", + "secondary" ); } diff --git a/packages/quicktype-core/src/support/Strings.ts b/packages/quicktype-core/src/support/Strings.ts index 78e1ad378..555b861f3 100644 --- a/packages/quicktype-core/src/support/Strings.ts +++ b/packages/quicktype-core/src/support/Strings.ts @@ -12,9 +12,9 @@ export type NamingStyle = import unicode from "unicode-properties"; -function computeAsciiMap (mapper: (codePoint: number) => string): { - charNoEscapeMap: number[], - charStringMap: string[], +function computeAsciiMap(mapper: (codePoint: number) => string): { + charNoEscapeMap: number[]; + charStringMap: string[]; } { const charStringMap: string[] = []; const charNoEscapeMap: number[] = []; @@ -35,7 +35,7 @@ function computeAsciiMap (mapper: (codePoint: number) => string): { type CodePointPredicate = (codePoint: number) => boolean; -function precomputedCodePointPredicate (p: CodePointPredicate): CodePointPredicate { +function precomputedCodePointPredicate(p: CodePointPredicate): CodePointPredicate { const asciiResults: boolean[] = []; for (let cp = 0; cp < 128; cp++) { asciiResults.push(p(cp)); @@ -47,10 +47,10 @@ function precomputedCodePointPredicate (p: CodePointPredicate): CodePointPredica } // FIXME: This is a copy of code in src/Data/String/Util.js -export function utf16ConcatMap (mapper: (utf16Unit: number) => string): (s: string) => string { +export function utf16ConcatMap(mapper: (utf16Unit: number) => string): (s: string) => string { const { charStringMap, charNoEscapeMap } = computeAsciiMap(mapper); - return function stringConcatMap_inner (s: string): string { + return function stringConcatMap_inner(s: string): string { let cs: string[] | null = null; let start = 0; let i = 0; @@ -81,18 +81,18 @@ export function utf16ConcatMap (mapper: (utf16Unit: number) => string): (s: stri }; } -function isHighSurrogate (cc: number): boolean { +function isHighSurrogate(cc: number): boolean { return cc >= 0xd800 && cc <= 0xdbff; } -function isLowSurrogate (cc: number): boolean { +function isLowSurrogate(cc: number): boolean { return cc >= 0xdc00 && cc <= 0xdfff; } -export function utf32ConcatMap (mapper: (codePoint: number) => string): (s: string) => string { +export function utf32ConcatMap(mapper: (codePoint: number) => string): (s: string) => string { const { charStringMap, charNoEscapeMap } = computeAsciiMap(mapper); - return function stringConcatMap_inner (s: string): string { + return function stringConcatMap_inner(s: string): string { let cs: string[] | null = null; let start = 0; let i = 0; @@ -133,15 +133,15 @@ export function utf32ConcatMap (mapper: (codePoint: number) => string): (s: stri }; } -export function utf16LegalizeCharacters (isLegal: (utf16Unit: number) => boolean): (s: string) => string { - return utf16ConcatMap(u => isLegal(u) ? String.fromCharCode(u) : ""); +export function utf16LegalizeCharacters(isLegal: (utf16Unit: number) => boolean): (s: string) => string { + return utf16ConcatMap(u => (isLegal(u) ? String.fromCharCode(u) : "")); } -export function legalizeCharacters (isLegal: (codePoint: number) => boolean): (s: string) => string { - return utf32ConcatMap(u => u <= 0xffff && isLegal(u) ? String.fromCharCode(u) : ""); +export function legalizeCharacters(isLegal: (codePoint: number) => boolean): (s: string) => string { + return utf32ConcatMap(u => (u <= 0xffff && isLegal(u) ? String.fromCharCode(u) : "")); } -export function repeatString (s: string, n: number): string { +export function repeatString(s: string, n: number): string { assert(n >= 0, "Cannot repeat a string a negative number of times"); if (n === 0) return ""; @@ -163,13 +163,13 @@ export function repeatString (s: string, n: number): string { return result; } -export function intToHex (i: number, width: number): string { +export function intToHex(i: number, width: number): string { let str = i.toString(16); if (str.length >= width) return str; return repeatString("0", width - str.length) + str; } -export function standardUnicodeHexEscape (codePoint: number): string { +export function standardUnicodeHexEscape(codePoint: number): string { if (codePoint <= 0xffff) { return "\\u" + intToHex(codePoint, 4); } else { @@ -177,16 +177,16 @@ export function standardUnicodeHexEscape (codePoint: number): string { } } -export function escapeNonPrintableMapper ( +export function escapeNonPrintableMapper( printablePredicate: (codePoint: number) => boolean, - escaper: (codePoint: number) => string, + escaper: (codePoint: number) => string ): (u: number) => string { - function mapper (u: number): string { + function mapper(u: number): string { switch (u) { case 0x5c: return "\\\\"; case 0x22: - return "\\\""; + return '\\"'; case 0x0a: return "\\n"; case 0x09: @@ -206,75 +206,73 @@ export function escapeNonPrintableMapper ( export const utf16StringEscape = utf16ConcatMap(escapeNonPrintableMapper(isPrintable, standardUnicodeHexEscape)); export const stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, standardUnicodeHexEscape)); -export function isPrintable (codePoint: number): boolean { +export function isPrintable(codePoint: number): boolean { if (codePoint > 0xffff) return false; const category = unicode.getCategory(codePoint); - return ( - [ - "Mc", - "No", - "Sk", - "Me", - "Nd", - "Po", - "Lt", - "Pc", - "Sm", - "Zs", - "Lu", - "Pd", - "So", - "Pe", - "Pf", - "Ps", - "Sc", - "Ll", - "Lm", - "Pi", - "Nl", - "Mn", - "Lo", - ].includes(category) - ); -} - -export function isAscii (codePoint: number): boolean { + return [ + "Mc", + "No", + "Sk", + "Me", + "Nd", + "Po", + "Lt", + "Pc", + "Sm", + "Zs", + "Lu", + "Pd", + "So", + "Pe", + "Pf", + "Ps", + "Sc", + "Ll", + "Lm", + "Pi", + "Nl", + "Mn", + "Lo" + ].includes(category); +} + +export function isAscii(codePoint: number): boolean { return codePoint < 128; } -export function isLetter (codePoint: number): boolean { +export function isLetter(codePoint: number): boolean { const category = unicode.getCategory(codePoint); // FIXME: Include Letter, modifier (Lm)? return ["Lu", "Ll", "Lt", "Lo"].includes(category); } -export function isDigit (codePoint: number): boolean { +export function isDigit(codePoint: number): boolean { const category = unicode.getCategory(codePoint); return ["Nd"].includes(category); } -export function isNumeric (codePoint: number): boolean { +export function isNumeric(codePoint: number): boolean { const category = unicode.getCategory(codePoint); return ["No", "Nd", "Nl"].includes(category); } -export function isLetterOrDigit (codePoint: number): boolean { +export function isLetterOrDigit(codePoint: number): boolean { return isLetter(codePoint) || isDigit(codePoint); } -export function isLetterOrUnderscore (codePoint: number): boolean { +export function isLetterOrUnderscore(codePoint: number): boolean { return isLetter(codePoint) || codePoint === 0x5f; } -export function isLetterOrUnderscoreOrDigit (codePoint: number): boolean { +export function isLetterOrUnderscoreOrDigit(codePoint: number): boolean { return isLetterOrUnderscore(codePoint) || isDigit(codePoint); } -export function isWordCharacter (codePoint: number): boolean { +export function isWordCharacter(codePoint: number): boolean { return isLetter(codePoint) || isDigit(codePoint); } -export function trimEnd (str: string): string { +export function trimEnd(str: string): string { const l = str.length; let firstWS = l; for (let i = l - 1; i >= 0; i--) { @@ -286,39 +284,39 @@ export function trimEnd (str: string): string { return str.slice(0, firstWS); } -function modifyFirstChar (f: (c: string) => string, s: string): string { +function modifyFirstChar(f: (c: string) => string, s: string): string { if (s === "") return s; return f(s[0]) + s.slice(1); } -export function capitalize (str: string): string { +export function capitalize(str: string): string { return modifyFirstChar(c => c.toUpperCase(), str); } -export function decapitalize (str: string): string { +export function decapitalize(str: string): string { return modifyFirstChar(c => c.toLowerCase(), str); } const wordSeparatorRegex = /[-_. ]+/; -export function pascalCase (str: string): string { +export function pascalCase(str: string): string { const words = str.split(wordSeparatorRegex).map(capitalize); return words.join(""); } -export function camelCase (str: string): string { +export function camelCase(str: string): string { return decapitalize(pascalCase(str)); } -export function snakeCase (str: string): string { +export function snakeCase(str: string): string { const words = splitIntoWords(str).map(({ word }) => word.toLowerCase()); return words.join("_"); } -export function startWithLetter ( +export function startWithLetter( isAllowedStart: (codePoint: number) => boolean, // FIXME: technically, this operates on UTF16 units upper: boolean, - str: string, + str: string ): string { const modify = upper ? capitalize : decapitalize; if (str === "") return modify("empty"); @@ -340,7 +338,7 @@ export const fastIsUpperCase = precomputedCodePointPredicate(cp => unicode.isUpp const fastNonLetter = precomputedCodePointPredicate(cp => !unicode.isLowerCase(cp) && !unicode.isUpperCase(cp)); const fastIsDigit = precomputedCodePointPredicate(isDigit); -export function splitIntoWords (s: string): WordInName[] { +export function splitIntoWords(s: string): WordInName[] { // [start, end, allUpper] const intervals: Array<[number, number, boolean]> = []; let intervalStart: number | undefined = undefined; @@ -348,15 +346,15 @@ export function splitIntoWords (s: string): WordInName[] { let i = 0; let lastLowerCaseIndex: number | undefined = undefined; - function atEnd (): boolean { + function atEnd(): boolean { return i >= len; } - function currentCodePoint (): number { + function currentCodePoint(): number { return defined(s.codePointAt(i)); } - function skipWhile (p: (codePoint: number) => boolean): void { + function skipWhile(p: (codePoint: number) => boolean): void { while (!atEnd()) { const cp = currentCodePoint(); if (!p(cp)) break; @@ -365,32 +363,32 @@ export function splitIntoWords (s: string): WordInName[] { } } - function skipNonWord (): void { + function skipNonWord(): void { skipWhile(fastIsNonWordCharacter); } - function skipLowerCase (): void { + function skipLowerCase(): void { skipWhile(fastIsLowerCase); } - function skipUpperCase (): void { + function skipUpperCase(): void { skipWhile(fastIsUpperCase); } - function skipNonLetter (): void { + function skipNonLetter(): void { skipWhile(fastNonLetter); } - function skipDigits (): void { + function skipDigits(): void { skipWhile(fastIsDigit); } - function startInterval (): void { + function startInterval(): void { assert(intervalStart === undefined, "Interval started before last one was committed"); intervalStart = i; } - function commitInterval (): void { + function commitInterval(): void { if (intervalStart === undefined) { return panic("Tried to commit interval without starting one"); } @@ -410,7 +408,7 @@ export function splitIntoWords (s: string): WordInName[] { intervalStart = undefined; } - function intervalLength (): number { + function intervalLength(): number { if (intervalStart === undefined) { return panic("Tried to get interval length without starting one"); } @@ -454,7 +452,7 @@ export function splitIntoWords (s: string): WordInName[] { const words: WordInName[] = []; for (const [start, end, allUpper] of intervals) { const word = s.slice(start, end); - const isAcronym = lastLowerCaseIndex !== undefined && allUpper || knownAcronyms.has(word.toLowerCase()); + const isAcronym = (lastLowerCaseIndex !== undefined && allUpper) || knownAcronyms.has(word.toLowerCase()); words.push({ word, isAcronym }); } @@ -463,31 +461,31 @@ export function splitIntoWords (s: string): WordInName[] { export type WordStyle = (word: string) => string; -export function firstUpperWordStyle (s: string): string { +export function firstUpperWordStyle(s: string): string { assert(s.length > 0, "Cannot style an empty string"); return s[0].toUpperCase() + s.slice(1).toLowerCase(); } -export function allUpperWordStyle (s: string): string { +export function allUpperWordStyle(s: string): string { return s.toUpperCase(); } -export function originalWord (s: string): string { +export function originalWord(s: string): string { return s; } -export function allLowerWordStyle (s: string): string { +export function allLowerWordStyle(s: string): string { return s.toLowerCase(); } -function styleWord (style: WordStyle, word: string): string { +function styleWord(style: WordStyle, word: string): string { assert(word.length > 0, "Tried to style an empty word"); const result = style(word); assert(result.length > 0, "Word style must not make word empty"); return result; } -export function combineWords ( +export function combineWords( words: WordInName[], removeInvalidCharacters: (s: string) => string, firstWordStyle: WordStyle, @@ -495,7 +493,7 @@ export function combineWords ( firstWordAcronymStyle: WordStyle, restAcronymStyle: WordStyle, separator: string, - isStartCharacter: (codePoint: number) => boolean, + isStartCharacter: (codePoint: number) => boolean ): string { const legalizedWords: WordInName[] = []; for (const w of words) { @@ -506,7 +504,7 @@ export function combineWords ( if (legalizedWords.length === 0) { const validEmpty = removeInvalidCharacters("empty"); - assert(validEmpty.length > 0, "Word \"empty\" is invalid in target language"); + assert(validEmpty.length > 0, 'Word "empty" is invalid in target language'); legalizedWords.push({ word: validEmpty, isAcronym: false }); } @@ -517,11 +515,11 @@ export function combineWords ( let restWords: WordInName[]; if (!isStartCharacter(defined(styledFirstWord.codePointAt(0)))) { const validThe = removeInvalidCharacters("the"); - assert(validThe.length > 0, "Word \"the\" is invalid in the target language"); + assert(validThe.length > 0, 'Word "the" is invalid in the target language'); const styledThe = styleWord(firstWordStyle, validThe); assert( isStartCharacter(defined(styledThe.codePointAt(0))), - "The first character of styling \"the\" is not a start character", + 'The first character of styling "the" is not a start character' ); styledWords.push(styledThe); restWords = legalizedWords; @@ -538,15 +536,15 @@ export function combineWords ( return styledWords.join(separator); } -export function addPrefixIfNecessary (prefix: string, name: string): string { +export function addPrefixIfNecessary(prefix: string, name: string): string { // Take care not to doubly-prefix type names return name.startsWith(prefix) ? name : prefix + name; } -export function makeNameStyle ( +export function makeNameStyle( namingStyle: NamingStyle, legalizeName: (name: string) => string, - prefix?: string, + prefix?: string ): (rawName: string) => string { let separator: string; let firstWordStyle: WordStyle; @@ -601,7 +599,7 @@ export function makeNameStyle ( firstWordAcronymStyle, restAcronymStyle, separator, - isLetterOrUnderscore, + isLetterOrUnderscore ); if (prefix !== undefined) { diff --git a/packages/quicktype-core/src/support/Support.ts b/packages/quicktype-core/src/support/Support.ts index ab67bbefc..0fef6624a 100644 --- a/packages/quicktype-core/src/support/Support.ts +++ b/packages/quicktype-core/src/support/Support.ts @@ -4,12 +4,12 @@ import { messageError } from "../Messages"; import * as YAML from "yaml"; export interface StringMap { - [name: string]: any; + [name: string]: any; } -export function isStringMap (x: any): x is StringMap; -export function isStringMap (x: any, checkValue: (v: any) => v is T): x is { [name: string]: T, }; -export function isStringMap (x: any, checkValue?: (v: any) => v is T): boolean { +export function isStringMap(x: any): x is StringMap; +export function isStringMap(x: any, checkValue: (v: any) => v is T): x is { [name: string]: T }; +export function isStringMap(x: any, checkValue?: (v: any) => v is T): boolean { if (typeof x !== "object" || Array.isArray(x) || x === null) { return false; } @@ -26,20 +26,20 @@ export function isStringMap (x: any, checkValue?: (v: any) => v is T): boolea return true; } -export function checkString (x: any): x is string { +export function checkString(x: any): x is string { return typeof x === "string"; } -export function checkStringMap (x: any): StringMap; -export function checkStringMap (x: any, checkValue: (v: any) => v is T): { [name: string]: T, }; -export function checkStringMap (x: any, checkValue?: (v: any) => v is T): StringMap { +export function checkStringMap(x: any): StringMap; +export function checkStringMap(x: any, checkValue: (v: any) => v is T): { [name: string]: T }; +export function checkStringMap(x: any, checkValue?: (v: any) => v is T): StringMap { if (isStringMap(x, checkValue as any)) return x; return panic(`Value must be an object, but is ${x}`); } -export function checkArray (x: any): any[]; -export function checkArray (x: any, checkItem: (v: any) => v is T): T[]; -export function checkArray (x: any, checkItem?: (v: any) => v is T): T[] { +export function checkArray(x: any): any[]; +export function checkArray(x: any, checkItem: (v: any) => v is T): T[]; +export function checkArray(x: any, checkItem?: (v: any) => v is T): T[] { if (!Array.isArray(x)) { return panic(`Value must be an array, but is ${x}`); } @@ -55,35 +55,35 @@ export function checkArray (x: any, checkItem?: (v: any) => v is T): T[] { return x; } -export function defined (x: T | undefined): T { +export function defined(x: T | undefined): T { if (x !== undefined) return x; return panic("Defined value expected, but got undefined"); } -export function nonNull (x: T | null): T { +export function nonNull(x: T | null): T { if (x !== null) return x; return panic("Non-null value expected, but got null"); } -export function assertNever (x: never): never { +export function assertNever(x: never): never { return messageError("InternalError", { message: `Unexpected object ${x as any}` }); } -export function assert (condition: boolean, message = "Assertion failed"): void { +export function assert(condition: boolean, message = "Assertion failed"): void { if (!condition) { return messageError("InternalError", { message }); } } -export function panic (message: string): never { +export function panic(message: string): never { return messageError("InternalError", { message }); } -export function mustNotHappen (): never { +export function mustNotHappen(): never { return panic("This must not happen"); } -export function repeated (n: number, value: T): T[] { +export function repeated(n: number, value: T): T[] { const arr: T[] = []; for (let i = 0; i < n; i++) { arr.push(value); @@ -92,7 +92,7 @@ export function repeated (n: number, value: T): T[] { return arr; } -export function repeatedCall (n: number, producer: () => T): T[] { +export function repeatedCall(n: number, producer: () => T): T[] { const arr: T[] = []; for (let i = 0; i < n; i++) { arr.push(producer()); @@ -101,7 +101,7 @@ export function repeatedCall (n: number, producer: () => T): T[] { return arr; } -export function errorMessage (e: any): string { +export function errorMessage(e: any): string { if (e instanceof Error) { return e.message; } @@ -109,12 +109,12 @@ export function errorMessage (e: any): string { return e.toString(); } -export function inflateBase64 (encoded: string): string { +export function inflateBase64(encoded: string): string { const bytes = Base64.atob(encoded); return pako.inflate(bytes, { to: "string" }); } -export function parseJSON (text: string, description: string, address = ""): any { +export function parseJSON(text: string, description: string, address = ""): any { try { // https://gist.github.com/pbakondy/f5045eff725193dad9c7 if (text.charCodeAt(0) === 0xfeff) { @@ -135,11 +135,11 @@ export function parseJSON (text: string, description: string, address = " nn.typeRef), + setMap(nonNulls, nn => nn.typeRef) ); } return panic("Trying to remove null results in empty union."); } -function makeScalar (builder: TypeBuilder, ft: GQLType): TypeRef { +function makeScalar(builder: TypeBuilder, ft: GQLType): TypeRef { switch (ft.name) { case "Boolean": return builder.getPrimitiveType("bool"); @@ -142,7 +142,7 @@ function makeScalar (builder: TypeBuilder, ft: GQLType): TypeRef { } } -function hasOptionalDirectives (directives?: DirectiveNode[]): boolean { +function hasOptionalDirectives(directives?: DirectiveNode[]): boolean { if (!directives) return false; for (const d of directives) { const name = d.name.value; @@ -158,7 +158,7 @@ interface Selection { selection: SelectionNode; } -function expandSelectionSet (selectionSet: SelectionSetNode, inType: GQLType, optional: boolean): Selection[] { +function expandSelectionSet(selectionSet: SelectionSetNode, inType: GQLType, optional: boolean): Selection[] { return selectionSet.selections .reverse() .map(s => ({ selection: s, inType, optional: optional || hasOptionalDirectives(s.directives) })); @@ -167,17 +167,17 @@ function expandSelectionSet (selectionSet: SelectionSetNode, inType: GQLType, op interface GQLSchema { readonly mutationType?: GQLType; readonly queryType: GQLType; - readonly types: { [name: string]: GQLType, }; + readonly types: { [name: string]: GQLType }; } class GQLQuery { private readonly _schema: GQLSchema; - private readonly _fragments: { [name: string]: FragmentDefinitionNode, }; + private readonly _fragments: { [name: string]: FragmentDefinitionNode }; - readonly queries: readonly OperationDefinitionNode[]; + public readonly queries: readonly OperationDefinitionNode[]; - constructor (schema: GQLSchema, queryString: string) { + public constructor(schema: GQLSchema, queryString: string) { this._schema = schema; this._fragments = {}; @@ -201,7 +201,7 @@ class GQLQuery { builder: TypeBuilder, fieldNode: FieldNode, fieldType: GQLType, - containingTypeName: string, + containingTypeName: string ): TypeRef => { let optional = hasOptionalDirectives(fieldNode.directives); let result: TypeRef; @@ -224,11 +224,11 @@ class GQLQuery { fieldNode.selectionSet, fieldType, fieldNode.name.value, - containingTypeName, + containingTypeName ), fieldNode.name.value, null, - containingTypeName, + containingTypeName ); case TypeKind.ENUM: if (!fieldType.enumValues) { @@ -260,7 +260,7 @@ class GQLQuery { optional = true; result = builder.getArrayType( emptyTypeAttributes, - this.makeIRTypeFromFieldNode(builder, fieldNode, fieldType.ofType, containingTypeName), + this.makeIRTypeFromFieldNode(builder, fieldNode, fieldType.ofType, containingTypeName) ); break; case TypeKind.NON_NULL: @@ -270,7 +270,7 @@ class GQLQuery { result = removeNull( builder, - this.makeIRTypeFromFieldNode(builder, fieldNode, fieldType.ofType, containingTypeName), + this.makeIRTypeFromFieldNode(builder, fieldNode, fieldType.ofType, containingTypeName) ); break; default: @@ -296,7 +296,7 @@ class GQLQuery { gqlType: GQLType, containingFieldName: string | null, containingTypeName: string | null, - overrideName?: string, + overrideName?: string ): TypeRef => { if ( gqlType.kind !== TypeKind.OBJECT && @@ -354,7 +354,7 @@ class GQLQuery { return builder.getClassType(makeNames(nameOrOverride, containingFieldName, containingTypeName), properties); }; - makeType (builder: TypeBuilder, query: OperationDefinitionNode, queryName: string): TypeRef { + public makeType(builder: TypeBuilder, query: OperationDefinitionNode, queryName: string): TypeRef { if (query.operation === "query") { return this.makeIRTypeFromSelectionSet( builder, @@ -362,7 +362,7 @@ class GQLQuery { this._schema.queryType, null, queryName, - "data", + "data" ); } @@ -377,7 +377,7 @@ class GQLQuery { this._schema.mutationType, null, queryName, - "data", + "data" ); } @@ -386,15 +386,14 @@ class GQLQuery { } class GQLSchemaFromJSON implements GQLSchema { - readonly types: { [name: string]: GQLType, } = {}; + public readonly types: { [name: string]: GQLType } = {}; // @ts-expect-error: The constructor can return early, but only by throwing. - readonly queryType: GQLType; + public readonly queryType: GQLType; - // @ts-expect-error: The constructor can return early, but only by throwing. - readonly mutationType?: GQLType; + public readonly mutationType?: GQLType; - constructor (json: any) { + public constructor(json: any) { const schema: GraphQLSchema = json.data; if (schema.__schema.queryType.name === null) { @@ -444,7 +443,7 @@ class GQLSchemaFromJSON implements GQLSchema { name: f.name, description: f.description, type: this.makeType(f.type), - args: f.args.map(this.makeInputValue), + args: f.args.map(this.makeInputValue) }; }); // console.log(`${target.name} has ${target.fields.length} fields`); @@ -478,7 +477,7 @@ class GQLSchemaFromJSON implements GQLSchema { name: iv.name, description: iv.description, type: this.makeType(iv.type), - defaultValue: iv.defaultValue, + defaultValue: iv.defaultValue }; }; @@ -493,18 +492,18 @@ class GQLSchemaFromJSON implements GQLSchema { const type: GQLType = { kind: t.kind, description: t.description, - ofType: this.makeType(t.ofType), + ofType: this.makeType(t.ofType) }; this.addTypeFields(type, t); return type; }; } -function makeGraphQLQueryTypes ( +function makeGraphQLQueryTypes( topLevelName: string, builder: TypeBuilder, json: any, - queryString: string, + queryString: string ): Map { const schema = new GQLSchemaFromJSON(json); const query = new GQLQuery(schema, queryString); @@ -518,29 +517,29 @@ function makeGraphQLQueryTypes ( const dataType = query.makeType(builder, odn, queryName); const dataOrNullType = builder.getUnionType( emptyTypeAttributes, - new Set([dataType, builder.getPrimitiveType("null")]), + new Set([dataType, builder.getPrimitiveType("null")]) ); const errorType = builder.getClassType( namesTypeAttributeKind.makeAttributes(TypeNames.make(new Set(["error"]), new Set(["graphQLError"]), false)), mapFromObject({ message: builder.makeClassProperty( builder.getStringType(emptyTypeAttributes, StringTypes.unrestricted), - false, - ), - }), + false + ) + }) ); const errorArray = builder.getArrayType( namesTypeAttributeKind.makeAttributes( - TypeNames.make(new Set(["errors"]), new Set(["graphQLErrors"]), false), + TypeNames.make(new Set(["errors"]), new Set(["graphQLErrors"]), false) ), - errorType, + errorType ); const t = builder.getClassType( makeNamesTypeAttributes(queryName, false), mapFromObject({ data: builder.makeClassProperty(dataOrNullType, false), - errors: builder.makeClassProperty(errorArray, true), - }), + errors: builder.makeClassProperty(errorArray, true) + }) ); types.set(queryName, t); } @@ -549,42 +548,45 @@ function makeGraphQLQueryTypes ( } export interface GraphQLSourceData { - name: string; query: string; schema: any; + name: string; + query: string; + schema: any; } interface GraphQLTopLevel { - query: string; schema: any; + query: string; + schema: any; } export class GraphQLInput implements Input { - readonly kind: string = "graphql"; + public readonly kind: string = "graphql"; - readonly needIR: boolean = true; + public readonly needIR: boolean = true; - readonly needSchemaProcessing: boolean = false; + public readonly needSchemaProcessing: boolean = false; private readonly _topLevels: Map = new Map(); - async addSource (source: GraphQLSourceData): Promise { + public async addSource(source: GraphQLSourceData): Promise { this.addSourceSync(source); } - addSourceSync (source: GraphQLSourceData): void { + public addSourceSync(source: GraphQLSourceData): void { this._topLevels.set(source.name, { schema: source.schema, - query: source.query, + query: source.query }); } - singleStringSchemaSource (): undefined { + public singleStringSchemaSource(): undefined { return undefined; } - async addTypes (ctx: RunContext, typeBuilder: TypeBuilder): Promise { + public async addTypes(ctx: RunContext, typeBuilder: TypeBuilder): Promise { this.addTypesSync(ctx, typeBuilder); } - addTypesSync (_ctx: RunContext, typeBuilder: TypeBuilder): void { + public addTypesSync(_ctx: RunContext, typeBuilder: TypeBuilder): void { for (const [name, { schema, query }] of this._topLevels) { const newTopLevels = makeGraphQLQueryTypes(name, typeBuilder, schema, query); for (const [actualName, t] of newTopLevels) { diff --git a/src/CompressedJSONFromStream.ts b/src/CompressedJSONFromStream.ts index 850da2fc1..c442b2f8f 100644 --- a/src/CompressedJSONFromStream.ts +++ b/src/CompressedJSONFromStream.ts @@ -3,7 +3,7 @@ import { type Value } from "quicktype-core"; import { CompressedJSON } from "quicktype-core"; import { Parser } from "stream-json"; -const methodMap: { [name: string]: string, } = { +const methodMap: { [name: string]: string } = { startObject: "pushObjectContext", endObject: "finishObject", startArray: "pushArrayContext", @@ -15,13 +15,13 @@ const methodMap: { [name: string]: string, } = { stringValue: "commitString", nullValue: "commitNull", trueValue: "handleTrueValue", - falseValue: "handleFalseValue", + falseValue: "handleFalseValue" }; export class CompressedJSONFromStream extends CompressedJSON { - async parse (readStream: Readable): Promise { + public async parse(readStream: Readable): Promise { const combo = new Parser({ packKeys: true, packStrings: true }); - combo.on("data", (item: { name: string, value: string | undefined, }) => { + combo.on("data", (item: { name: string; value: string | undefined }) => { if (typeof methodMap[item.name] === "string") { (this as any)[methodMap[item.name]](item.value); } @@ -52,17 +52,17 @@ export class CompressedJSONFromStream extends CompressedJSON { } }; - protected handleEndNumber (): void { + protected handleEndNumber(): void { const isDouble = this.context.currentNumberIsDouble; this.popContext(); this.commitNumber(isDouble); } - protected handleTrueValue (): void { + protected handleTrueValue(): void { this.commitBoolean(true); } - protected handleFalseValue (): void { + protected handleFalseValue(): void { this.commitBoolean(false); } } From f79172171ad3d96faf41689d2ef60381d5ae25ee Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Thu, 11 Apr 2024 23:23:22 -0700 Subject: [PATCH 32/94] fix nullish errors --- .../quicktype-core/src/ConvenienceRenderer.ts | 2 +- .../quicktype-core/src/MakeTransformations.ts | 2 +- packages/quicktype-core/src/TypeBuilder.ts | 2 +- packages/quicktype-core/src/TypeUtils.ts | 2 +- .../src/input/JSONSchemaInput.ts | 6 +- .../src/input/io/get-stream/buffer-stream.ts | 6 +- .../src/input/io/get-stream/index.ts | 8 +- packages/quicktype-core/src/language/CJSON.ts | 428 +++++++++--------- .../src/language/Objective-C.ts | 2 +- packages/quicktype-graphql-input/src/index.ts | 2 +- src/index.ts | 219 ++++----- 11 files changed, 341 insertions(+), 338 deletions(-) diff --git a/packages/quicktype-core/src/ConvenienceRenderer.ts b/packages/quicktype-core/src/ConvenienceRenderer.ts index 7fd2041db..21e219ef0 100644 --- a/packages/quicktype-core/src/ConvenienceRenderer.ts +++ b/packages/quicktype-core/src/ConvenienceRenderer.ts @@ -743,7 +743,7 @@ export abstract class ConvenienceRenderer extends Renderer { sortOrder: ((n: Name, t: Type) => string) | null, f: (name: Name, t: Type, position: ForEachPosition) => void ): void { - const iterateMembers = members === null ? u.members : members; + const iterateMembers = members ?? u.members; if (sortOrder === null) { sortOrder = n => defined(this.names.get(n)); } diff --git a/packages/quicktype-core/src/MakeTransformations.ts b/packages/quicktype-core/src/MakeTransformations.ts index 8daede47e..0b5de7301 100644 --- a/packages/quicktype-core/src/MakeTransformations.ts +++ b/packages/quicktype-core/src/MakeTransformations.ts @@ -184,7 +184,7 @@ function replaceUnion( transformerForClass === undefined || transformerForMap === undefined, "Can't have both class and map in a transformed union" ); - const transformerForObject = transformerForClass !== undefined ? transformerForClass : transformerForMap; + const transformerForObject = transformerForClass ?? transformerForMap; const transformer = new DecodingChoiceTransformer( graph, diff --git a/packages/quicktype-core/src/TypeBuilder.ts b/packages/quicktype-core/src/TypeBuilder.ts index d9a8b17ef..5370e5be8 100644 --- a/packages/quicktype-core/src/TypeBuilder.ts +++ b/packages/quicktype-core/src/TypeBuilder.ts @@ -185,7 +185,7 @@ export class TypeBuilder { assert(this.types[typeRefIndex(forwardingRef)] === undefined); } - const tref = forwardingRef !== undefined ? forwardingRef : this.reserveTypeRef(); + const tref = forwardingRef ?? this.reserveTypeRef(); if (attributes !== undefined) { const index = typeRefIndex(tref); this.typeAttributes[index] = combineTypeAttributes("union", this.typeAttributes[index], attributes); diff --git a/packages/quicktype-core/src/TypeUtils.ts b/packages/quicktype-core/src/TypeUtils.ts index 7a39c450a..5a37546bd 100644 --- a/packages/quicktype-core/src/TypeUtils.ts +++ b/packages/quicktype-core/src/TypeUtils.ts @@ -304,7 +304,7 @@ export function matchType( typeNotSupported, enumType, unionType, - transformedStringType || typeNotSupported + transformedStringType ?? typeNotSupported ); } diff --git a/packages/quicktype-core/src/input/JSONSchemaInput.ts b/packages/quicktype-core/src/input/JSONSchemaInput.ts index 427e74d75..c0aa1c1b8 100644 --- a/packages/quicktype-core/src/input/JSONSchemaInput.ts +++ b/packages/quicktype-core/src/input/JSONSchemaInput.ts @@ -85,7 +85,7 @@ function withRef(refOrLoc: Ref | (() => Ref) | Location, props function withRef(refOrLoc: Ref | (() => Ref) | Location, props?: T): any { const ref = typeof refOrLoc === "function" ? refOrLoc() : refOrLoc instanceof Ref ? refOrLoc : refOrLoc.canonicalRef; - return Object.assign({ ref }, props === undefined ? {} : props); + return Object.assign({ ref }, props ?? {}); } function checkJSONSchemaObject(x: any, refOrLoc: Ref | (() => Ref)): StringMap { @@ -378,7 +378,7 @@ class Location { public readonly haveID: boolean = false ) { this.canonicalRef = canonicalRef; - this.virtualRef = virtualRef !== undefined ? virtualRef : canonicalRef; + this.virtualRef = virtualRef ?? canonicalRef; } public updateWithID(id: any) { @@ -1143,7 +1143,7 @@ async function refsInSchemaForURI( name = schema.title; } else { const maybeName = nameFromURI(uri); - name = maybeName !== undefined ? maybeName : defaultName; + name = maybeName ?? defaultName; } return [name, ref]; diff --git a/packages/quicktype-core/src/input/io/get-stream/buffer-stream.ts b/packages/quicktype-core/src/input/io/get-stream/buffer-stream.ts index f1cb10861..16ea64a20 100644 --- a/packages/quicktype-core/src/input/io/get-stream/buffer-stream.ts +++ b/packages/quicktype-core/src/input/io/get-stream/buffer-stream.ts @@ -1,7 +1,7 @@ import { type Options } from "."; import { PassThrough } from "readable-stream"; -export default function bufferStream (opts: Options) { +export default function bufferStream(opts: Options) { opts = Object.assign({}, opts); const array = opts.array; @@ -10,8 +10,10 @@ export default function bufferStream (opts: Options) { let objectMode = false; if (array) { + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing objectMode = !(encoding || buffer); } else { + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing encoding = encoding || "utf8"; } @@ -22,7 +24,7 @@ export default function bufferStream (opts: Options) { let len = 0; const ret: any[] = []; const stream = new PassThrough({ - objectMode, + objectMode }) as any; if (encoding) { diff --git a/packages/quicktype-core/src/input/io/get-stream/index.ts b/packages/quicktype-core/src/input/io/get-stream/index.ts index 98ae97240..d8d067cae 100644 --- a/packages/quicktype-core/src/input/io/get-stream/index.ts +++ b/packages/quicktype-core/src/input/io/get-stream/index.ts @@ -7,14 +7,14 @@ export interface Options { maxBuffer?: number; } -export async function getStream (inputStream: Readable, opts: Options = {}) { +export async function getStream(inputStream: Readable, opts: Options = {}) { if (!inputStream) { return await Promise.reject(new Error("Expected a stream")); } opts = Object.assign({ maxBuffer: Infinity }, opts); - const maxBuffer = opts.maxBuffer || Infinity; + const maxBuffer = opts.maxBuffer ?? Infinity; let stream: any; let clean; @@ -53,10 +53,10 @@ export async function getStream (inputStream: Readable, opts: Options = {}) { return await p.then(() => stream.getBufferedValue()); } -export function buffer (stream: Readable, opts: Options = {}) { +export function buffer(stream: Readable, opts: Options = {}) { getStream(stream, Object.assign({}, opts, { encoding: "buffer" })); } -export function array (stream: Readable, opts: Options = {}) { +export function array(stream: Readable, opts: Options = {}) { getStream(stream, Object.assign({}, opts, { array: true })); } diff --git a/packages/quicktype-core/src/language/CJSON.ts b/packages/quicktype-core/src/language/CJSON.ts index 4bfb848ea..84d1c41eb 100644 --- a/packages/quicktype-core/src/language/CJSON.ts +++ b/packages/quicktype-core/src/language/CJSON.ts @@ -876,57 +876,57 @@ export class CJSONRenderer extends ConvenienceRenderer { ], () => { const add = (cJSON: TypeCJSON, level: number, child_level: number) => { - if (cJSON.items!.cjsonType === "cJSON_Array") { + if (cJSON.items?.cjsonType === "cJSON_Array") { /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Map") { + } else if (cJSON.items?.cjsonType === "cJSON_Map") { /* Not supported */ } else if ( - cJSON.items!.cjsonType === "cJSON_Invalid" || - cJSON.items!.cjsonType === "cJSON_NULL" + cJSON.items?.cjsonType === "cJSON_Invalid" || + cJSON.items?.cjsonType === "cJSON_NULL" ) { this.emitLine( "list_add_tail(x", child_level.toString(), ", (", - cJSON.items!.cType, + cJSON.items?.cType, " *)0xDEADBEEF, sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, " *));" ); - } else if (cJSON.items!.cjsonType === "cJSON_String") { + } else if (cJSON.items?.cjsonType === "cJSON_String") { this.emitLine( "list_add_tail(x", child_level.toString(), ", strdup(", - cJSON.items!.getValue, + cJSON.items?.getValue, "(e", child_level.toString(), ")), sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, " *));" ); } else if ( - cJSON.items!.cjsonType === "cJSON_Object" || - cJSON.items!.cjsonType === "cJSON_Union" + cJSON.items?.cjsonType === "cJSON_Object" || + cJSON.items?.cjsonType === "cJSON_Union" ) { this.emitLine( "list_add_tail(x", child_level.toString(), ", ", - cJSON.items!.getValue, + cJSON.items?.getValue, "(e", child_level.toString(), "), sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, " *));" ); } else { this.emitLine( - cJSON.items!.cType, + cJSON.items?.cType, " * tmp", level > 0 ? level.toString() : "", " = cJSON_malloc(sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, "));" ); this.emitBlock( @@ -936,7 +936,7 @@ export class CJSONRenderer extends ConvenienceRenderer { "* tmp", level > 0 ? level.toString() : "", " = ", - cJSON.items!.getValue, + cJSON.items?.getValue, "(e", child_level.toString(), ");" @@ -947,7 +947,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ", tmp", level > 0 ? level.toString() : "", ", sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, " *));" ); } @@ -955,7 +955,7 @@ export class CJSONRenderer extends ConvenienceRenderer { } }; - if (cJSON.items!.isNullable) { + if (cJSON.items?.isNullable) { this.emitBlock( ["if (!cJSON_IsNull(e", child_level.toString(), "))"], () => { @@ -1005,13 +1005,13 @@ export class CJSONRenderer extends ConvenienceRenderer { ], () => { const add = (cJSON: TypeCJSON, level: number, child_level: number) => { - if (cJSON.items!.cjsonType === "cJSON_Array") { + if (cJSON.items?.cjsonType === "cJSON_Array") { /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Map") { + } else if (cJSON.items?.cjsonType === "cJSON_Map") { /* Not supported */ } else if ( - cJSON.items!.cjsonType === "cJSON_Invalid" || - cJSON.items!.cjsonType === "cJSON_NULL" + cJSON.items?.cjsonType === "cJSON_Invalid" || + cJSON.items?.cjsonType === "cJSON_NULL" ) { this.emitLine( "hashtable_add(x", @@ -1019,28 +1019,28 @@ export class CJSONRenderer extends ConvenienceRenderer { ", e", child_level.toString(), "->string, (", - cJSON.items!.cType, + cJSON.items?.cType, " *)0xDEADBEEF, sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, " *));" ); - } else if (cJSON.items!.cjsonType === "cJSON_String") { + } else if (cJSON.items?.cjsonType === "cJSON_String") { this.emitLine( "hashtable_add(x", child_level.toString(), ", e", child_level.toString(), "->string, strdup(", - cJSON.items!.getValue, + cJSON.items?.getValue, "(e", child_level.toString(), ")), sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, " *));" ); } else if ( - cJSON.items!.cjsonType === "cJSON_Object" || - cJSON.items!.cjsonType === "cJSON_Union" + cJSON.items?.cjsonType === "cJSON_Object" || + cJSON.items?.cjsonType === "cJSON_Union" ) { this.emitLine( "hashtable_add(x", @@ -1048,20 +1048,20 @@ export class CJSONRenderer extends ConvenienceRenderer { ", e", child_level.toString(), "->string, ", - cJSON.items!.getValue, + cJSON.items?.getValue, "(e", child_level.toString(), "), sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, " *));" ); } else { this.emitLine( - cJSON.items!.cType, + cJSON.items?.cType, " * tmp", level > 0 ? level.toString() : "", " = cJSON_malloc(sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, "));" ); this.emitBlock( @@ -1071,7 +1071,7 @@ export class CJSONRenderer extends ConvenienceRenderer { "* tmp", level > 0 ? level.toString() : "", " = ", - cJSON.items!.getValue, + cJSON.items?.getValue, "(e", child_level.toString(), ");" @@ -1084,7 +1084,7 @@ export class CJSONRenderer extends ConvenienceRenderer { "->string, tmp", level > 0 ? level.toString() : "", ", sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, " *));" ); } @@ -1092,7 +1092,7 @@ export class CJSONRenderer extends ConvenienceRenderer { } }; - if (cJSON.items!.isNullable) { + if (cJSON.items?.isNullable) { this.emitBlock( ["if (!cJSON_IsNull(e", child_level.toString(), "))"], () => { @@ -1185,7 +1185,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ); this.emitBlock(["if (NULL != j", child_level.toString(), ")"], () => { this.emitLine( - cJSON.items!.cType, + cJSON.items?.cType, " * x", child_level.toString(), " = list_get_head(x", @@ -1196,30 +1196,30 @@ export class CJSONRenderer extends ConvenienceRenderer { ); this.emitBlock(["while (NULL != x", child_level.toString(), ")"], () => { const add = (cJSON: TypeCJSON, child_level: number) => { - if (cJSON.items!.cjsonType === "cJSON_Array") { + if (cJSON.items?.cjsonType === "cJSON_Array") { /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Map") { + } else if (cJSON.items?.cjsonType === "cJSON_Map") { /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Invalid") { + } else if (cJSON.items?.cjsonType === "cJSON_Invalid") { /* Nothing to do */ - } else if (cJSON.items!.cjsonType === "cJSON_NULL") { + } else if (cJSON.items?.cjsonType === "cJSON_NULL") { this.emitLine( "cJSON_AddItemToArray(j", child_level.toString(), ", ", - cJSON.items!.createObject, + cJSON.items?.createObject, "());" ); } else if ( - cJSON.items!.cjsonType === "cJSON_String" || - cJSON.items!.cjsonType === "cJSON_Object" || - cJSON.items!.cjsonType === "cJSON_Union" + cJSON.items?.cjsonType === "cJSON_String" || + cJSON.items?.cjsonType === "cJSON_Object" || + cJSON.items?.cjsonType === "cJSON_Union" ) { this.emitLine( "cJSON_AddItemToArray(j", child_level.toString(), ", ", - cJSON.items!.createObject, + cJSON.items?.createObject, "(x", child_level.toString(), "));" @@ -1229,7 +1229,7 @@ export class CJSONRenderer extends ConvenienceRenderer { "cJSON_AddItemToArray(j", child_level.toString(), ", ", - cJSON.items!.createObject, + cJSON.items?.createObject, "(*x", child_level.toString(), "));" @@ -1237,7 +1237,7 @@ export class CJSONRenderer extends ConvenienceRenderer { } }; - if (cJSON.items!.isNullable) { + if (cJSON.items?.isNullable) { this.emitBlock( ["if ((void *)0xDEADBEEF != x", child_level.toString(), ")"], () => { @@ -1305,7 +1305,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ], () => { this.emitLine( - cJSON.items!.cType, + cJSON.items?.cType, " *x", child_level.toString(), " = hashtable_lookup(x", @@ -1319,13 +1319,13 @@ export class CJSONRenderer extends ConvenienceRenderer { "]);" ); const add = (cJSON: TypeCJSON, child_level: number) => { - if (cJSON.items!.cjsonType === "cJSON_Array") { + if (cJSON.items?.cjsonType === "cJSON_Array") { /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Map") { + } else if (cJSON.items?.cjsonType === "cJSON_Map") { /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Invalid") { + } else if (cJSON.items?.cjsonType === "cJSON_Invalid") { /* Nothing to do */ - } else if (cJSON.items!.cjsonType === "cJSON_NULL") { + } else if (cJSON.items?.cjsonType === "cJSON_NULL") { this.emitLine( cJSON.addToObject, "(j", @@ -1335,13 +1335,13 @@ export class CJSONRenderer extends ConvenienceRenderer { "[index", child_level.toString(), "], ", - cJSON.items!.createObject, + cJSON.items?.createObject, "());" ); } else if ( - cJSON.items!.cjsonType === "cJSON_String" || - cJSON.items!.cjsonType === "cJSON_Object" || - cJSON.items!.cjsonType === "cJSON_Union" + cJSON.items?.cjsonType === "cJSON_String" || + cJSON.items?.cjsonType === "cJSON_Object" || + cJSON.items?.cjsonType === "cJSON_Union" ) { this.emitLine( cJSON.addToObject, @@ -1352,7 +1352,7 @@ export class CJSONRenderer extends ConvenienceRenderer { "[index", child_level.toString(), "], ", - cJSON.items!.createObject, + cJSON.items?.createObject, "(x", child_level.toString(), "));" @@ -1367,7 +1367,7 @@ export class CJSONRenderer extends ConvenienceRenderer { "[index", child_level.toString(), "], ", - cJSON.items!.createObject, + cJSON.items?.createObject, "(*x", child_level.toString(), "));" @@ -1375,7 +1375,7 @@ export class CJSONRenderer extends ConvenienceRenderer { } }; - if (cJSON.items!.isNullable) { + if (cJSON.items?.isNullable) { this.emitBlock( [ "if ((void *)0xDEADBEEF != x", @@ -1450,7 +1450,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ], () => { this.emitLine( - cJSON.items!.cType, + cJSON.items?.cType, " * x", child_level.toString(), " = list_get_head(x", @@ -1460,22 +1460,22 @@ export class CJSONRenderer extends ConvenienceRenderer { ");" ); this.emitBlock(["while (NULL != x", child_level.toString(), ")"], () => { - if (cJSON.items!.cjsonType === "cJSON_Array") { + if (cJSON.items?.cjsonType === "cJSON_Array") { /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Map") { + } else if (cJSON.items?.cjsonType === "cJSON_Map") { /* Not supported */ } else if ( - cJSON.items!.cjsonType === "cJSON_Invalid" || - cJSON.items!.cjsonType === "cJSON_NULL" + cJSON.items?.cjsonType === "cJSON_Invalid" || + cJSON.items?.cjsonType === "cJSON_NULL" ) { /* Nothing to do */ } else { - if (cJSON.items!.isNullable) { + if (cJSON.items?.isNullable) { this.emitBlock( ["if ((void *)0xDEADBEEF != x", child_level.toString(), ")"], () => { this.emitLine( - cJSON.items!.deleteType, + cJSON.items?.deleteType, "(x", child_level.toString(), ");" @@ -1484,7 +1484,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ); } else { this.emitLine( - cJSON.items!.deleteType, + cJSON.items?.deleteType, "(x", child_level.toString(), ");" @@ -1551,7 +1551,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ], () => { this.emitLine( - cJSON.items!.cType, + cJSON.items?.cType, " *x", child_level.toString(), " = hashtable_lookup(x", @@ -1565,17 +1565,17 @@ export class CJSONRenderer extends ConvenienceRenderer { "]);" ); this.emitBlock(["if (NULL != x", child_level.toString(), ")"], () => { - if (cJSON.items!.cjsonType === "cJSON_Array") { + if (cJSON.items?.cjsonType === "cJSON_Array") { /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Map") { + } else if (cJSON.items?.cjsonType === "cJSON_Map") { /* Not supported */ } else if ( - cJSON.items!.cjsonType === "cJSON_Invalid" || - cJSON.items!.cjsonType === "cJSON_NULL" + cJSON.items?.cjsonType === "cJSON_Invalid" || + cJSON.items?.cjsonType === "cJSON_NULL" ) { /* Nothing to do */ } else { - if (cJSON.items!.isNullable) { + if (cJSON.items?.isNullable) { this.emitBlock( [ "if ((void *)0xDEADBEEF != x", @@ -1584,7 +1584,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ], () => { this.emitLine( - cJSON.items!.deleteType, + cJSON.items?.deleteType, "(x", child_level.toString(), ");" @@ -1593,7 +1593,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ); } else { this.emitLine( - cJSON.items!.deleteType, + cJSON.items?.deleteType, "(x", child_level.toString(), ");" @@ -1766,7 +1766,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ", x", child_level2.toString(), ", sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, " *));" ); } else if (cJSON.cjsonType === "cJSON_Map") { @@ -1905,7 +1905,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level: number, child_level: number ) => { - if (cJSON.items!.cjsonType === "cJSON_Array") { + if (cJSON.items?.cjsonType === "cJSON_Array") { if (type instanceof ArrayType) { const child_level2 = child_level + 1; recur(type.items, child_level); @@ -1915,61 +1915,61 @@ export class CJSONRenderer extends ConvenienceRenderer { ", x", child_level2.toString(), ", sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, " *));" ); } else { panic("Invalid type"); } - } else if (cJSON.items!.cjsonType === "cJSON_Map") { + } else if (cJSON.items?.cjsonType === "cJSON_Map") { /* Not supported */ } else if ( - cJSON.items!.cjsonType === "cJSON_Invalid" || - cJSON.items!.cjsonType === "cJSON_NULL" + cJSON.items?.cjsonType === "cJSON_Invalid" || + cJSON.items?.cjsonType === "cJSON_NULL" ) { this.emitLine( "list_add_tail(x", child_level.toString(), ", (", - cJSON.items!.cType, + cJSON.items?.cType, " *)0xDEADBEEF, sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, " *));" ); - } else if (cJSON.items!.cjsonType === "cJSON_String") { + } else if (cJSON.items?.cjsonType === "cJSON_String") { this.emitLine( "list_add_tail(x", child_level.toString(), ", strdup(", - cJSON.items!.getValue, + cJSON.items?.getValue, "(e", child_level.toString(), ")), sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, " *));" ); } else if ( - cJSON.items!.cjsonType === "cJSON_Object" || - cJSON.items!.cjsonType === "cJSON_Union" + cJSON.items?.cjsonType === "cJSON_Object" || + cJSON.items?.cjsonType === "cJSON_Union" ) { this.emitLine( "list_add_tail(x", child_level.toString(), ", ", - cJSON.items!.getValue, + cJSON.items?.getValue, "(e", child_level.toString(), "), sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, " *));" ); } else { this.emitLine( - cJSON.items!.cType, + cJSON.items?.cType, " * tmp", level > 0 ? level.toString() : "", " = cJSON_malloc(sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, "));" ); this.emitBlock( @@ -1983,7 +1983,7 @@ export class CJSONRenderer extends ConvenienceRenderer { "* tmp", level > 0 ? level.toString() : "", " = ", - cJSON.items!.getValue, + cJSON.items?.getValue, "(e", child_level.toString(), ");" @@ -1994,7 +1994,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ", tmp", level > 0 ? level.toString() : "", ", sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, " *));" ); } @@ -2002,7 +2002,7 @@ export class CJSONRenderer extends ConvenienceRenderer { } }; - if (cJSON.items!.isNullable) { + if (cJSON.items?.isNullable) { this.emitBlock( [ "if (!cJSON_IsNull(e", @@ -2071,7 +2071,7 @@ export class CJSONRenderer extends ConvenienceRenderer { level: number, child_level: number ) => { - if (cJSON.items!.cjsonType === "cJSON_Array") { + if (cJSON.items?.cjsonType === "cJSON_Array") { if (type instanceof MapType) { const child_level2 = child_level + 1; recur(type.values, child_level); @@ -2083,17 +2083,17 @@ export class CJSONRenderer extends ConvenienceRenderer { "->string, x", child_level2.toString(), ", sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, " *));" ); } else { panic("Invalid type"); } - } else if (cJSON.items!.cjsonType === "cJSON_Map") { + } else if (cJSON.items?.cjsonType === "cJSON_Map") { /* Not supported */ } else if ( - cJSON.items!.cjsonType === "cJSON_Invalid" || - cJSON.items!.cjsonType === "cJSON_NULL" + cJSON.items?.cjsonType === "cJSON_Invalid" || + cJSON.items?.cjsonType === "cJSON_NULL" ) { this.emitLine( "hashtable_add(x", @@ -2101,28 +2101,28 @@ export class CJSONRenderer extends ConvenienceRenderer { ", e", child_level.toString(), "->string, (", - cJSON.items!.cType, + cJSON.items?.cType, " *)0xDEADBEEF, sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, " *));" ); - } else if (cJSON.items!.cjsonType === "cJSON_String") { + } else if (cJSON.items?.cjsonType === "cJSON_String") { this.emitLine( "hashtable_add(x", child_level.toString(), ", e", child_level.toString(), "->string, strdup(", - cJSON.items!.getValue, + cJSON.items?.getValue, "(e", child_level.toString(), ")), sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, " *));" ); } else if ( - cJSON.items!.cjsonType === "cJSON_Object" || - cJSON.items!.cjsonType === "cJSON_Union" + cJSON.items?.cjsonType === "cJSON_Object" || + cJSON.items?.cjsonType === "cJSON_Union" ) { this.emitLine( "hashtable_add(x", @@ -2130,20 +2130,20 @@ export class CJSONRenderer extends ConvenienceRenderer { ", e", child_level.toString(), "->string, ", - cJSON.items!.getValue, + cJSON.items?.getValue, "(e", child_level.toString(), "), sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, " *));" ); } else { this.emitLine( - cJSON.items!.cType, + cJSON.items?.cType, " * tmp", level > 0 ? level.toString() : "", " = cJSON_malloc(sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, "));" ); this.emitBlock( @@ -2157,7 +2157,7 @@ export class CJSONRenderer extends ConvenienceRenderer { "* tmp", level > 0 ? level.toString() : "", " = ", - cJSON.items!.getValue, + cJSON.items?.getValue, "(e", child_level.toString(), ");" @@ -2170,7 +2170,7 @@ export class CJSONRenderer extends ConvenienceRenderer { "->string, tmp", level > 0 ? level.toString() : "", ", sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, " *));" ); } @@ -2178,7 +2178,7 @@ export class CJSONRenderer extends ConvenienceRenderer { } }; - if (cJSON.items!.isNullable) { + if (cJSON.items?.isNullable) { this.emitBlock( [ "if (!cJSON_IsNull(e", @@ -2478,7 +2478,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ); this.emitBlock(["if (NULL != j", child_level.toString(), ")"], () => { this.emitLine( - cJSON.items!.cType, + cJSON.items?.cType, " * x", child_level.toString(), " = list_get_head(x", @@ -2495,7 +2495,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON: TypeCJSON, child_level: number ) => { - if (cJSON.items!.cjsonType === "cJSON_Array") { + if (cJSON.items?.cjsonType === "cJSON_Array") { if (type instanceof ArrayType) { const child_level2 = child_level + 1; recur(type.items, child_level); @@ -2509,28 +2509,28 @@ export class CJSONRenderer extends ConvenienceRenderer { } else { panic("Invalid type"); } - } else if (cJSON.items!.cjsonType === "cJSON_Map") { + } else if (cJSON.items?.cjsonType === "cJSON_Map") { /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Invalid") { + } else if (cJSON.items?.cjsonType === "cJSON_Invalid") { /* Nothing to do */ - } else if (cJSON.items!.cjsonType === "cJSON_NULL") { + } else if (cJSON.items?.cjsonType === "cJSON_NULL") { this.emitLine( "cJSON_AddItemToArray(j", child_level.toString(), ", ", - cJSON.items!.createObject, + cJSON.items?.createObject, "());" ); } else if ( - cJSON.items!.cjsonType === "cJSON_String" || - cJSON.items!.cjsonType === "cJSON_Object" || - cJSON.items!.cjsonType === "cJSON_Union" + cJSON.items?.cjsonType === "cJSON_String" || + cJSON.items?.cjsonType === "cJSON_Object" || + cJSON.items?.cjsonType === "cJSON_Union" ) { this.emitLine( "cJSON_AddItemToArray(j", child_level.toString(), ", ", - cJSON.items!.createObject, + cJSON.items?.createObject, "(x", child_level.toString(), "));" @@ -2540,7 +2540,7 @@ export class CJSONRenderer extends ConvenienceRenderer { "cJSON_AddItemToArray(j", child_level.toString(), ", ", - cJSON.items!.createObject, + cJSON.items?.createObject, "(*x", child_level.toString(), "));" @@ -2548,7 +2548,7 @@ export class CJSONRenderer extends ConvenienceRenderer { } }; - if (cJSON.items!.isNullable) { + if (cJSON.items?.isNullable) { this.emitBlock( [ "if ((void *)0xDEADBEEF != x", @@ -2626,7 +2626,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ], () => { this.emitLine( - cJSON.items!.cType, + cJSON.items?.cType, " *x", child_level.toString(), " = hashtable_lookup(x", @@ -2644,7 +2644,7 @@ export class CJSONRenderer extends ConvenienceRenderer { cJSON: TypeCJSON, child_level: number ) => { - if (cJSON.items!.cjsonType === "cJSON_Array") { + if (cJSON.items?.cjsonType === "cJSON_Array") { if (type instanceof MapType) { const child_level2 = child_level + 1; recur(type.values, child_level); @@ -2664,15 +2664,15 @@ export class CJSONRenderer extends ConvenienceRenderer { panic("Invalid type"); } } else if ( - cJSON.items!.cjsonType === "cJSON_Map" + cJSON.items?.cjsonType === "cJSON_Map" ) { /* Not supported */ } else if ( - cJSON.items!.cjsonType === "cJSON_Invalid" + cJSON.items?.cjsonType === "cJSON_Invalid" ) { /* Nothing to do */ } else if ( - cJSON.items!.cjsonType === "cJSON_NULL" + cJSON.items?.cjsonType === "cJSON_NULL" ) { this.emitLine( cJSON.addToObject, @@ -2683,13 +2683,13 @@ export class CJSONRenderer extends ConvenienceRenderer { "[index", child_level.toString(), "], ", - cJSON.items!.createObject, + cJSON.items?.createObject, "());" ); } else if ( - cJSON.items!.cjsonType === "cJSON_String" || - cJSON.items!.cjsonType === "cJSON_Object" || - cJSON.items!.cjsonType === "cJSON_Union" + cJSON.items?.cjsonType === "cJSON_String" || + cJSON.items?.cjsonType === "cJSON_Object" || + cJSON.items?.cjsonType === "cJSON_Union" ) { this.emitLine( cJSON.addToObject, @@ -2700,7 +2700,7 @@ export class CJSONRenderer extends ConvenienceRenderer { "[index", child_level.toString(), "], ", - cJSON.items!.createObject, + cJSON.items?.createObject, "(x", child_level.toString(), "));" @@ -2715,7 +2715,7 @@ export class CJSONRenderer extends ConvenienceRenderer { "[index", child_level.toString(), "], ", - cJSON.items!.createObject, + cJSON.items?.createObject, "(*x", child_level.toString(), "));" @@ -2723,7 +2723,7 @@ export class CJSONRenderer extends ConvenienceRenderer { } }; - if (cJSON.items!.isNullable) { + if (cJSON.items?.isNullable) { this.emitBlock( [ "if ((void *)0xDEADBEEF != x", @@ -3015,7 +3015,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ["if (NULL != x", level > 0 ? level.toString() : "", "->", name, ")"], () => { this.emitLine( - cJSON.items!.cType, + cJSON.items?.cType, " * x", child_level.toString(), " = list_get_head(x", @@ -3025,11 +3025,11 @@ export class CJSONRenderer extends ConvenienceRenderer { ");" ); this.emitBlock(["while (NULL != x", child_level.toString(), ")"], () => { - if (cJSON.items!.cjsonType === "cJSON_Array") { + if (cJSON.items?.cjsonType === "cJSON_Array") { if (property.type instanceof ArrayType) { recur(property.type.items, child_level); this.emitLine( - cJSON.items!.deleteType, + cJSON.items?.deleteType, "(x", child_level.toString(), ");" @@ -3037,20 +3037,20 @@ export class CJSONRenderer extends ConvenienceRenderer { } else { panic("Invalid type"); } - } else if (cJSON.items!.cjsonType === "cJSON_Map") { + } else if (cJSON.items?.cjsonType === "cJSON_Map") { /* Not supported */ } else if ( - cJSON.items!.cjsonType === "cJSON_Invalid" || - cJSON.items!.cjsonType === "cJSON_NULL" + cJSON.items?.cjsonType === "cJSON_Invalid" || + cJSON.items?.cjsonType === "cJSON_NULL" ) { /* Nothing to do */ } else { - if (cJSON.items!.isNullable) { + if (cJSON.items?.isNullable) { this.emitBlock( ["if ((void *)0xDEADBEEF != x", child_level.toString(), ")"], () => { this.emitLine( - cJSON.items!.deleteType, + cJSON.items?.deleteType, "(x", child_level.toString(), ");" @@ -3059,7 +3059,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ); } else { this.emitLine( - cJSON.items!.deleteType, + cJSON.items?.deleteType, "(x", child_level.toString(), ");" @@ -3119,7 +3119,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ], () => { this.emitLine( - cJSON.items!.cType, + cJSON.items?.cType, " *x", child_level.toString(), " = hashtable_lookup(x", @@ -3135,11 +3135,11 @@ export class CJSONRenderer extends ConvenienceRenderer { this.emitBlock( ["if (NULL != x", child_level.toString(), ")"], () => { - if (cJSON.items!.cjsonType === "cJSON_Array") { + if (cJSON.items?.cjsonType === "cJSON_Array") { if (property.type instanceof MapType) { recur(property.type.values, child_level); this.emitLine( - cJSON.items!.deleteType, + cJSON.items?.deleteType, "(x", child_level.toString(), ");" @@ -3147,15 +3147,15 @@ export class CJSONRenderer extends ConvenienceRenderer { } else { panic("Invalid type"); } - } else if (cJSON.items!.cjsonType === "cJSON_Map") { + } else if (cJSON.items?.cjsonType === "cJSON_Map") { /* Not supported */ } else if ( - cJSON.items!.cjsonType === "cJSON_Invalid" || - cJSON.items!.cjsonType === "cJSON_NULL" + cJSON.items?.cjsonType === "cJSON_Invalid" || + cJSON.items?.cjsonType === "cJSON_NULL" ) { /* Nothing to do */ } else { - if (cJSON.items!.isNullable) { + if (cJSON.items?.isNullable) { this.emitBlock( [ "if ((void *)0xDEADBEEF != x", @@ -3164,7 +3164,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ], () => { this.emitLine( - cJSON.items!.deleteType, + cJSON.items?.deleteType, "(x", child_level.toString(), ");" @@ -3173,7 +3173,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ); } else { this.emitLine( - cJSON.items!.deleteType, + cJSON.items?.deleteType, "(x", child_level.toString(), ");" @@ -3350,41 +3350,41 @@ export class CJSONRenderer extends ConvenienceRenderer { this.emitLine("cJSON * e = NULL;"); this.emitBlock(["cJSON_ArrayForEach(e, j)"], () => { const add = (cJSON: TypeCJSON) => { - if (cJSON.items!.cjsonType === "cJSON_Array") { + if (cJSON.items?.cjsonType === "cJSON_Array") { /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Map") { + } else if (cJSON.items?.cjsonType === "cJSON_Map") { /* Not supported */ } else if ( - cJSON.items!.cjsonType === "cJSON_Invalid" || - cJSON.items!.cjsonType === "cJSON_NULL" + cJSON.items?.cjsonType === "cJSON_Invalid" || + cJSON.items?.cjsonType === "cJSON_NULL" ) { this.emitLine( "list_add_tail(x->value, (", - cJSON.items!.cType, + cJSON.items?.cType, " *)0xDEADBEAF, sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, " *));" ); - } else if (cJSON.items!.cjsonType === "cJSON_String") { + } else if (cJSON.items?.cjsonType === "cJSON_String") { this.emitLine( "list_add_tail(x->value, strdup(", - cJSON.items!.getValue, + cJSON.items?.getValue, "(e)), sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, " *));" ); } else { this.emitLine( "list_add_tail(x->value, ", - cJSON.items!.getValue, + cJSON.items?.getValue, "(e), sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, " *));" ); } }; - if (cJSON.items!.isNullable) { + if (cJSON.items?.isNullable) { this.emitBlock(["if (!cJSON_IsNull(e))"], () => { add(cJSON); }); @@ -3404,41 +3404,41 @@ export class CJSONRenderer extends ConvenienceRenderer { this.emitLine("cJSON * e = NULL;"); this.emitBlock(["cJSON_ArrayForEach(e, j)"], () => { const add = (cJSON: TypeCJSON) => { - if (cJSON.items!.cjsonType === "cJSON_Array") { + if (cJSON.items?.cjsonType === "cJSON_Array") { /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Map") { + } else if (cJSON.items?.cjsonType === "cJSON_Map") { /* Not supported */ } else if ( - cJSON.items!.cjsonType === "cJSON_Invalid" || - cJSON.items!.cjsonType === "cJSON_NULL" + cJSON.items?.cjsonType === "cJSON_Invalid" || + cJSON.items?.cjsonType === "cJSON_NULL" ) { this.emitLine( "hashtable_add(x->value, e->string, (", - cJSON.items!.cType, + cJSON.items?.cType, " *)0xDEADBEEF, sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, " *));" ); - } else if (cJSON.items!.cjsonType === "cJSON_String") { + } else if (cJSON.items?.cjsonType === "cJSON_String") { this.emitLine( "hashtable_add(x->value, e->string, strdup(", - cJSON.items!.getValue, + cJSON.items?.getValue, "(e)), sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, " *));" ); } else { this.emitLine( "hashtable_add(x->value, e->string, ", - cJSON.items!.getValue, + cJSON.items?.getValue, "(e), sizeof(", - cJSON.items!.cType, + cJSON.items?.cType, " *));" ); } }; - if (cJSON.items!.isNullable) { + if (cJSON.items?.isNullable) { this.emitBlock(["if (!cJSON_IsNull(e))"], () => { add(cJSON); }); @@ -3479,41 +3479,41 @@ export class CJSONRenderer extends ConvenienceRenderer { this.emitBlock(["if (NULL != x->value)"], () => { this.emitLine("j = ", cJSON.createObject, "();"); this.emitBlock(["if (NULL != j)"], () => { - this.emitLine(cJSON.items!.cType, " * x1 = list_get_head(x->value);"); + this.emitLine(cJSON.items?.cType, " * x1 = list_get_head(x->value);"); this.emitBlock(["while (NULL != x1)"], () => { const add = (cJSON: TypeCJSON) => { - if (cJSON.items!.cjsonType === "cJSON_Array") { + if (cJSON.items?.cjsonType === "cJSON_Array") { /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Map") { + } else if (cJSON.items?.cjsonType === "cJSON_Map") { /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Invalid") { + } else if (cJSON.items?.cjsonType === "cJSON_Invalid") { /* Nothing to do */ - } else if (cJSON.items!.cjsonType === "cJSON_NULL") { + } else if (cJSON.items?.cjsonType === "cJSON_NULL") { this.emitLine( "cJSON_AddItemToArray(j, ", - cJSON.items!.createObject, + cJSON.items?.createObject, "());" ); } else if ( - cJSON.items!.cjsonType === "cJSON_String" || - cJSON.items!.cjsonType === "cJSON_Object" || - cJSON.items!.cjsonType === "cJSON_Union" + cJSON.items?.cjsonType === "cJSON_String" || + cJSON.items?.cjsonType === "cJSON_Object" || + cJSON.items?.cjsonType === "cJSON_Union" ) { this.emitLine( "cJSON_AddItemToArray(j, ", - cJSON.items!.createObject, + cJSON.items?.createObject, "(x1));" ); } else { this.emitLine( "cJSON_AddItemToArray(j, ", - cJSON.items!.createObject, + cJSON.items?.createObject, "(*x1));" ); } }; - if (cJSON.items!.isNullable) { + if (cJSON.items?.isNullable) { this.emitBlock(["if ((void *)0xDEADBEEF != x1)"], () => { add(cJSON); }); @@ -3537,45 +3537,45 @@ export class CJSONRenderer extends ConvenienceRenderer { this.emitBlock(["if (NULL != keys)"], () => { this.emitBlock(["for (size_t index = 0; index < count; index++)"], () => { this.emitLine( - cJSON.items!.cType, + cJSON.items?.cType, " *x2 = hashtable_lookup(x->value, keys[index]);" ); const add = (cJSON: TypeCJSON) => { - if (cJSON.items!.cjsonType === "cJSON_Array") { + if (cJSON.items?.cjsonType === "cJSON_Array") { /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Map") { + } else if (cJSON.items?.cjsonType === "cJSON_Map") { /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Invalid") { + } else if (cJSON.items?.cjsonType === "cJSON_Invalid") { /* Nothing to do */ - } else if (cJSON.items!.cjsonType === "cJSON_NULL") { + } else if (cJSON.items?.cjsonType === "cJSON_NULL") { this.emitLine( cJSON.addToObject, "(j, keys[index], ", - cJSON.items!.createObject, + cJSON.items?.createObject, "());" ); } else if ( - cJSON.items!.cjsonType === "cJSON_String" || - cJSON.items!.cjsonType === "cJSON_Object" || - cJSON.items!.cjsonType === "cJSON_Union" + cJSON.items?.cjsonType === "cJSON_String" || + cJSON.items?.cjsonType === "cJSON_Object" || + cJSON.items?.cjsonType === "cJSON_Union" ) { this.emitLine( cJSON.addToObject, "(j, keys[index], ", - cJSON.items!.createObject, + cJSON.items?.createObject, "(x2));" ); } else { this.emitLine( cJSON.addToObject, "(j, keys[index], ", - cJSON.items!.createObject, + cJSON.items?.createObject, "(*x2));" ); } }; - if (cJSON.items!.isNullable) { + if (cJSON.items?.isNullable) { this.emitBlock(["if ((void *)0xDEADBEEF != x2)"], () => { add(cJSON); }); @@ -3626,14 +3626,14 @@ export class CJSONRenderer extends ConvenienceRenderer { const cJSON = this.quicktypeTypeToCJSON(type, false); if (cJSON.cjsonType === "cJSON_Array" && cJSON.items !== undefined) { this.emitBlock(["if (NULL != x->value)"], () => { - this.emitLine(cJSON.items!.cType, " * x1 = list_get_head(x->value);"); + this.emitLine(cJSON.items?.cType, " * x1 = list_get_head(x->value);"); this.emitBlock(["while (NULL != x1)"], () => { - if (cJSON.items!.isNullable) { + if (cJSON.items?.isNullable) { this.emitBlock(["if ((void *)0xDEADBEEF != x1)"], () => { - this.emitLine(cJSON.items!.deleteType, "(x1);"); + this.emitLine(cJSON.items?.deleteType, "(x1);"); }); } else { - this.emitLine(cJSON.items!.deleteType, "(x1);"); + this.emitLine(cJSON.items?.deleteType, "(x1);"); } this.emitLine("x1 = list_get_next(x->value);"); @@ -3646,14 +3646,14 @@ export class CJSONRenderer extends ConvenienceRenderer { this.emitLine("size_t count = hashtable_get_keys(x->value, &keys);"); this.emitBlock(["if (NULL != keys)"], () => { this.emitBlock(["for (size_t index = 0; index < count; index++)"], () => { - this.emitLine(cJSON.items!.cType, " *x2 = hashtable_lookup(x->value, keys[index]);"); + this.emitLine(cJSON.items?.cType, " *x2 = hashtable_lookup(x->value, keys[index]);"); this.emitBlock(["if (NULL != x2)"], () => { - if (cJSON.items!.isNullable) { - this.emitBlock(["if ((", cJSON.items!.cType, " *)0xDEADBEEF != x2)"], () => { - this.emitLine(cJSON.items!.deleteType, "(x2);"); + if (cJSON.items?.isNullable) { + this.emitBlock(["if ((", cJSON.items?.cType, " *)0xDEADBEEF != x2)"], () => { + this.emitLine(cJSON.items?.deleteType, "(x2);"); }); } else { - this.emitLine(cJSON.items!.deleteType, "(x2);"); + this.emitLine(cJSON.items?.deleteType, "(x2);"); } }); }); diff --git a/packages/quicktype-core/src/language/Objective-C.ts b/packages/quicktype-core/src/language/Objective-C.ts index e97381a00..2dc5612f1 100644 --- a/packages/quicktype-core/src/language/Objective-C.ts +++ b/packages/quicktype-core/src/language/Objective-C.ts @@ -225,7 +225,7 @@ function splitExtension(filename: string): [string, string] { const i = filename.lastIndexOf("."); const extension = i !== -1 ? filename.split(".").pop() : "m"; filename = i !== -1 ? filename.slice(0, i) : filename; - return [filename, extension === undefined ? "m" : extension]; + return [filename, extension ?? "m"]; } export class ObjectiveCRenderer extends ConvenienceRenderer { diff --git a/packages/quicktype-graphql-input/src/index.ts b/packages/quicktype-graphql-input/src/index.ts index 97bcb91ae..c2cc29cbb 100644 --- a/packages/quicktype-graphql-input/src/index.ts +++ b/packages/quicktype-graphql-input/src/index.ts @@ -310,7 +310,7 @@ class GQLQuery { return panic("Object, interface, or union type doesn't have a name."); } - const nameOrOverride = overrideName || gqlType.name; + const nameOrOverride = overrideName ?? gqlType.name; const properties = new Map(); let selections = expandSelectionSet(selectionSet, gqlType, false); for (;;) { diff --git a/src/index.ts b/src/index.ts index 710b5cc9e..78c22b445 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,7 +12,8 @@ import { type SerializedRenderResult, type TargetLanguage, type OptionDefinition, - type JSONSourceData} from "quicktype-core"; + type JSONSourceData +} from "quicktype-core"; import { getTargetLanguage, quicktypeMultiFile, @@ -38,7 +39,7 @@ import { getStream, readableFromFileOrURL, readFromFileOrURL, - FetchingJSONSchemaStore, + FetchingJSONSchemaStore } from "quicktype-core"; import { schemaForTypeScriptSources } from "quicktype-typescript-input"; import { GraphQLInput } from "quicktype-graphql-input"; @@ -89,22 +90,22 @@ export interface CLIOptions { const defaultDefaultTargetLanguageName = "go"; -async function sourceFromFileOrUrlArray ( +async function sourceFromFileOrUrlArray( name: string, filesOrUrls: string[], - httpHeaders?: string[], + httpHeaders?: string[] ): Promise { const samples = await Promise.all(filesOrUrls.map(async file => await readableFromFileOrURL(file, httpHeaders))); return { kind: "json", name, samples }; } -function typeNameFromFilename (filename: string): string { +function typeNameFromFilename(filename: string): string { const name = path.basename(filename); return name.substring(0, name.lastIndexOf(".")); } -async function samplesFromDirectory (dataDir: string, httpHeaders?: string[]): Promise { - async function readFilesOrURLsInDirectory (d: string): Promise { +async function samplesFromDirectory(dataDir: string, httpHeaders?: string[]): Promise { + async function readFilesOrURLsInDirectory(d: string): Promise { const files = fs .readdirSync(d) .map(x => path.join(d, x)) @@ -129,17 +130,17 @@ async function samplesFromDirectory (dataDir: string, httpHeaders?: string[]): P sourcesInDir.push({ kind: "json", name, - samples: [await readableFromFileOrURL(fileOrUrl, httpHeaders)], + samples: [await readableFromFileOrURL(fileOrUrl, httpHeaders)] }); } else if (file.endsWith(".schema")) { sourcesInDir.push({ kind: "schema", name, - uris: [fileOrUrl], + uris: [fileOrUrl] }); } else if (file.endsWith(".gqlschema")) { messageAssert(graphQLSchema === undefined, "DriverMoreThanOneGraphQLSchemaInDir", { - dir: dataDir, + dir: dataDir }); graphQLSchema = await readableFromFileOrURL(fileOrUrl, httpHeaders); graphQLSchemaFileName = fileOrUrl; @@ -148,7 +149,7 @@ async function samplesFromDirectory (dataDir: string, httpHeaders?: string[]): P kind: "graphql", name, schema: undefined, - query: await getStream(await readableFromFileOrURL(fileOrUrl, httpHeaders)), + query: await getStream(await readableFromFileOrURL(fileOrUrl, httpHeaders)) }); } } @@ -207,7 +208,7 @@ async function samplesFromDirectory (dataDir: string, httpHeaders?: string[]): P sources.push({ kind: "json", name: path.basename(dir), - samples: jsonSamples, + samples: jsonSamples }); } @@ -218,7 +219,7 @@ async function samplesFromDirectory (dataDir: string, httpHeaders?: string[]): P return sources; } -function inferLang (options: Partial, defaultLanguage: string): string { +function inferLang(options: Partial, defaultLanguage: string): string { // Output file extension determines the language if language is undefined if (options.out !== undefined) { let extension = path.extname(options.out); @@ -232,7 +233,7 @@ function inferLang (options: Partial, defaultLanguage: string): stri return defaultLanguage; } -function inferTopLevel (options: Partial): string { +function inferTopLevel(options: Partial): string { // Output file name determines the top-level if undefined if (options.out !== undefined) { let extension = path.extname(options.out); @@ -251,7 +252,7 @@ function inferTopLevel (options: Partial): string { return "TopLevel"; } -function inferCLIOptions (opts: Partial, targetLanguage: TargetLanguage | undefined): CLIOptions { +function inferCLIOptions(opts: Partial, targetLanguage: TargetLanguage | undefined): CLIOptions { let srcLang = opts.srcLang; if (opts.graphqlSchema !== undefined || opts.graphqlIntrospect !== undefined) { messageAssert(srcLang === undefined || srcLang === "graphql", "DriverSourceLangMustBeGraphQL", {}); @@ -267,7 +268,7 @@ function inferCLIOptions (opts: Partial, targetLanguage: TargetLangu if (targetLanguage !== undefined) { language = targetLanguage; } else { - const languageName = opts.lang !== undefined ? opts.lang : inferLang(opts, defaultDefaultTargetLanguageName); + const languageName = opts.lang ?? inferLang(opts, defaultDefaultTargetLanguageName); const maybeLanguage = languageNamed(languageName); if (maybeLanguage === undefined) { return messageError("DriverUnknownOutputLanguage", { lang: languageName }); @@ -277,27 +278,27 @@ function inferCLIOptions (opts: Partial, targetLanguage: TargetLangu } const options: CLIOptions = { - src: opts.src || [], + src: opts.src ?? [], srcUrls: opts.srcUrls, srcLang: srcLang, lang: language.displayName, - topLevel: opts.topLevel || inferTopLevel(opts), + topLevel: opts.topLevel ?? inferTopLevel(opts), noRender: !!opts.noRender, alphabetizeProperties: !!opts.alphabetizeProperties, allPropertiesOptional: !!opts.allPropertiesOptional, - rendererOptions: opts.rendererOptions || {}, - help: opts.help || false, - quiet: opts.quiet || false, - version: opts.version || false, + rendererOptions: opts.rendererOptions ?? {}, + help: opts.help ?? false, + quiet: opts.quiet ?? false, + version: opts.version ?? false, out: opts.out, buildMarkovChain: opts.buildMarkovChain, - additionalSchema: opts.additionalSchema || [], + additionalSchema: opts.additionalSchema ?? [], graphqlSchema: opts.graphqlSchema, graphqlIntrospect: opts.graphqlIntrospect, httpMethod: opts.httpMethod, httpHeader: opts.httpHeader, debug: opts.debug, - telemetry: opts.telemetry, + telemetry: opts.telemetry }; for (const flagName of inferenceFlagNames) { const cliName = negatedInferenceFlagName(flagName); @@ -307,12 +308,12 @@ function inferCLIOptions (opts: Partial, targetLanguage: TargetLangu return options; } -function makeLangTypeLabel (targetLanguages: TargetLanguage[]): string { +function makeLangTypeLabel(targetLanguages: TargetLanguage[]): string { assert(targetLanguages.length > 0, "Must have at least one target language"); return targetLanguages.map(r => _.minBy(r.names, s => s.length)).join("|"); } -function negatedInferenceFlagName (name: string): string { +function negatedInferenceFlagName(name: string): string { const prefix = "infer"; if (name.startsWith(prefix)) { name = name.slice(prefix.length); @@ -321,41 +322,41 @@ function negatedInferenceFlagName (name: string): string { return "no" + capitalize(name); } -function dashedFromCamelCase (name: string): string { +function dashedFromCamelCase(name: string): string { return splitIntoWords(name) .map(w => w.word.toLowerCase()) .join("-"); } -function makeOptionDefinitions (targetLanguages: TargetLanguage[]): OptionDefinition[] { +function makeOptionDefinitions(targetLanguages: TargetLanguage[]): OptionDefinition[] { const beforeLang: OptionDefinition[] = [ { name: "out", alias: "o", type: String, typeLabel: "FILE", - description: "The output file. Determines --lang and --top-level.", + description: "The output file. Determines --lang and --top-level." }, { name: "top-level", alias: "t", type: String, typeLabel: "NAME", - description: "The name for the top level type.", - }, + description: "The name for the top level type." + } ]; const lang: OptionDefinition[] = targetLanguages.length < 2 ? [] : [ - { - name: "lang", - alias: "l", - type: String, - typeLabel: "LANG", - description: "The target language.", - }, - ]; + { + name: "lang", + alias: "l", + type: String, + typeLabel: "LANG", + description: "The target language." + } + ]; const afterLang: OptionDefinition[] = [ { name: "src-lang", @@ -363,7 +364,7 @@ function makeOptionDefinitions (targetLanguages: TargetLanguage[]): OptionDefini type: String, defaultValue: undefined, typeLabel: "SRC_LANG", - description: "The source language (default is json).", + description: "The source language (default is json)." }, { name: "src", @@ -371,49 +372,49 @@ function makeOptionDefinitions (targetLanguages: TargetLanguage[]): OptionDefini multiple: true, defaultOption: true, typeLabel: "FILE|URL|DIRECTORY", - description: "The file, url, or data directory to type.", + description: "The file, url, or data directory to type." }, { name: "src-urls", type: String, typeLabel: "FILE", - description: "Tracery grammar describing URLs to crawl.", - }, + description: "Tracery grammar describing URLs to crawl." + } ]; const inference: OptionDefinition[] = Array.from( mapMap(mapFromObject(inferenceFlags), (flag, name) => { return { name: dashedFromCamelCase(negatedInferenceFlagName(name)), type: Boolean, - description: flag.negationDescription + ".", + description: flag.negationDescription + "." }; - }).values(), + }).values() ); const afterInference: OptionDefinition[] = [ { name: "graphql-schema", type: String, typeLabel: "FILE", - description: "GraphQL introspection file.", + description: "GraphQL introspection file." }, { name: "graphql-introspect", type: String, typeLabel: "URL", - description: "Introspect GraphQL schema from a server.", + description: "Introspect GraphQL schema from a server." }, { name: "http-method", type: String, typeLabel: "METHOD", - description: "HTTP method to use for the GraphQL introspection query.", + description: "HTTP method to use for the GraphQL introspection query." }, { name: "http-header", type: String, multiple: true, typeLabel: "HEADER", - description: "Header(s) to attach to all HTTP requests, including the GraphQL introspection query.", + description: "Header(s) to attach to all HTTP requests, including the GraphQL introspection query." }, { name: "additional-schema", @@ -421,66 +422,66 @@ function makeOptionDefinitions (targetLanguages: TargetLanguage[]): OptionDefini type: String, multiple: true, typeLabel: "FILE", - description: "Register the $id's of additional JSON Schema files.", + description: "Register the $id's of additional JSON Schema files." }, { name: "no-render", type: Boolean, - description: "Don't render output.", + description: "Don't render output." }, { name: "alphabetize-properties", type: Boolean, - description: "Alphabetize order of class properties.", + description: "Alphabetize order of class properties." }, { name: "all-properties-optional", type: Boolean, - description: "Make all class properties optional.", + description: "Make all class properties optional." }, { name: "build-markov-chain", type: String, typeLabel: "FILE", - description: "Markov chain corpus filename.", + description: "Markov chain corpus filename." }, { name: "quiet", type: Boolean, - description: "Don't show issues in the generated code.", + description: "Don't show issues in the generated code." }, { name: "debug", type: String, typeLabel: "OPTIONS or all", description: - "Comma separated debug options: print-graph, print-reconstitution, print-gather-names, print-transformations, print-schema-resolving, print-times, provenance", + "Comma separated debug options: print-graph, print-reconstitution, print-gather-names, print-transformations, print-schema-resolving, print-times, provenance" }, { name: "telemetry", type: String, typeLabel: "enable|disable", - description: "Enable anonymous telemetry to help improve quicktype", + description: "Enable anonymous telemetry to help improve quicktype" }, { name: "help", alias: "h", type: Boolean, - description: "Get some help.", + description: "Get some help." }, { name: "version", alias: "v", type: Boolean, - description: "Display the version of quicktype", - }, + description: "Display the version of quicktype" + } ]; return beforeLang.concat(lang, afterLang, inference, afterInference); } interface ColumnDefinition { name: string; - padding?: { left: string, right: string, }; + padding?: { left: string; right: string }; width?: number; } @@ -500,16 +501,16 @@ const tableOptionsForOptions: TableOptions = { columns: [ { name: "option", - width: 60, + width: 60 }, { name: "description", - width: 60, - }, - ], + width: 60 + } + ] }; -function makeSectionsBeforeRenderers (targetLanguages: TargetLanguage[]): UsageSection[] { +function makeSectionsBeforeRenderers(targetLanguages: TargetLanguage[]): UsageSection[] { const langDisplayNames = targetLanguages.map(r => r.displayName).join(", "); return [ @@ -517,24 +518,24 @@ function makeSectionsBeforeRenderers (targetLanguages: TargetLanguage[]): UsageS header: "Synopsis", content: [ `$ quicktype [${chalk.bold("--lang")} LANG] [${chalk.bold("--src-lang")} SRC_LANG] [${chalk.bold( - "--out", + "--out" )} FILE] FILE|URL ...`, "", ` LANG ... ${makeLangTypeLabel(targetLanguages)}`, "", - "SRC_LANG ... json|schema|graphql|postman|typescript", - ], + "SRC_LANG ... json|schema|graphql|postman|typescript" + ] }, { header: "Description", - content: `Given JSON sample data, quicktype outputs code for working with that data in ${langDisplayNames}.`, + content: `Given JSON sample data, quicktype outputs code for working with that data in ${langDisplayNames}.` }, { header: "Options", optionList: makeOptionDefinitions(targetLanguages), hide: ["no-render", "build-markov-chain"], - tableOptions: tableOptionsForOptions, - }, + tableOptions: tableOptionsForOptions + } ]; } @@ -551,21 +552,21 @@ const sectionsAfterRenderers: UsageSection[] = [ + Bar - bar-sample-1.json - bar-sample-2.json - - Baz.url`, + - Baz.url` ), "$ quicktype -l go samples", "", chalk.dim("Generate JSON Schema, then TypeScript"), "$ quicktype -o schema.json https://blockchain.info/latestblock", - "$ quicktype -o bitcoin.ts --src-lang schema schema.json", - ], + "$ quicktype -o bitcoin.ts --src-lang schema schema.json" + ] }, { - content: `Learn more at ${chalk.bold("quicktype.io")}`, - }, + content: `Learn more at ${chalk.bold("quicktype.io")}` + } ]; -export function parseCLIOptions (argv: string[], targetLanguage?: TargetLanguage): CLIOptions { +export function parseCLIOptions(argv: string[], targetLanguage?: TargetLanguage): CLIOptions { if (argv.length === 0) { return inferCLIOptions({ help: true }, targetLanguage); } @@ -592,8 +593,8 @@ export function parseCLIOptions (argv: string[], targetLanguage?: TargetLanguage // Parse the options in argv and split them into global options and renderer options, // according to each option definition's `renderer` field. If `partial` is false this // will throw if it encounters an unknown option. -function parseOptions (definitions: OptionDefinition[], argv: string[], partial: boolean): Partial { - let opts: { [key: string]: any, }; +function parseOptions(definitions: OptionDefinition[], argv: string[], partial: boolean): Partial { + let opts: { [key: string]: any }; try { opts = commandLineArgs(definitions, { argv, partial }); } catch (e) { @@ -604,12 +605,12 @@ function parseOptions (definitions: OptionDefinition[], argv: string[], partial: for (const k of Object.keys(opts)) { if (opts[k] === null) { return messageError("DriverCLIOptionParsingFailed", { - message: `Missing value for command line option "${k}"`, + message: `Missing value for command line option "${k}"` }); } } - const options: { [key: string]: any, rendererOptions: RendererOptions, } = { rendererOptions: {} }; + const options: { [key: string]: any; rendererOptions: RendererOptions } = { rendererOptions: {} }; for (const o of definitions) { if (!hasOwnProperty(opts, o.name)) continue; const v = opts[o.name] as string; @@ -623,7 +624,7 @@ function parseOptions (definitions: OptionDefinition[], argv: string[], partial: return options; } -function usage (targetLanguages: TargetLanguage[]) { +function usage(targetLanguages: TargetLanguage[]) { const rendererSections: UsageSection[] = []; for (const language of targetLanguages) { @@ -633,7 +634,7 @@ function usage (targetLanguages: TargetLanguage[]) { rendererSections.push({ header: `Options for ${language.displayName}`, optionList: definitions, - tableOptions: tableOptionsForOptions, + tableOptions: tableOptionsForOptions }); } @@ -643,12 +644,12 @@ function usage (targetLanguages: TargetLanguage[]) { } // Returns an array of [name, sourceURIs] pairs. -async function getSourceURIs (options: CLIOptions): Promise> { +async function getSourceURIs(options: CLIOptions): Promise> { if (options.srcUrls !== undefined) { const json = parseJSON( await readFromFileOrURL(options.srcUrls, options.httpHeader), "URL grammar", - options.srcUrls, + options.srcUrls ); const jsonMap = urlsFromURLGrammar(json); const topLevels = Object.getOwnPropertyNames(jsonMap); @@ -660,7 +661,7 @@ async function getSourceURIs (options: CLIOptions): Promise { +async function typeSourcesForURIs(name: string, uris: string[], options: CLIOptions): Promise { switch (options.srcLang) { case "json": return [await sourceFromFileOrUrlArray(name, uris, options.httpHeader)]; @@ -671,10 +672,10 @@ async function typeSourcesForURIs (name: string, uris: string[], options: CLIOpt } } -async function getSources (options: CLIOptions): Promise { +async function getSources(options: CLIOptions): Promise { const sourceURIs = await getSourceURIs(options); const sourceArrays = await Promise.all( - sourceURIs.map(async ([name, uris]) => await typeSourcesForURIs(name, uris, options)), + sourceURIs.map(async ([name, uris]) => await typeSourcesForURIs(name, uris, options)) ); let sources: TypeSource[] = ([] as TypeSource[]).concat(...sourceArrays); @@ -688,20 +689,20 @@ async function getSources (options: CLIOptions): Promise { // Every src that's not a directory is assumed to be a file or URL const filesOrUrls = options.src.filter(x => !_.includes(directories, x)); if (!_.isEmpty(filesOrUrls)) { - sources.push(...await typeSourcesForURIs(options.topLevel, filesOrUrls, options)); + sources.push(...(await typeSourcesForURIs(options.topLevel, filesOrUrls, options))); } return sources; } -function makeTypeScriptSource (fileNames: string[]): SchemaTypeSource { +function makeTypeScriptSource(fileNames: string[]): SchemaTypeSource { return Object.assign({ kind: "schema" }, schemaForTypeScriptSources(fileNames)) as SchemaTypeSource; } -export function jsonInputForTargetLanguage ( +export function jsonInputForTargetLanguage( targetLanguage: string | TargetLanguage, languages?: TargetLanguage[], - handleJSONRefs = false, + handleJSONRefs = false ): JSONInput { if (typeof targetLanguage === "string") { targetLanguage = defined(languageNamed(targetLanguage, languages)); @@ -711,12 +712,12 @@ export function jsonInputForTargetLanguage ( return new JSONInput(compressedJSON); } -async function makeInputData ( +async function makeInputData( sources: TypeSource[], targetLanguage: TargetLanguage, additionalSchemaAddresses: readonly string[], handleJSONRefs: boolean, - httpHeaders?: string[], + httpHeaders?: string[] ): Promise { const inputData = new InputData(); @@ -727,14 +728,14 @@ async function makeInputData ( break; case "json": await inputData.addSource("json", source, () => - jsonInputForTargetLanguage(targetLanguage, undefined, handleJSONRefs), + jsonInputForTargetLanguage(targetLanguage, undefined, handleJSONRefs) ); break; case "schema": await inputData.addSource( "schema", source, - () => new JSONSchemaInput(new FetchingJSONSchemaStore(httpHeaders), [], additionalSchemaAddresses), + () => new JSONSchemaInput(new FetchingJSONSchemaStore(httpHeaders), [], additionalSchemaAddresses) ); break; default: @@ -745,16 +746,16 @@ async function makeInputData ( return inputData; } -function stringSourceDataToStreamSourceData (src: JSONSourceData): JSONSourceData { +function stringSourceDataToStreamSourceData(src: JSONSourceData): JSONSourceData { return { name: src.name, description: src.description, samples: src.samples.map(stringToStream) }; } -export async function makeQuicktypeOptions ( +export async function makeQuicktypeOptions( options: CLIOptions, - targetLanguages?: TargetLanguage[], + targetLanguages?: TargetLanguage[] ): Promise | undefined> { if (options.help) { - usage(targetLanguages === undefined ? defaultTargetLanguages : targetLanguages); + usage(targetLanguages ?? defaultTargetLanguages); return undefined; } @@ -783,7 +784,7 @@ export async function makeQuicktypeOptions ( schemaString = await introspectServer( options.graphqlIntrospect, withDefault(options.httpMethod, "POST"), - withDefault(options.httpHeader, []), + withDefault(options.httpHeader, []) ); if (options.graphqlSchema !== undefined) { fs.writeFileSync(options.graphqlSchema, schemaString); @@ -836,11 +837,11 @@ export async function makeQuicktypeOptions ( const collectionJSON = fs.readFileSync(collectionFile, "utf8"); const { sources: postmanSources, description } = sourcesFromPostmanCollection( collectionJSON, - collectionFile, + collectionFile ); for (const src of postmanSources) { sources.push( - Object.assign({ kind: "json" }, stringSourceDataToStreamSourceData(src)) as JSONTypeSource, + Object.assign({ kind: "json" }, stringSourceDataToStreamSourceData(src)) as JSONTypeSource ); } @@ -910,7 +911,7 @@ export async function makeQuicktypeOptions ( debugPrintGatherNames, debugPrintTransformations, debugPrintSchemaResolving, - debugPrintTimes, + debugPrintTimes }; for (const flagName of inferenceFlagNames) { const cliName = negatedInferenceFlagName(flagName); @@ -927,15 +928,15 @@ export async function makeQuicktypeOptions ( lang, options.additionalSchema, quicktypeOptions.ignoreJsonRefs !== true, - options.httpHeader, + options.httpHeader ); return quicktypeOptions; } -export function writeOutput ( +export function writeOutput( cliOptions: CLIOptions, - resultsByFilename: ReadonlyMap, + resultsByFilename: ReadonlyMap ): void { let onFirst = true; for (const [filename, { lines, annotations }] of resultsByFilename) { @@ -972,7 +973,7 @@ export function writeOutput ( } } -export async function main (args: string[] | Partial) { +export async function main(args: string[] | Partial) { let cliOptions: CLIOptions; if (Array.isArray(args)) { cliOptions = parseCLIOptions(args); From db9a9cfa620e86fd002bc6f4929a2d2a5ef8fa3a Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Fri, 12 Apr 2024 00:05:51 -0700 Subject: [PATCH 33/94] update import rules --- .eslintrc.json | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/.eslintrc.json b/.eslintrc.json index fcf73b84b..c14276ec1 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -9,7 +9,8 @@ "eslint:recommended", "canonical/typescript", "canonical/typescript-type-checking", - "plugin:import/recommended", + "plugin:import/errors", + "plugin:import/warnings", "plugin:import/typescript" ], "plugins": ["canonical"], @@ -28,6 +29,41 @@ "no-extra-parens": "off", "canonical/prefer-inline-type-import": "error", "typescript-sort-keys/string-enum": "off", + + "sort-imports": [ + "error", + { + "ignoreDeclarationSort": true + } + ], + "no-duplicate-imports": "error", + "import/first": "error", + "import/order": [ + "error", + { + "newlines-between": "always", + "groups": ["builtin", "external", "internal", "parent", "sibling", "index", "object", "type"], + "pathGroups": [ + { + "pattern": "@/**", + "group": "internal", + "position": "before" + } + ], + "alphabetize": { + "order": "asc" /* sort in ascending order. Options: ['ignore', 'asc', 'desc'] */, + "caseInsensitive": true /* ignore case. Options: [true, false] */ + } + } + ], + + "import/no-absolute-path": "error", + "import/no-cycle": "error", + "import/no-duplicates": "error", + "import/no-extraneous-dependencies": "error", + "import/no-named-as-default": "off", + "import/no-useless-path-segments": "error", + "@typescript-eslint/class-literal-property-style": "off", "@typescript-eslint/comma-dangle": "off", "@typescript-eslint/consistent-type-definitions": ["error", "interface"], From 3088be7d251b6cdaed39f934140d77ec3f64cf25 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Fri, 12 Apr 2024 07:42:43 -0700 Subject: [PATCH 34/94] fix all require imports --- package-lock.json | 31 ++++++++++++++++++- package.json | 1 + packages/quicktype-core/package.json | 4 ++- .../quicktype-core/src/ConvenienceRenderer.ts | 3 +- .../quicktype-core/src/input/io/NodeIO.ts | 10 +++--- src/index.ts | 8 +++-- tsconfig.json | 3 +- 7 files changed, 48 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6bcb1cc29..566209a26 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44,6 +44,7 @@ "@types/shelljs": "^0.8.12", "@types/stream-json": "^1.7.3", "@types/urijs": "^1.19.25", + "@types/wordwrap": "^1.0.3", "@typescript-eslint/eslint-plugin": "^6.3.0", "@typescript-eslint/parser": "^6.3.0", "ajv": "^5.5.2", @@ -51,7 +52,7 @@ "eslint": "^8.57.0", "eslint-config-canonical": "^41.1.7", "eslint-config-prettier": "^6.10.0", - "eslint-import-resolver-typescript": "^3.5.2", + "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-canonical": "^3.4.0", "eslint-plugin-import": "^2.26.0", "eslint-plugin-json": "^3.1.0", @@ -1230,6 +1231,12 @@ "integrity": "sha512-xGWx4kx9JKlqxDrZA12gw5qi2lvxPNLxnQQcoTXVX83MuGcXcpb7TADatGyGW51GaaXQOQTbjw3x4HuL3ULBaA==", "dev": true }, + "node_modules/@types/is-url": { + "version": "1.2.32", + "resolved": "https://registry.npmjs.org/@types/is-url/-/is-url-1.2.32.tgz", + "integrity": "sha512-46VLdbWI8Sc+hPexQ6NLNR2YpoDyDZIpASHkJQ2Yr+Kf9Giw6LdCTkwOdsnHKPQeh7xTjTmSnxbE8qpxYuCiHA==", + "dev": true + }, "node_modules/@types/js-base64": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/@types/js-base64/-/js-base64-3.3.1.tgz", @@ -1342,6 +1349,12 @@ "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.25.tgz", "integrity": "sha512-XOfUup9r3Y06nFAZh3WvO0rBU4OtlfPB/vgxpjg+NRdGU6CN6djdc6OEiH+PcqHCY6eFLo9Ista73uarf4gnBg==" }, + "node_modules/@types/wordwrap": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/wordwrap/-/wordwrap-1.0.3.tgz", + "integrity": "sha512-jx39cOYWJxZxVOZeNHvLVoDLRUFcYtIJaurC6C0qzCovIB3GPDbMDbYvoWi9D1B2PtIE16rElQOFR4Y+8QbUgw==", + "dev": true + }, "node_modules/@types/ws": { "version": "8.5.10", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", @@ -8815,12 +8828,14 @@ }, "devDependencies": { "@types/browser-or-node": "^1.3.2", + "@types/is-url": "^1.2.32", "@types/js-base64": "^3.3.1", "@types/node": "18.14.0", "@types/pako": "^1.0.0", "@types/pluralize": "0.0.30", "@types/readable-stream": "4.0.10", "@types/unicode-properties": "^1.3.0", + "@types/wordwrap": "^1.0.3", "@types/yaml": "^1.9.7", "typescript": "4.9.5" } @@ -9868,6 +9883,12 @@ "integrity": "sha512-xGWx4kx9JKlqxDrZA12gw5qi2lvxPNLxnQQcoTXVX83MuGcXcpb7TADatGyGW51GaaXQOQTbjw3x4HuL3ULBaA==", "dev": true }, + "@types/is-url": { + "version": "1.2.32", + "resolved": "https://registry.npmjs.org/@types/is-url/-/is-url-1.2.32.tgz", + "integrity": "sha512-46VLdbWI8Sc+hPexQ6NLNR2YpoDyDZIpASHkJQ2Yr+Kf9Giw6LdCTkwOdsnHKPQeh7xTjTmSnxbE8qpxYuCiHA==", + "dev": true + }, "@types/js-base64": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/@types/js-base64/-/js-base64-3.3.1.tgz", @@ -9979,6 +10000,12 @@ "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.25.tgz", "integrity": "sha512-XOfUup9r3Y06nFAZh3WvO0rBU4OtlfPB/vgxpjg+NRdGU6CN6djdc6OEiH+PcqHCY6eFLo9Ista73uarf4gnBg==" }, + "@types/wordwrap": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/wordwrap/-/wordwrap-1.0.3.tgz", + "integrity": "sha512-jx39cOYWJxZxVOZeNHvLVoDLRUFcYtIJaurC6C0qzCovIB3GPDbMDbYvoWi9D1B2PtIE16rElQOFR4Y+8QbUgw==", + "dev": true + }, "@types/ws": { "version": "8.5.10", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", @@ -14066,6 +14093,7 @@ "requires": { "@glideapps/ts-necessities": "2.1.3", "@types/browser-or-node": "^1.3.2", + "@types/is-url": "^1.2.32", "@types/js-base64": "^3.3.1", "@types/node": "18.14.0", "@types/pako": "^1.0.0", @@ -14073,6 +14101,7 @@ "@types/readable-stream": "4.0.10", "@types/unicode-properties": "^1.3.0", "@types/urijs": "^1.19.25", + "@types/wordwrap": "^1.0.3", "@types/yaml": "^1.9.7", "browser-or-node": "^2.1.1", "collection-utils": "^1.0.1", diff --git a/package.json b/package.json index 17ee5b728..24d02f243 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "@types/shelljs": "^0.8.12", "@types/stream-json": "^1.7.3", "@types/urijs": "^1.19.25", + "@types/wordwrap": "^1.0.3", "@typescript-eslint/eslint-plugin": "^6.3.0", "@typescript-eslint/parser": "^6.3.0", "ajv": "^5.5.2", diff --git a/packages/quicktype-core/package.json b/packages/quicktype-core/package.json index 0cbd4a35b..7adb7bc4b 100644 --- a/packages/quicktype-core/package.json +++ b/packages/quicktype-core/package.json @@ -15,8 +15,8 @@ "@types/urijs": "^1.19.25", "browser-or-node": "^2.1.1", "collection-utils": "^1.0.1", - "is-url": "^1.2.4", "cross-fetch": "^4.0.0", + "is-url": "^1.2.4", "js-base64": "^3.7.5", "lodash": "^4.17.21", "pako": "^1.0.6", @@ -29,12 +29,14 @@ }, "devDependencies": { "@types/browser-or-node": "^1.3.2", + "@types/is-url": "^1.2.32", "@types/js-base64": "^3.3.1", "@types/node": "18.14.0", "@types/pako": "^1.0.0", "@types/pluralize": "0.0.30", "@types/readable-stream": "4.0.10", "@types/unicode-properties": "^1.3.0", + "@types/wordwrap": "^1.0.3", "@types/yaml": "^1.9.7", "typescript": "4.9.5" }, diff --git a/packages/quicktype-core/src/ConvenienceRenderer.ts b/packages/quicktype-core/src/ConvenienceRenderer.ts index 21e219ef0..bcb6a9304 100644 --- a/packages/quicktype-core/src/ConvenienceRenderer.ts +++ b/packages/quicktype-core/src/ConvenienceRenderer.ts @@ -32,7 +32,8 @@ import { transformationForType, followTargetType } from "./Transformers"; import { type TargetLanguage } from "./TargetLanguage"; import { type Comment, isStringComment, type CommentOptions } from "./support/Comments"; -const wordWrap: (s: string) => string = require("wordwrap")(90); +import _wordwrap from "wordwrap"; +const wordWrap: (s: string) => string = _wordwrap(90); export const topLevelNameOrder = 1; diff --git a/packages/quicktype-core/src/input/io/NodeIO.ts b/packages/quicktype-core/src/input/io/NodeIO.ts index bb6d3f8f9..fdc63b6b5 100644 --- a/packages/quicktype-core/src/input/io/NodeIO.ts +++ b/packages/quicktype-core/src/input/io/NodeIO.ts @@ -5,14 +5,14 @@ import { getStream } from "./get-stream"; import { defined, exceptionToString } from "@glideapps/ts-necessities"; import { messageError, panic } from "../../index"; -const isURL = require("is-url"); +import isURL from "is-url"; import fetch from "cross-fetch"; interface HttpHeaders { [key: string]: string; } -function parseHeaders (httpHeaders?: string[]): HttpHeaders { +function parseHeaders(httpHeaders?: string[]): HttpHeaders { if (!Array.isArray(httpHeaders)) { return {}; } @@ -34,11 +34,11 @@ function parseHeaders (httpHeaders?: string[]): HttpHeaders { }, {} as HttpHeaders); } -export async function readableFromFileOrURL (fileOrURL: string, httpHeaders?: string[]): Promise { +export async function readableFromFileOrURL(fileOrURL: string, httpHeaders?: string[]): Promise { try { if (isURL(fileOrURL)) { const response = await fetch(fileOrURL, { - headers: parseHeaders(httpHeaders), + headers: parseHeaders(httpHeaders) }); return defined(response.body) as unknown as Readable; } else if (isNode) { @@ -60,7 +60,7 @@ export async function readableFromFileOrURL (fileOrURL: string, httpHeaders?: st return messageError("DriverInputFileDoesNotExist", { filename: fileOrURL }); } -export async function readFromFileOrURL (fileOrURL: string, httpHeaders?: string[]): Promise { +export async function readFromFileOrURL(fileOrURL: string, httpHeaders?: string[]): Promise { const readable = await readableFromFileOrURL(fileOrURL, httpHeaders); try { return await getStream(readable); diff --git a/src/index.ts b/src/index.ts index 78c22b445..a71cfe3f5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -49,14 +49,16 @@ import { introspectServer } from "./GraphQLIntrospection"; import { type JSONTypeSource, type TypeSource, type GraphQLTypeSource, type SchemaTypeSource } from "./TypeSource"; import { CompressedJSONFromStream } from "./CompressedJSONFromStream"; -const stringToStream = require("string-to-stream"); +import stringToStream from "string-to-stream"; import commandLineArgs from "command-line-args"; import getUsage from "command-line-usage"; import chalk from "chalk"; -const wordWrap: (s: string) => string = require("wordwrap")(90); -const packageJSON = require("../package.json"); +import _wordwrap from "wordwrap"; +const wordWrap: (s: string) => string = _wordwrap(90); + +import packageJSON from "../package.json"; export interface CLIOptions { // We use this to access the inference flags diff --git a/tsconfig.json b/tsconfig.json index 60bab643b..4f1446d5e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,7 +10,8 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "outDir": "dist", - "baseUrl": "src" + "baseUrl": "src", + "resolveJsonModule": true }, "include": ["src"] } From c492962d34c6bb70eb6b39bb7e97441c7773b23b Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Fri, 12 Apr 2024 08:25:00 -0700 Subject: [PATCH 35/94] fix all imports --- .../quicktype-core/src/ConvenienceRenderer.ts | 52 +++++------ packages/quicktype-core/src/DeclarationIR.ts | 8 +- packages/quicktype-core/src/GatherNames.ts | 11 ++- packages/quicktype-core/src/Graph.ts | 2 +- packages/quicktype-core/src/GraphRewriting.ts | 26 +++--- .../quicktype-core/src/MakeTransformations.ts | 57 ++++++------ packages/quicktype-core/src/MarkovChain.ts | 2 +- packages/quicktype-core/src/Messages.ts | 14 +-- packages/quicktype-core/src/Naming.ts | 20 ++--- packages/quicktype-core/src/Renderer.ts | 13 ++- .../quicktype-core/src/RendererOptions.ts | 6 +- packages/quicktype-core/src/Run.ts | 30 +++---- packages/quicktype-core/src/Source.ts | 2 +- packages/quicktype-core/src/TargetLanguage.ts | 18 ++-- packages/quicktype-core/src/Transformers.ts | 18 ++-- packages/quicktype-core/src/Type.ts | 40 ++++----- packages/quicktype-core/src/TypeBuilder.ts | 59 ++++++------ packages/quicktype-core/src/TypeGraph.ts | 29 +++--- packages/quicktype-core/src/TypeUtils.ts | 33 +++++-- packages/quicktype-core/src/UnifyClasses.ts | 17 ++-- packages/quicktype-core/src/UnionBuilder.ts | 24 +++-- .../src/attributes/AccessorNames.ts | 18 ++-- .../src/attributes/Constraints.ts | 9 +- .../src/attributes/Description.ts | 21 +++-- .../src/attributes/EnumValues.ts | 8 +- .../src/attributes/StringTypes.ts | 23 ++--- .../src/attributes/TypeAttributes.ts | 6 +- .../src/attributes/TypeNames.ts | 10 +-- .../src/attributes/URIAttributes.ts | 8 +- packages/quicktype-core/src/index.ts | 16 ++-- .../src/input/CompressedJSON.ts | 11 ++- .../src/input/FetchingJSONSchemaStore.ts | 5 +- .../quicktype-core/src/input/Inference.ts | 26 +++--- packages/quicktype-core/src/input/Inputs.ts | 19 ++-- .../src/input/JSONSchemaInput.ts | 84 +++++++++-------- .../src/input/JSONSchemaStore.ts | 3 +- .../src/input/PostmanCollection.ts | 1 + .../quicktype-core/src/input/io/NodeIO.ts | 13 +-- .../src/input/io/get-stream/buffer-stream.ts | 3 +- .../src/input/io/get-stream/index.ts | 1 + packages/quicktype-core/src/language/All.ts | 42 +++++---- packages/quicktype-core/src/language/CJSON.ts | 29 +++--- .../quicktype-core/src/language/CPlusPlus.ts | 90 +++++++++++-------- .../quicktype-core/src/language/CSharp.ts | 85 ++++++++++-------- .../quicktype-core/src/language/Crystal.ts | 35 ++++---- packages/quicktype-core/src/language/Dart.ts | 46 +++++----- packages/quicktype-core/src/language/Elm.ts | 48 +++++----- .../quicktype-core/src/language/Golang.ts | 34 ++++--- .../quicktype-core/src/language/Haskell.ts | 44 ++++----- .../quicktype-core/src/language/JSONSchema.ts | 33 +++---- packages/quicktype-core/src/language/Java.ts | 35 +++++--- .../quicktype-core/src/language/JavaScript.ts | 48 +++++----- .../src/language/JavaScriptPropTypes.ts | 37 ++++---- .../quicktype-core/src/language/Kotlin.ts | 31 ++++--- .../src/language/Objective-C.ts | 49 +++++----- packages/quicktype-core/src/language/Php.ts | 19 ++-- packages/quicktype-core/src/language/Pike.ts | 16 ++-- .../quicktype-core/src/language/Python.ts | 73 +++++++-------- packages/quicktype-core/src/language/Rust.ts | 39 ++++---- .../quicktype-core/src/language/Scala3.ts | 26 +++--- .../quicktype-core/src/language/Smithy4s.ts | 26 +++--- packages/quicktype-core/src/language/Swift.ts | 77 ++++++++-------- .../src/language/TypeScriptEffectSchema.ts | 21 +++-- .../src/language/TypeScriptFlow.ts | 29 +++--- .../src/language/TypeScriptZod.ts | 33 +++---- .../quicktype-core/src/language/ruby/index.ts | 62 +++++++------ .../src/rewrites/CombineClasses.ts | 8 +- .../src/rewrites/ExpandStrings.ts | 20 ++--- .../src/rewrites/FlattenStrings.ts | 10 +-- .../src/rewrites/FlattenUnions.ts | 18 ++-- .../quicktype-core/src/rewrites/InferMaps.ts | 14 ++- .../src/rewrites/ReplaceObjectType.ts | 10 +-- .../src/rewrites/ResolveIntersections.ts | 41 +++++---- .../quicktype-core/src/support/Acronyms.ts | 16 ++-- .../quicktype-core/src/support/Strings.ts | 10 ++- .../quicktype-core/src/support/Support.ts | 3 +- packages/quicktype-graphql-input/src/index.ts | 40 ++++----- .../quicktype-typescript-input/src/index.ts | 15 ++-- src/CompressedJSONFromStream.ts | 4 +- src/GraphQLIntrospection.ts | 16 ++-- src/TypeSource.ts | 2 +- src/URLGrammar.ts | 8 +- src/index.ts | 74 ++++++++------- 83 files changed, 1139 insertions(+), 1043 deletions(-) diff --git a/packages/quicktype-core/src/ConvenienceRenderer.ts b/packages/quicktype-core/src/ConvenienceRenderer.ts index bcb6a9304..8de7ac678 100644 --- a/packages/quicktype-core/src/ConvenienceRenderer.ts +++ b/packages/quicktype-core/src/ConvenienceRenderer.ts @@ -1,38 +1,40 @@ import { - setUnion, - setFilter, iterableEnumerate, iterableSome, mapFilter, - mapSortBy, mapFilterMap, - mapSome + mapSome, + mapSortBy, + setFilter, + setUnion } from "collection-utils"; +import _wordwrap from "wordwrap"; -import { type Type, type TypeKind, type ClassProperty } from "./Type"; -import { ClassType, EnumType, UnionType, MapType, ObjectType } from "./Type"; -import { separateNamedTypes, nullableFromUnion, matchTypeExhaustive, isNamedType } from "./TypeUtils"; -import { type Name, type Namer } from "./Naming"; -import { Namespace, FixedName, SimpleName, DependencyName, keywordNamespace } from "./Naming"; -import { type BlankLineConfig, type RenderContext, type ForEachPosition } from "./Renderer"; -import { Renderer } from "./Renderer"; -import { defined, panic, nonNull, assert } from "./support/Support"; -import { trimEnd } from "./support/Strings"; -import { type Sourcelike } from "./Source"; -import { sourcelikeToSource, serializeRenderResult } from "./Source"; - -import { type DeclarationIR, type Declaration } from "./DeclarationIR"; -import { declarationsForGraph, cycleBreakerTypesForGraph } from "./DeclarationIR"; -import { TypeAttributeStoreView } from "./TypeGraph"; -import { TypeAttributeKind } from "./attributes/TypeAttributes"; +import { enumCaseNames, getAccessorName, objectPropertyNames, unionMemberName } from "./attributes/AccessorNames"; import { descriptionTypeAttributeKind, propertyDescriptionsTypeAttributeKind } from "./attributes/Description"; -import { enumCaseNames, objectPropertyNames, unionMemberName, getAccessorName } from "./attributes/AccessorNames"; -import { type Transformation } from "./Transformers"; -import { transformationForType, followTargetType } from "./Transformers"; +import { TypeAttributeKind } from "./attributes/TypeAttributes"; +import { type Declaration, type DeclarationIR, cycleBreakerTypesForGraph, declarationsForGraph } from "./DeclarationIR"; +import { DependencyName, FixedName, type Name, type Namer, Namespace, SimpleName, keywordNamespace } from "./Naming"; +import { type BlankLineConfig, type ForEachPosition, type RenderContext, Renderer } from "./Renderer"; +import { type Sourcelike, serializeRenderResult, sourcelikeToSource } from "./Source"; +import { type Comment, type CommentOptions, isStringComment } from "./support/Comments"; +import { trimEnd } from "./support/Strings"; +import { assert, defined, nonNull, panic } from "./support/Support"; import { type TargetLanguage } from "./TargetLanguage"; -import { type Comment, isStringComment, type CommentOptions } from "./support/Comments"; +import { type Transformation, followTargetType, transformationForType } from "./Transformers"; +import { + type ClassProperty, + ClassType, + EnumType, + MapType, + ObjectType, + type Type, + type TypeKind, + UnionType +} from "./Type"; +import { TypeAttributeStoreView } from "./TypeGraph"; +import { isNamedType, matchTypeExhaustive, nullableFromUnion, separateNamedTypes } from "./TypeUtils"; -import _wordwrap from "wordwrap"; const wordWrap: (s: string) => string = _wordwrap(90); export const topLevelNameOrder = 1; diff --git a/packages/quicktype-core/src/DeclarationIR.ts b/packages/quicktype-core/src/DeclarationIR.ts index 47d53d2de..f3f15ce0f 100644 --- a/packages/quicktype-core/src/DeclarationIR.ts +++ b/packages/quicktype-core/src/DeclarationIR.ts @@ -1,10 +1,10 @@ -import { setUnionInto, setFilter, iterableFirst, setSubtract, setIntersect } from "collection-utils"; +import { iterableFirst, setFilter, setIntersect, setSubtract, setUnionInto } from "collection-utils"; -import { type TypeGraph } from "./TypeGraph"; -import { type Type } from "./Type"; -import { panic, defined, assert } from "./support/Support"; import { Graph } from "./Graph"; import { messageError } from "./Messages"; +import { assert, defined, panic } from "./support/Support"; +import { type Type } from "./Type"; +import { type TypeGraph } from "./TypeGraph"; export type DeclarationKind = "forward" | "define"; diff --git a/packages/quicktype-core/src/GatherNames.ts b/packages/quicktype-core/src/GatherNames.ts index e5b7d3b86..2dba2afb3 100644 --- a/packages/quicktype-core/src/GatherNames.ts +++ b/packages/quicktype-core/src/GatherNames.ts @@ -1,13 +1,12 @@ +import { setMap, setSortBy, setUnion } from "collection-utils"; import * as pluralize from "pluralize"; -import { setUnion, setMap, setSortBy } from "collection-utils"; +import { TooManyTypeNames, TypeNames, namesTypeAttributeKind, tooManyNamesThreshold } from "./attributes/TypeNames"; +import { assert, defined, panic } from "./support/Support"; +import { transformationForType } from "./Transformers"; +import { ObjectType, type Type } from "./Type"; import { type TypeGraph } from "./TypeGraph"; -import { type Type } from "./Type"; -import { ObjectType } from "./Type"; import { matchCompoundType, nullableFromUnion } from "./TypeUtils"; -import { TypeNames, namesTypeAttributeKind, TooManyTypeNames, tooManyNamesThreshold } from "./attributes/TypeNames"; -import { defined, panic, assert } from "./support/Support"; -import { transformationForType } from "./Transformers"; class UniqueQueue { private readonly _present = new Set(); diff --git a/packages/quicktype-core/src/Graph.ts b/packages/quicktype-core/src/Graph.ts index c54e3ed05..df186ce9c 100644 --- a/packages/quicktype-core/src/Graph.ts +++ b/packages/quicktype-core/src/Graph.ts @@ -1,6 +1,6 @@ import { setMap } from "collection-utils"; -import { defined, repeated, assert, repeatedCall } from "./support/Support"; +import { assert, defined, repeated, repeatedCall } from "./support/Support"; function countComponentGraphNodes(components: number[][]): number { if (components.length === 0) return 0; diff --git a/packages/quicktype-core/src/GraphRewriting.ts b/packages/quicktype-core/src/GraphRewriting.ts index e60360890..546877575 100644 --- a/packages/quicktype-core/src/GraphRewriting.ts +++ b/packages/quicktype-core/src/GraphRewriting.ts @@ -1,14 +1,20 @@ -import { mapMap, EqualityMap } from "collection-utils"; - -import { type PrimitiveTypeKind, type Type, type ClassProperty, type MaybeTypeIdentity } from "./Type"; +import { EqualityMap, mapMap } from "collection-utils"; + +import { type TypeAttributes, combineTypeAttributes, emptyTypeAttributes } from "./attributes/TypeAttributes"; +import { assert, indentationString, panic } from "./support/Support"; +import { type ClassProperty, type MaybeTypeIdentity, type PrimitiveTypeKind, type Type } from "./Type"; +// eslint-disable-next-line import/no-cycle +import { type StringTypeMapping, TypeBuilder } from "./TypeBuilder"; +import { + type TypeGraph, + type TypeRef, + assertTypeRefGraph, + derefTypeRef, + isTypeRef, + typeAndAttributesForTypeRef, + typeRefIndex +} from "./TypeGraph"; import { combineTypeAttributesOfTypes } from "./TypeUtils"; -import { type TypeGraph, type TypeRef } from "./TypeGraph"; -import { derefTypeRef, typeAndAttributesForTypeRef, assertTypeRefGraph, typeRefIndex, isTypeRef } from "./TypeGraph"; -import { type TypeAttributes } from "./attributes/TypeAttributes"; -import { emptyTypeAttributes, combineTypeAttributes } from "./attributes/TypeAttributes"; -import { assert, panic, indentationString } from "./support/Support"; -import { type StringTypeMapping } from "./TypeBuilder"; -import { TypeBuilder } from "./TypeBuilder"; export interface TypeLookerUp { lookupTypeRefs: (typeRefs: TypeRef[], forwardingRef?: TypeRef) => TypeRef | undefined; diff --git a/packages/quicktype-core/src/MakeTransformations.ts b/packages/quicktype-core/src/MakeTransformations.ts index 0b5de7301..fc3bf23f5 100644 --- a/packages/quicktype-core/src/MakeTransformations.ts +++ b/packages/quicktype-core/src/MakeTransformations.ts @@ -1,39 +1,40 @@ -import { setFilter, iterableFirst, mapMapEntries, withDefault, iterableSome, arraySortByInto } from "collection-utils"; +import { arraySortByInto, iterableFirst, iterableSome, mapMapEntries, setFilter, withDefault } from "collection-utils"; -import { type TypeGraph, type TypeRef } from "./TypeGraph"; -import { typeRefIndex } from "./TypeGraph"; +import { minMaxLengthForType, minMaxValueForType } from "./attributes/Constraints"; +import { StringTypes } from "./attributes/StringTypes"; +import { type TypeAttributes, combineTypeAttributes, emptyTypeAttributes } from "./attributes/TypeAttributes"; +import { type GraphRewriteBuilder } from "./GraphRewriting"; +import { type RunContext } from "./Run"; +import { assert, defined, panic } from "./support/Support"; import { type TargetLanguage } from "./TargetLanguage"; -import { type TypeKind, type Type, type PrimitiveType, type PrimitiveStringTypeKind } from "./Type"; import { - UnionType, - EnumType, + ArrayDecodingTransformer, + ChoiceTransformer, + DecodingChoiceTransformer, + DecodingTransformer, + MinMaxLengthCheckTransformer, + MinMaxValueTransformer, + ParseStringTransformer, + StringMatchTransformer, + StringProducerTransformer, + Transformation, + type Transformer, + UnionInstantiationTransformer, + transformationTypeAttributeKind +} from "./Transformers"; +import { ArrayType, + EnumType, + type PrimitiveStringTypeKind, + type PrimitiveType, + type Type, + type TypeKind, + UnionType, isNumberTypeKind, isPrimitiveStringTypeKind, targetTypeKindForTransformedStringTypeKind } from "./Type"; -import { type GraphRewriteBuilder } from "./GraphRewriting"; -import { defined, assert, panic } from "./support/Support"; -import { type Transformer } from "./Transformers"; -import { - UnionInstantiationTransformer, - DecodingChoiceTransformer, - Transformation, - transformationTypeAttributeKind, - StringMatchTransformer, - StringProducerTransformer, - ChoiceTransformer, - DecodingTransformer, - ParseStringTransformer, - ArrayDecodingTransformer, - MinMaxLengthCheckTransformer, - MinMaxValueTransformer -} from "./Transformers"; -import { type TypeAttributes } from "./attributes/TypeAttributes"; -import { emptyTypeAttributes, combineTypeAttributes } from "./attributes/TypeAttributes"; -import { StringTypes } from "./attributes/StringTypes"; -import { type RunContext } from "./Run"; -import { minMaxLengthForType, minMaxValueForType } from "./attributes/Constraints"; +import { type TypeGraph, type TypeRef, typeRefIndex } from "./TypeGraph"; function transformationAttributes( graph: TypeGraph, diff --git a/packages/quicktype-core/src/MarkovChain.ts b/packages/quicktype-core/src/MarkovChain.ts index a2e6f453b..9a3fa5f84 100644 --- a/packages/quicktype-core/src/MarkovChain.ts +++ b/packages/quicktype-core/src/MarkovChain.ts @@ -1,5 +1,5 @@ -import { panic, assert, inflateBase64 } from "./support/Support"; import { encodedMarkovChain } from "./EncodedMarkovChain"; +import { assert, inflateBase64, panic } from "./support/Support"; // This must be null, not undefined, because we read it from JSON. export type SubTrie = number | null | Trie; diff --git a/packages/quicktype-core/src/Messages.ts b/packages/quicktype-core/src/Messages.ts index 0236235f9..6f35dae1c 100644 --- a/packages/quicktype-core/src/Messages.ts +++ b/packages/quicktype-core/src/Messages.ts @@ -1,14 +1,14 @@ -import { type StringMap } from "./support/Support"; import { type Ref } from "./input/JSONSchemaInput"; +import { type StringMap } from "./support/Support"; export type ErrorProperties = | { kind: "InternalError"; properties: { message: string } } // Misc | { - kind: "MiscJSONParseError"; - properties: { address: string; description: string; message: string }; - } + kind: "MiscJSONParseError"; + properties: { address: string; description: string; message: string }; + } | { kind: "MiscReadError"; properties: { fileOrURL: string; message: string } } | { kind: "MiscUnicodeHighSurrogateWithoutLowSurrogate"; properties: {} } | { kind: "MiscInvalidMinMaxConstraint"; properties: { max: number; min: number } } @@ -36,9 +36,9 @@ export type ErrorProperties = | { kind: "SchemaIDMustHaveAddress"; properties: { id: string; ref: Ref } } | { kind: "SchemaWrongAccessorEntryArrayLength"; properties: { operation: string; ref: Ref } } | { - kind: "SchemaSetOperationCasesIsNotArray"; - properties: { cases: any; operation: string; ref: Ref }; - } + kind: "SchemaSetOperationCasesIsNotArray"; + properties: { cases: any; operation: string; ref: Ref }; + } | { kind: "SchemaMoreThanOneUnionMemberName"; properties: { names: string[] } } | { kind: "SchemaCannotGetTypesFromBoolean"; properties: { ref: string } } | { kind: "SchemaCannotIndexArrayWithNonNumber"; properties: { actual: string; ref: Ref } } diff --git a/packages/quicktype-core/src/Naming.ts b/packages/quicktype-core/src/Naming.ts index f49ad815b..d23dd30fc 100644 --- a/packages/quicktype-core/src/Naming.ts +++ b/packages/quicktype-core/src/Naming.ts @@ -1,19 +1,19 @@ import { - setUnion, - setUnionInto, - setMap, - setFilter, + iterableEvery, iterableFind, - iterableSome, + iterableFirst, iterableMinBy, - setGroupBy, + iterableSome, + mapMergeInto, + setFilter, setFilterMap, - iterableFirst, - iterableEvery, - mapMergeInto + setGroupBy, + setMap, + setUnion, + setUnionInto } from "collection-utils"; -import { defined, assert, panic } from "./support/Support"; +import { assert, defined, panic } from "./support/Support"; export class Namespace { public readonly forbiddenNamespaces: ReadonlySet; diff --git a/packages/quicktype-core/src/Renderer.ts b/packages/quicktype-core/src/Renderer.ts index f22dc7c0a..9c8f04e6d 100644 --- a/packages/quicktype-core/src/Renderer.ts +++ b/packages/quicktype-core/src/Renderer.ts @@ -1,15 +1,12 @@ import { iterableEnumerate } from "collection-utils"; -import { type TypeGraph } from "./TypeGraph"; -import { type Name, type Namespace } from "./Naming"; -import { assignNames } from "./Naming"; -import { type Source, type Sourcelike, type NewlineSource } from "./Source"; -import { annotated, sourcelikeToSource, newline } from "./Source"; -import { type AnnotationData } from "./Annotation"; -import { IssueAnnotationData } from "./Annotation"; +import { type AnnotationData, IssueAnnotationData } from "./Annotation"; +import { type Name, type Namespace, assignNames } from "./Naming"; +import { type NewlineSource, type Source, type Sourcelike, annotated, newline, sourcelikeToSource } from "./Source"; +import { type Comment } from "./support/Comments"; import { assert, panic } from "./support/Support"; import { type TargetLanguage } from "./TargetLanguage"; -import { type Comment } from "./support/Comments"; +import { type TypeGraph } from "./TypeGraph"; export interface RenderResult { names: ReadonlyMap; diff --git a/packages/quicktype-core/src/RendererOptions.ts b/packages/quicktype-core/src/RendererOptions.ts index 4aab7d4ec..9e4b17542 100644 --- a/packages/quicktype-core/src/RendererOptions.ts +++ b/packages/quicktype-core/src/RendererOptions.ts @@ -1,7 +1,9 @@ -import { assert } from "./support/Support"; -import { messageError } from "./Messages"; +// eslint-disable-next-line @typescript-eslint/no-redeclare import { hasOwnProperty } from "collection-utils"; +import { messageError } from "./Messages"; +import { assert } from "./support/Support"; + /** * Primary options show up in the web UI in the "Language" settings tab, * secondary options in "Other". diff --git a/packages/quicktype-core/src/Run.ts b/packages/quicktype-core/src/Run.ts index 2e2790781..42a5e5b31 100644 --- a/packages/quicktype-core/src/Run.ts +++ b/packages/quicktype-core/src/Run.ts @@ -1,27 +1,25 @@ import { mapFirst } from "collection-utils"; -import * as targetLanguages from "./language/All"; -import { type TargetLanguage, type MultiFileRenderResult } from "./TargetLanguage"; -import { type SerializedRenderResult, type Annotation, type Location, type Span } from "./Source"; -import { assert } from "./support/Support"; -import { combineClasses } from "./rewrites/CombineClasses"; -import { inferMaps } from "./rewrites/InferMaps"; -import { type StringTypeMapping } from "./TypeBuilder"; -import { TypeBuilder } from "./TypeBuilder"; -import { type TypeGraph } from "./TypeGraph"; -import { noneToAny, optionalToNullable, removeIndirectionIntersections } from "./TypeGraph"; import { initTypeNames } from "./attributes/TypeNames"; import { gatherNames } from "./GatherNames"; +import { InputData } from "./input/Inputs"; +import * as targetLanguages from "./language/All"; +import { makeTransformations } from "./MakeTransformations"; +import { messageError } from "./Messages"; +import { combineClasses } from "./rewrites/CombineClasses"; import { expandStrings } from "./rewrites/ExpandStrings"; +import { flattenStrings } from "./rewrites/FlattenStrings"; import { flattenUnions } from "./rewrites/FlattenUnions"; -import { resolveIntersections } from "./rewrites/ResolveIntersections"; +import { inferMaps } from "./rewrites/InferMaps"; import { replaceObjectType } from "./rewrites/ReplaceObjectType"; -import { messageError } from "./Messages"; -import { InputData } from "./input/Inputs"; -import { flattenStrings } from "./rewrites/FlattenStrings"; -import { makeTransformations } from "./MakeTransformations"; -import { type TransformedStringTypeKind } from "./Type"; +import { resolveIntersections } from "./rewrites/ResolveIntersections"; +import { type Annotation, type Location, type SerializedRenderResult, type Span } from "./Source"; import { type Comment } from "./support/Comments"; +import { assert } from "./support/Support"; +import { type MultiFileRenderResult, type TargetLanguage } from "./TargetLanguage"; +import { type TransformedStringTypeKind } from "./Type"; +import { type StringTypeMapping, TypeBuilder } from "./TypeBuilder"; +import { type TypeGraph, noneToAny, optionalToNullable, removeIndirectionIntersections } from "./TypeGraph"; export function getTargetLanguage(nameOrInstance: string | TargetLanguage): TargetLanguage { if (typeof nameOrInstance === "object") { diff --git a/packages/quicktype-core/src/Source.ts b/packages/quicktype-core/src/Source.ts index f47360c37..fcf004546 100644 --- a/packages/quicktype-core/src/Source.ts +++ b/packages/quicktype-core/src/Source.ts @@ -2,8 +2,8 @@ import { arrayIntercalate, iterableMax, withDefault } from "collection-utils"; import { type AnnotationData } from "./Annotation"; import { Name } from "./Naming"; -import { defined, assertNever, panic, assert } from "./support/Support"; import { repeatString } from "./support/Strings"; +import { assert, assertNever, defined, panic } from "./support/Support"; export type Source = | TextSource diff --git a/packages/quicktype-core/src/TargetLanguage.ts b/packages/quicktype-core/src/TargetLanguage.ts index 7f41b919e..07fe51409 100644 --- a/packages/quicktype-core/src/TargetLanguage.ts +++ b/packages/quicktype-core/src/TargetLanguage.ts @@ -1,17 +1,15 @@ import { mapMap } from "collection-utils"; -import { type TypeGraph } from "./TypeGraph"; -import { type Renderer, type RenderContext } from "./Renderer"; -import { type OptionDefinition, type Option } from "./RendererOptions"; -import { type SerializedRenderResult } from "./Source"; -import { serializeRenderResult } from "./Source"; -import { type StringTypeMapping } from "./TypeBuilder"; -import { defined } from "./support/Support"; import { type ConvenienceRenderer } from "./ConvenienceRenderer"; -import { type Type } from "./Type"; -import { type DateTimeRecognizer } from "./DateTime"; -import { DefaultDateTimeRecognizer } from "./DateTime"; +import { type DateTimeRecognizer, DefaultDateTimeRecognizer } from "./DateTime"; +import { type RenderContext, type Renderer } from "./Renderer"; +import { type Option, type OptionDefinition } from "./RendererOptions"; +import { type SerializedRenderResult, serializeRenderResult } from "./Source"; import { type Comment } from "./support/Comments"; +import { defined } from "./support/Support"; +import { type Type } from "./Type"; +import { type StringTypeMapping } from "./TypeBuilder"; +import { type TypeGraph } from "./TypeGraph"; export type MultiFileRenderResult = ReadonlyMap; diff --git a/packages/quicktype-core/src/Transformers.ts b/packages/quicktype-core/src/Transformers.ts index 3c9b3f9eb..01de933a8 100644 --- a/packages/quicktype-core/src/Transformers.ts +++ b/packages/quicktype-core/src/Transformers.ts @@ -1,21 +1,19 @@ import { - setUnionInto, + addHashCode, areEqual, - hashCodeOf, + arraySortByInto, definedMap, - addHashCode, definedMapWithDefault, - arraySortByInto, - hashString + hashCodeOf, + hashString, + setUnionInto } from "collection-utils"; -import { type Type, type TypeKind } from "./Type"; -import { UnionType, EnumType, PrimitiveType } from "./Type"; import { TypeAttributeKind } from "./attributes/TypeAttributes"; -import { panic, assert, indentationString } from "./support/Support"; import { type BaseGraphRewriteBuilder } from "./GraphRewriting"; -import { type TypeRef, type TypeGraph } from "./TypeGraph"; -import { derefTypeRef } from "./TypeGraph"; +import { assert, indentationString, panic } from "./support/Support"; +import { EnumType, PrimitiveType, type Type, type TypeKind, UnionType } from "./Type"; +import { type TypeGraph, type TypeRef, derefTypeRef } from "./TypeGraph"; function debugStringForType(t: Type): string { const target = followTargetType(t); diff --git a/packages/quicktype-core/src/Type.ts b/packages/quicktype-core/src/Type.ts index 6b50cd7d9..6184f712b 100644 --- a/packages/quicktype-core/src/Type.ts +++ b/packages/quicktype-core/src/Type.ts @@ -1,35 +1,35 @@ import { + addHashCode, + areEqual, + definedMap, + // eslint-disable-next-line @typescript-eslint/no-redeclare + hasOwnProperty, + hashCodeInit, + hashCodeOf, iterableEvery, iterableFind, iterableSome, - toReadonlySet, - hashCodeOf, - areEqual, + mapFilter, + mapFromObject, mapMap, - setMap, - mapSortByKey, mapSome, - mapFilter, - setSortBy, + mapSortByKey, + mapSortToArray, setFilter, + setMap, + setSortBy, setUnionInto, - mapSortToArray, - definedMap, - hashCodeInit, - addHashCode, - hasOwnProperty, - mapFromObject + toReadonlySet } from "collection-utils"; -import { defined, panic, assert } from "./support/Support"; -import { type TypeReconstituter, type BaseGraphRewriteBuilder } from "./GraphRewriting"; -import { type TypeNames } from "./attributes/TypeNames"; -import { namesTypeAttributeKind } from "./attributes/TypeNames"; import { type TypeAttributes } from "./attributes/TypeAttributes"; -import { messageAssert } from "./Messages"; -import { type TypeRef, type TypeGraph } from "./TypeGraph"; -import { attributesForTypeRef, derefTypeRef, typeRefIndex } from "./TypeGraph"; +import { type TypeNames, namesTypeAttributeKind } from "./attributes/TypeNames"; import { uriInferenceAttributesProducer } from "./attributes/URIAttributes"; +import { type BaseGraphRewriteBuilder, type TypeReconstituter } from "./GraphRewriting"; +import { messageAssert } from "./Messages"; +import { assert, defined, panic } from "./support/Support"; +// eslint-disable-next-line import/no-cycle +import { type TypeGraph, type TypeRef, attributesForTypeRef, derefTypeRef, typeRefIndex } from "./TypeGraph"; /** * `jsonSchema` is the `format` to be used to represent this string type in diff --git a/packages/quicktype-core/src/TypeBuilder.ts b/packages/quicktype-core/src/TypeBuilder.ts index 5370e5be8..2b4275be8 100644 --- a/packages/quicktype-core/src/TypeBuilder.ts +++ b/packages/quicktype-core/src/TypeBuilder.ts @@ -1,51 +1,54 @@ import { EqualityMap, - mapMap, - mapSortByKey, + areEqual, + definedMap, iterableEvery, mapFilter, mapFind, - areEqual, + mapMap, + mapSortByKey, setUnionManyInto, - definedMap, withDefault } from "collection-utils"; +// eslint-disable-next-line import/no-cycle +import { StringTypes, stringTypesTypeAttributeKind } from "./attributes/StringTypes"; import { - type PrimitiveTypeKind, - type Type, - type PrimitiveStringTypeKind, - type MaybeTypeIdentity, - type TypeIdentity, - type TransformedStringTypeKind, - type TypeKind -} from "./Type"; + TypeAttributeKind, + type TypeAttributes, + combineTypeAttributes, + emptyTypeAttributes +} from "./attributes/TypeAttributes"; +import { assert, defined, panic } from "./support/Support"; +// eslint-disable-next-line import/no-cycle import { - PrimitiveType, - EnumType, - MapType, ArrayType, - ClassType, - UnionType, ClassProperty, + ClassType, + EnumType, IntersectionType, + MapType, + type MaybeTypeIdentity, ObjectType, - primitiveTypeIdentity, - enumTypeIdentity, - mapTypeIdentify, + type PrimitiveStringTypeKind, + PrimitiveType, + type PrimitiveTypeKind, + type TransformedStringTypeKind, + type Type, + type TypeIdentity, + type TypeKind, + UnionType, arrayTypeIdentity, classTypeIdentity, - unionTypeIdentity, + enumTypeIdentity, intersectionTypeIdentity, isPrimitiveStringTypeKind, - transformedStringTypeKinds + mapTypeIdentify, + primitiveTypeIdentity, + transformedStringTypeKinds, + unionTypeIdentity } from "./Type"; -import { type TypeRef } from "./TypeGraph"; -import { TypeGraph, makeTypeRef, derefTypeRef, typeRefIndex, assertTypeRefGraph } from "./TypeGraph"; -import { type TypeAttributes } from "./attributes/TypeAttributes"; -import { combineTypeAttributes, TypeAttributeKind, emptyTypeAttributes } from "./attributes/TypeAttributes"; -import { defined, assert, panic } from "./support/Support"; -import { stringTypesTypeAttributeKind, StringTypes } from "./attributes/StringTypes"; +import { TypeGraph, type TypeRef, assertTypeRefGraph, derefTypeRef, makeTypeRef, typeRefIndex } from "./TypeGraph"; // FIXME: Don't infer provenance. All original types should be present in // non-inferred form in the final graph. diff --git a/packages/quicktype-core/src/TypeGraph.ts b/packages/quicktype-core/src/TypeGraph.ts index 2e5ddb1c4..98df9370f 100644 --- a/packages/quicktype-core/src/TypeGraph.ts +++ b/packages/quicktype-core/src/TypeGraph.ts @@ -1,19 +1,22 @@ -import { iterableFirst, setFilter, setUnionManyInto, setSubtract, mapMap, mapSome, setMap } from "collection-utils"; - -import { type Type } from "./Type"; -import { ClassType, UnionType, IntersectionType } from "./Type"; -import { type SeparatedNamedTypes } from "./TypeUtils"; -import { separateNamedTypes, isNamedType, combineTypeAttributesOfTypes } from "./TypeUtils"; -import { defined, assert, panic, mustNotHappen } from "./support/Support"; -import { type TypeBuilder, type StringTypeMapping } from "./TypeBuilder"; -import { getNoStringTypeMapping, provenanceTypeAttributeKind } from "./TypeBuilder"; -import { type BaseGraphRewriteBuilder } from "./GraphRewriting"; -import { GraphRewriteBuilder, GraphRemapBuilder } from "./GraphRewriting"; +import { iterableFirst, mapMap, mapSome, setFilter, setMap, setSubtract, setUnionManyInto } from "collection-utils"; + +import { type TypeAttributeKind, type TypeAttributes, emptyTypeAttributes } from "./attributes/TypeAttributes"; import { TypeNames, namesTypeAttributeKind } from "./attributes/TypeNames"; import { Graph } from "./Graph"; -import { type TypeAttributeKind, type TypeAttributes } from "./attributes/TypeAttributes"; -import { emptyTypeAttributes } from "./attributes/TypeAttributes"; +// eslint-disable-next-line import/no-cycle +import { type BaseGraphRewriteBuilder, GraphRemapBuilder, GraphRewriteBuilder } from "./GraphRewriting"; import { messageError } from "./Messages"; +import { assert, defined, mustNotHappen, panic } from "./support/Support"; +// eslint-disable-next-line import/no-cycle +import { ClassType, IntersectionType, type Type, UnionType } from "./Type"; +// eslint-disable-next-line import/no-cycle +import { + type StringTypeMapping, + type TypeBuilder, + getNoStringTypeMapping, + provenanceTypeAttributeKind +} from "./TypeBuilder"; +import { type SeparatedNamedTypes, combineTypeAttributesOfTypes, isNamedType, separateNamedTypes } from "./TypeUtils"; export type TypeRef = number; diff --git a/packages/quicktype-core/src/TypeUtils.ts b/packages/quicktype-core/src/TypeUtils.ts index 5a37546bd..07fdd4e65 100644 --- a/packages/quicktype-core/src/TypeUtils.ts +++ b/packages/quicktype-core/src/TypeUtils.ts @@ -1,12 +1,27 @@ -import { setFilter, setSortBy, iterableFirst, setUnion, EqualityMap } from "collection-utils"; - -import { defined, panic, assert, assertNever } from "./support/Support"; -import { type TypeAttributes, type CombinationKind } from "./attributes/TypeAttributes"; -import { combineTypeAttributes, emptyTypeAttributes } from "./attributes/TypeAttributes"; -import { type Type, type PrimitiveType, type ClassProperty, type SetOperationType } from "./Type"; -import { ArrayType, EnumType, ObjectType, MapType, ClassType, UnionType, isPrimitiveStringTypeKind } from "./Type"; -import { type StringTypes } from "./attributes/StringTypes"; -import { stringTypesTypeAttributeKind } from "./attributes/StringTypes"; +import { EqualityMap, iterableFirst, setFilter, setSortBy, setUnion } from "collection-utils"; + +// eslint-disable-next-line import/no-cycle +import { type StringTypes, stringTypesTypeAttributeKind } from "./attributes/StringTypes"; +import { + type CombinationKind, + type TypeAttributes, + combineTypeAttributes, + emptyTypeAttributes +} from "./attributes/TypeAttributes"; +import { assert, assertNever, defined, panic } from "./support/Support"; +import { + ArrayType, + type ClassProperty, + ClassType, + EnumType, + MapType, + ObjectType, + type PrimitiveType, + type SetOperationType, + type Type, + UnionType, + isPrimitiveStringTypeKind +} from "./Type"; export function assertIsObject(t: Type): ObjectType { if (t instanceof ObjectType) { diff --git a/packages/quicktype-core/src/UnifyClasses.ts b/packages/quicktype-core/src/UnifyClasses.ts index dbf5fa4b2..f1e6ab3e0 100644 --- a/packages/quicktype-core/src/UnifyClasses.ts +++ b/packages/quicktype-core/src/UnifyClasses.ts @@ -1,16 +1,13 @@ import { iterableFirst, setUnionInto } from "collection-utils"; -import { type Type, type ClassProperty, type ObjectType } from "./Type"; -import { UnionType } from "./Type"; -import { assertIsObject } from "./TypeUtils"; +import { type TypeAttributes, combineTypeAttributes, emptyTypeAttributes } from "./attributes/TypeAttributes"; +import { type BaseGraphRewriteBuilder, type GraphRewriteBuilder, type TypeLookerUp } from "./GraphRewriting"; +import { assert, defined, panic } from "./support/Support"; +import { type ClassProperty, type ObjectType, type Type, UnionType } from "./Type"; import { type TypeBuilder } from "./TypeBuilder"; -import { type TypeLookerUp, type GraphRewriteBuilder, type BaseGraphRewriteBuilder } from "./GraphRewriting"; -import { UnionBuilder, TypeRefUnionAccumulator } from "./UnionBuilder"; -import { panic, assert, defined } from "./support/Support"; -import { type TypeAttributes } from "./attributes/TypeAttributes"; -import { combineTypeAttributes, emptyTypeAttributes } from "./attributes/TypeAttributes"; -import { type TypeRef } from "./TypeGraph"; -import { derefTypeRef } from "./TypeGraph"; +import { type TypeRef, derefTypeRef } from "./TypeGraph"; +import { assertIsObject } from "./TypeUtils"; +import { TypeRefUnionAccumulator, UnionBuilder } from "./UnionBuilder"; function getCliqueProperties( clique: ObjectType[], diff --git a/packages/quicktype-core/src/UnionBuilder.ts b/packages/quicktype-core/src/UnionBuilder.ts index 0573b18b7..4c93a6ac6 100644 --- a/packages/quicktype-core/src/UnionBuilder.ts +++ b/packages/quicktype-core/src/UnionBuilder.ts @@ -1,19 +1,25 @@ -import { mapMerge, mapUpdateInto, mapMap, setUnionInto } from "collection-utils"; +import { mapMap, mapMerge, mapUpdateInto, setUnionInto } from "collection-utils"; -import { type TypeKind, type PrimitiveStringTypeKind, type Type, type PrimitiveTypeKind } from "./Type"; -import { UnionType, isPrimitiveTypeKind } from "./Type"; -import { matchTypeExhaustive } from "./TypeUtils"; -import { type TypeAttributes } from "./attributes/TypeAttributes"; +import { StringTypes, stringTypesTypeAttributeKind } from "./attributes/StringTypes"; import { + type TypeAttributes, combineTypeAttributes, emptyTypeAttributes, - makeTypeAttributesInferred, - increaseTypeAttributesDistance + increaseTypeAttributesDistance, + makeTypeAttributesInferred } from "./attributes/TypeAttributes"; -import { defined, assert, panic, assertNever } from "./support/Support"; +import { assert, assertNever, defined, panic } from "./support/Support"; +import { + type PrimitiveStringTypeKind, + type PrimitiveTypeKind, + type Type, + type TypeKind, + UnionType, + isPrimitiveTypeKind +} from "./Type"; import { type TypeBuilder } from "./TypeBuilder"; -import { StringTypes, stringTypesTypeAttributeKind } from "./attributes/StringTypes"; import { type TypeRef } from "./TypeGraph"; +import { matchTypeExhaustive } from "./TypeUtils"; // FIXME: This interface is badly designed. All the properties // should use immutable types, and getMemberKinds should be diff --git a/packages/quicktype-core/src/attributes/AccessorNames.ts b/packages/quicktype-core/src/attributes/AccessorNames.ts index c9384cd56..cb19ca59e 100644 --- a/packages/quicktype-core/src/attributes/AccessorNames.ts +++ b/packages/quicktype-core/src/attributes/AccessorNames.ts @@ -1,19 +1,19 @@ import { iterableFirst, mapFromIterable, - mapMap, mapFromObject, - setUnionManyInto, - mapMergeInto + mapMap, + mapMergeInto, + setUnionManyInto } from "collection-utils"; -import { type TypeAttributes } from "./TypeAttributes"; -import { TypeAttributeKind } from "./TypeAttributes"; -import { defined, isStringMap, checkStringMap, checkArray } from "../support/Support"; -import { type EnumType, type UnionType, type Type, type ObjectType } from "../Type"; -import { messageAssert } from "../Messages"; +import { type JSONSchemaAttributes, type JSONSchemaType, type Ref } from "../input/JSONSchemaInput"; import { type JSONSchema } from "../input/JSONSchemaStore"; -import { type Ref, type JSONSchemaType, type JSONSchemaAttributes } from "../input/JSONSchemaInput"; +import { messageAssert } from "../Messages"; +import { checkArray, checkStringMap, defined, isStringMap } from "../support/Support"; +import { type EnumType, type ObjectType, type Type, type UnionType } from "../Type"; + +import { TypeAttributeKind, type TypeAttributes } from "./TypeAttributes"; export type AccessorEntry = string | Map; diff --git a/packages/quicktype-core/src/attributes/Constraints.ts b/packages/quicktype-core/src/attributes/Constraints.ts index 1bb66e2cf..09fb79564 100644 --- a/packages/quicktype-core/src/attributes/Constraints.ts +++ b/packages/quicktype-core/src/attributes/Constraints.ts @@ -1,9 +1,10 @@ +import { type JSONSchemaAttributes, type JSONSchemaType, type Ref } from "../input/JSONSchemaInput"; +import { type JSONSchema } from "../input/JSONSchemaStore"; +import { messageError } from "../Messages"; +import { assert } from "../support/Support"; import { type Type, type TypeKind } from "../Type"; + import { TypeAttributeKind } from "./TypeAttributes"; -import { assert } from "../support/Support"; -import { messageError } from "../Messages"; -import { type JSONSchemaType, type JSONSchemaAttributes, type Ref } from "../input/JSONSchemaInput"; -import { type JSONSchema } from "../input/JSONSchemaStore"; // This can't be an object type, unfortunately, because it's in the // type's identity and as such must be comparable and hashable with diff --git a/packages/quicktype-core/src/attributes/Description.ts b/packages/quicktype-core/src/attributes/Description.ts index 9bf1d6588..01022e7dd 100644 --- a/packages/quicktype-core/src/attributes/Description.ts +++ b/packages/quicktype-core/src/attributes/Description.ts @@ -1,22 +1,29 @@ import { + iterableFirst, mapFilterMap, mapFromObject, - setUnion, - iterableFirst, - setUnionManyInto, mapMergeWithInto, - setSubtract + setSubtract, + setUnion, + setUnionManyInto } from "collection-utils"; // There's a cyclic import here. Ignoring now because it requires a large refactor. // skipcq: JS-E1008 -import { TypeAttributeKind, emptyTypeAttributes } from "./TypeAttributes"; // FIXME: This is a circular import -import { type JSONSchemaType, type Ref, type JSONSchemaAttributes, type PathElement } from "../input/JSONSchemaInput"; -import { PathElementKind } from "../input/JSONSchemaInput"; +// eslint-disable-next-line import/no-cycle +import { + type JSONSchemaAttributes, + type JSONSchemaType, + type PathElement, + PathElementKind, + type Ref +} from "../input/JSONSchemaInput"; import { type JSONSchema } from "../input/JSONSchemaStore"; import { type Type } from "../Type"; +import { TypeAttributeKind, emptyTypeAttributes } from "./TypeAttributes"; + export function addDescriptionToSchema( schema: { [name: string]: unknown }, description: Iterable | undefined diff --git a/packages/quicktype-core/src/attributes/EnumValues.ts b/packages/quicktype-core/src/attributes/EnumValues.ts index 38ac38542..1f66958e3 100644 --- a/packages/quicktype-core/src/attributes/EnumValues.ts +++ b/packages/quicktype-core/src/attributes/EnumValues.ts @@ -1,11 +1,11 @@ import { mapMap } from "collection-utils"; -import { type AccessorNames } from "./AccessorNames"; -import { lookupKey, makeAccessorNames } from "./AccessorNames"; +import { type JSONSchemaAttributes, type JSONSchemaType, type Ref } from "../input/JSONSchemaInput"; +import { type JSONSchema } from "../input/JSONSchemaStore"; import { type EnumType } from "../Type"; + +import { type AccessorNames, lookupKey, makeAccessorNames } from "./AccessorNames"; import { TypeAttributeKind } from "./TypeAttributes"; -import { type JSONSchema } from "../input/JSONSchemaStore"; -import { type Ref, type JSONSchemaType, type JSONSchemaAttributes } from "../input/JSONSchemaInput"; class EnumValuesTypeAttributeKind extends TypeAttributeKind { public constructor() { diff --git a/packages/quicktype-core/src/attributes/StringTypes.ts b/packages/quicktype-core/src/attributes/StringTypes.ts index 4c0083e82..343eeebe0 100644 --- a/packages/quicktype-core/src/attributes/StringTypes.ts +++ b/packages/quicktype-core/src/attributes/StringTypes.ts @@ -1,21 +1,22 @@ import { - mapMap, - iterableFirst, - setIntersect, - hashCodeOf, + addHashCode, areEqual, - mapMergeWithInto, definedMap, - addHashCode, + hashCodeOf, + iterableFirst, + mapMap, + mapMergeWithInto, + setIntersect, setUnionInto } from "collection-utils"; -import { TypeAttributeKind } from "./TypeAttributes"; -import { defined, assert } from "../support/Support"; -import { type StringTypeMapping } from "../TypeBuilder"; -import { stringTypeMappingGet } from "../TypeBuilder"; -import { type TransformedStringTypeKind } from "../Type"; import { type DateTimeRecognizer } from "../DateTime"; +import { assert, defined } from "../support/Support"; +import { type TransformedStringTypeKind } from "../Type"; +// eslint-disable-next-line import/no-cycle +import { type StringTypeMapping, stringTypeMappingGet } from "../TypeBuilder"; + +import { TypeAttributeKind } from "./TypeAttributes"; export class StringTypes { public static readonly unrestricted: StringTypes = new StringTypes(undefined, new Set()); diff --git a/packages/quicktype-core/src/attributes/TypeAttributes.ts b/packages/quicktype-core/src/attributes/TypeAttributes.ts index bf5a35d5b..164f9878d 100644 --- a/packages/quicktype-core/src/attributes/TypeAttributes.ts +++ b/packages/quicktype-core/src/attributes/TypeAttributes.ts @@ -1,8 +1,8 @@ -import { mapFilterMap, mapFilter, mapTranspose, hashString } from "collection-utils"; +import { hashString, mapFilter, mapFilterMap, mapTranspose } from "collection-utils"; -import { panic, assert } from "../support/Support"; -import { type Type, type TypeKind } from "../Type"; import { type BaseGraphRewriteBuilder } from "../GraphRewriting"; +import { assert, panic } from "../support/Support"; +import { type Type, type TypeKind } from "../Type"; export class TypeAttributeKind { public constructor(public readonly name: string) {} diff --git a/packages/quicktype-core/src/attributes/TypeNames.ts b/packages/quicktype-core/src/attributes/TypeNames.ts index a1be97d07..f5d96a7ac 100644 --- a/packages/quicktype-core/src/attributes/TypeNames.ts +++ b/packages/quicktype-core/src/attributes/TypeNames.ts @@ -1,11 +1,11 @@ +import { definedMap, iterableFirst, iterableSkip, setMap, setUnionInto } from "collection-utils"; import * as pluralize from "pluralize"; -import { setMap, iterableFirst, iterableSkip, setUnionInto, definedMap } from "collection-utils"; -import { panic, defined, assert } from "../support/Support"; -import { type TypeAttributes } from "./TypeAttributes"; -import { TypeAttributeKind } from "./TypeAttributes"; -import { splitIntoWords } from "../support/Strings"; import { Chance } from "../support/Chance"; +import { splitIntoWords } from "../support/Strings"; +import { assert, defined, panic } from "../support/Support"; + +import { TypeAttributeKind, type TypeAttributes } from "./TypeAttributes"; let chance: Chance; let usedRandomNames: Set; diff --git a/packages/quicktype-core/src/attributes/URIAttributes.ts b/packages/quicktype-core/src/attributes/URIAttributes.ts index 78e2fcc68..f2b5cb560 100644 --- a/packages/quicktype-core/src/attributes/URIAttributes.ts +++ b/packages/quicktype-core/src/attributes/URIAttributes.ts @@ -1,13 +1,13 @@ +import { setUnionManyInto } from "collection-utils"; import URI from "urijs"; -import { type TypeAttributes } from "./TypeAttributes"; -import { TypeAttributeKind, emptyTypeAttributes } from "./TypeAttributes"; -import { setUnionManyInto } from "collection-utils"; -import { type JSONSchemaType, type JSONSchemaAttributes, type Ref } from "../input/JSONSchemaInput"; +import { type JSONSchemaAttributes, type JSONSchemaType, type Ref } from "../input/JSONSchemaInput"; import { type JSONSchema } from "../input/JSONSchemaStore"; import { checkArray, checkString } from "../support/Support"; import { type Type } from "../Type"; +import { TypeAttributeKind, type TypeAttributes, emptyTypeAttributes } from "./TypeAttributes"; + const protocolsSchemaProperty = "qt-uri-protocols"; const extensionsSchemaProperty = "qt-uri-extensions"; diff --git a/packages/quicktype-core/src/index.ts b/packages/quicktype-core/src/index.ts index a56413a31..41c968bdd 100644 --- a/packages/quicktype-core/src/index.ts +++ b/packages/quicktype-core/src/index.ts @@ -12,7 +12,7 @@ export { inferenceFlagsObject, type InferenceFlags, type InferenceFlagName, - type RunContext, + type RunContext } from "./Run"; export { CompressedJSON, type Value } from "./input/CompressedJSON"; export { type Input, InputData, JSONInput, type JSONSourceData, jsonInputForTargetLanguage } from "./input/Inputs"; @@ -29,7 +29,7 @@ export { type Annotation, modifySource, singleWord, - parenIfNeeded, + parenIfNeeded } from "./Source"; export { Name, funPrefixNamer, Namer } from "./Naming"; export { IssueAnnotationData } from "./Annotation"; @@ -41,7 +41,7 @@ export { parseJSON, checkStringMap, checkArray, - inflateBase64, + inflateBase64 } from "./support/Support"; export { splitIntoWords, @@ -50,7 +50,7 @@ export { firstUpperWordStyle, allUpperWordStyle, legalizeCharacters, - isLetterOrDigit, + isLetterOrDigit } from "./support/Strings"; export { train as trainMarkovChain } from "./MarkovChain"; export { QuickTypeError, messageError, messageAssert } from "./Messages"; @@ -66,10 +66,12 @@ export { type TypeKind, ObjectType, type TransformedStringTypeKind, - type PrimitiveStringTypeKind, + type PrimitiveStringTypeKind } from "./Type"; export { getStream } from "./input/io/get-stream"; +// eslint-disable-next-line import/no-cycle export { readableFromFileOrURL, readFromFileOrURL } from "./input/io/NodeIO"; +// eslint-disable-next-line import/no-cycle export { FetchingJSONSchemaStore } from "./input/FetchingJSONSchemaStore"; export { JSONSchemaStore, type JSONSchema } from "./input/JSONSchemaStore"; export { sourcesFromPostmanCollection } from "./input/PostmanCollection"; @@ -93,14 +95,14 @@ export { JavaScriptTargetLanguage, JavaScriptRenderer, javaScriptOptions } from export { JavaScriptPropTypesTargetLanguage, JavaScriptPropTypesRenderer, - javaScriptPropTypesOptions, + javaScriptPropTypesOptions } from "./language/JavaScriptPropTypes"; export { TypeScriptTargetLanguage, TypeScriptRenderer, FlowTargetLanguage, FlowRenderer, - tsFlowOptions, + tsFlowOptions } from "./language/TypeScriptFlow"; export { SwiftTargetLanguage, SwiftRenderer, swiftOptions } from "./language/Swift"; export { KotlinTargetLanguage, KotlinRenderer, kotlinOptions } from "./language/Kotlin"; diff --git a/packages/quicktype-core/src/input/CompressedJSON.ts b/packages/quicktype-core/src/input/CompressedJSON.ts index cb3909e0d..2aa3355cf 100644 --- a/packages/quicktype-core/src/input/CompressedJSON.ts +++ b/packages/quicktype-core/src/input/CompressedJSON.ts @@ -1,10 +1,13 @@ import { addHashCode, hashCodeInit, hashString } from "collection-utils"; -import { defined, panic, assert } from "../support/Support"; -import { type TransformedStringTypeKind } from "../Type"; -import { isPrimitiveStringTypeKind, transformedStringTypeTargetTypeKindsMap } from "../Type"; -import { type DateTimeRecognizer } from "../DateTime"; import { inferTransformedStringTypeKindForString } from "../attributes/StringTypes"; +import { type DateTimeRecognizer } from "../DateTime"; +import { assert, defined, panic } from "../support/Support"; +import { + type TransformedStringTypeKind, + isPrimitiveStringTypeKind, + transformedStringTypeTargetTypeKindsMap +} from "../Type"; export enum Tag { Null = 1, diff --git a/packages/quicktype-core/src/input/FetchingJSONSchemaStore.ts b/packages/quicktype-core/src/input/FetchingJSONSchemaStore.ts index edd9a8824..4e7c132f5 100644 --- a/packages/quicktype-core/src/input/FetchingJSONSchemaStore.ts +++ b/packages/quicktype-core/src/input/FetchingJSONSchemaStore.ts @@ -1,7 +1,8 @@ -import { type JSONSchema } from "./JSONSchemaStore"; -import { JSONSchemaStore } from "./JSONSchemaStore"; +// eslint-disable-next-line import/no-cycle import { parseJSON } from ".."; + import { readFromFileOrURL } from "./io/NodeIO"; +import { type JSONSchema, JSONSchemaStore } from "./JSONSchemaStore"; export class FetchingJSONSchemaStore extends JSONSchemaStore { public constructor(private readonly _httpHeaders?: string[]) { diff --git a/packages/quicktype-core/src/input/Inference.ts b/packages/quicktype-core/src/input/Inference.ts index 07c1c52d3..a8dc6a772 100644 --- a/packages/quicktype-core/src/input/Inference.ts +++ b/packages/quicktype-core/src/input/Inference.ts @@ -1,17 +1,21 @@ -import { type Value, type CompressedJSON } from "./CompressedJSON"; -import { Tag, valueTag } from "./CompressedJSON"; -import { assertNever, defined, panic, assert } from "../support/Support"; -import { type TypeBuilder } from "../TypeBuilder"; -import { UnionBuilder, UnionAccumulator } from "../UnionBuilder"; -import { type ClassProperty } from "../Type"; -import { transformedStringTypeTargetTypeKindsMap, UnionType, ClassType, MapType, ArrayType } from "../Type"; -import { type TypeAttributes } from "../attributes/TypeAttributes"; -import { emptyTypeAttributes } from "../attributes/TypeAttributes"; import { StringTypes, inferTransformedStringTypeKindForString } from "../attributes/StringTypes"; -import { type TypeRef } from "../TypeGraph"; -import { derefTypeRef } from "../TypeGraph"; +import { type TypeAttributes, emptyTypeAttributes } from "../attributes/TypeAttributes"; import { messageError } from "../Messages"; +import { assert, assertNever, defined, panic } from "../support/Support"; +import { + ArrayType, + type ClassProperty, + ClassType, + MapType, + UnionType, + transformedStringTypeTargetTypeKindsMap +} from "../Type"; +import { type TypeBuilder } from "../TypeBuilder"; +import { type TypeRef, derefTypeRef } from "../TypeGraph"; import { nullableFromUnion } from "../TypeUtils"; +import { UnionAccumulator, UnionBuilder } from "../UnionBuilder"; + +import { type CompressedJSON, Tag, type Value, valueTag } from "./CompressedJSON"; // This should be the recursive type // Value[] | NestedValueArray[] diff --git a/packages/quicktype-core/src/input/Inputs.ts b/packages/quicktype-core/src/input/Inputs.ts index 5f57ac684..031d84ead 100644 --- a/packages/quicktype-core/src/input/Inputs.ts +++ b/packages/quicktype-core/src/input/Inputs.ts @@ -1,16 +1,17 @@ -import { iterableFirst, iterableFind, iterableSome, setFilterMap, withDefault, arrayMapSync } from "collection-utils"; +import { arrayMapSync, iterableFind, iterableFirst, iterableSome, setFilterMap, withDefault } from "collection-utils"; -import { type Value, type CompressedJSON } from "./CompressedJSON"; -import { CompressedJSONFromString } from "./CompressedJSON"; -import { panic, errorMessage, defined } from "../support/Support"; +import { descriptionTypeAttributeKind } from "../attributes/Description"; +import { makeNamesTypeAttributes } from "../attributes/TypeNames"; +// eslint-disable-next-line import/no-cycle +import { languageNamed } from "../language/All"; import { messageError } from "../Messages"; +import { type RunContext } from "../Run"; +import { defined, errorMessage, panic } from "../support/Support"; +import { type TargetLanguage } from "../TargetLanguage"; import { type TypeBuilder } from "../TypeBuilder"; -import { makeNamesTypeAttributes } from "../attributes/TypeNames"; -import { descriptionTypeAttributeKind } from "../attributes/Description"; + +import { type CompressedJSON, CompressedJSONFromString, type Value } from "./CompressedJSON"; import { TypeInference } from "./Inference"; -import { type TargetLanguage } from "../TargetLanguage"; -import { type RunContext } from "../Run"; -import { languageNamed } from "../language/All"; export interface Input { addSource: (source: T) => Promise; diff --git a/packages/quicktype-core/src/input/JSONSchemaInput.ts b/packages/quicktype-core/src/input/JSONSchemaInput.ts index c0aa1c1b8..03ce2ea6c 100644 --- a/packages/quicktype-core/src/input/JSONSchemaInput.ts +++ b/packages/quicktype-core/src/input/JSONSchemaInput.ts @@ -1,54 +1,62 @@ -import URI from "urijs"; import { - setFilter, EqualityMap, - mapMap, - mapFromObject, - setSubtract, - mapFromIterable, - iterableFind, - mapSortBy, - mapMapSync, - mapMergeInto, - arrayMapSync, - arrayLast, + addHashCode, arrayGetFromEnd, - hashCodeOf, - hasOwnProperty, + arrayLast, + arrayMapSync, definedMap, - addHashCode, + // eslint-disable-next-line @typescript-eslint/no-redeclare + hasOwnProperty, + hashCodeOf, + hashString, + iterableFind, iterableFirst, - hashString + mapFromIterable, + mapFromObject, + mapMap, + mapMapSync, + mapMergeInto, + mapSortBy, + setFilter, + setSubtract } from "collection-utils"; +import URI from "urijs"; -import { type PrimitiveTypeKind, type TransformedStringTypeKind } from "../Type"; -import { transformedStringTypeTargetTypeKindsMap, isNumberTypeKind } from "../Type"; -import { type StringMap } from "../support/Support"; -import { panic, assertNever, assert, defined, parseJSON } from "../support/Support"; -import { type TypeBuilder } from "../TypeBuilder"; -import { TypeNames } from "../attributes/TypeNames"; -import { makeNamesTypeAttributes, modifyTypeNames, singularizeTypeNames } from "../attributes/TypeNames"; -import { type TypeAttributes } from "../attributes/TypeAttributes"; -import { makeTypeAttributesInferred, emptyTypeAttributes, combineTypeAttributes } from "../attributes/TypeAttributes"; -import { type JSONSchema } from "./JSONSchemaStore"; -import { JSONSchemaStore } from "./JSONSchemaStore"; -import { messageAssert, messageError } from "../Messages"; +import { accessorNamesAttributeProducer } from "../attributes/AccessorNames"; +import { + minMaxAttributeProducer, + minMaxLengthAttributeProducer, + patternAttributeProducer +} from "../attributes/Constraints"; +// eslint-disable-next-line import/no-cycle +import { descriptionAttributeProducer } from "../attributes/Description"; +import { enumValuesAttributeProducer } from "../attributes/EnumValues"; import { StringTypes } from "../attributes/StringTypes"; - -import { type TypeRef } from "../TypeGraph"; +import { + type TypeAttributes, + combineTypeAttributes, + emptyTypeAttributes, + makeTypeAttributesInferred +} from "../attributes/TypeAttributes"; +import { TypeNames, makeNamesTypeAttributes, modifyTypeNames, singularizeTypeNames } from "../attributes/TypeNames"; +import { uriSchemaAttributesProducer } from "../attributes/URIAttributes"; +import { messageAssert, messageError } from "../Messages"; import { type RunContext } from "../Run"; +import { type StringMap, assert, assertNever, defined, panic, parseJSON } from "../support/Support"; +import { + type PrimitiveTypeKind, + type TransformedStringTypeKind, + isNumberTypeKind, + transformedStringTypeTargetTypeKindsMap +} from "../Type"; +import { type TypeBuilder } from "../TypeBuilder"; +import { type TypeRef } from "../TypeGraph"; + import { type Input } from "./Inputs"; +import { type JSONSchema, JSONSchemaStore } from "./JSONSchemaStore"; // There's a cyclic import here. Ignoring now because it requires a large refactor. // skipcq: JS-E1008 -import { descriptionAttributeProducer } from "../attributes/Description"; - -import { accessorNamesAttributeProducer } from "../attributes/AccessorNames"; -import { enumValuesAttributeProducer } from "../attributes/EnumValues"; -import { minMaxAttributeProducer } from "../attributes/Constraints"; -import { minMaxLengthAttributeProducer } from "../attributes/Constraints"; -import { patternAttributeProducer } from "../attributes/Constraints"; -import { uriSchemaAttributesProducer } from "../attributes/URIAttributes"; export enum PathElementKind { Root = 1, diff --git a/packages/quicktype-core/src/input/JSONSchemaStore.ts b/packages/quicktype-core/src/input/JSONSchemaStore.ts index 9fe5c62ec..4292bf08c 100644 --- a/packages/quicktype-core/src/input/JSONSchemaStore.ts +++ b/packages/quicktype-core/src/input/JSONSchemaStore.ts @@ -1,5 +1,4 @@ -import { type StringMap } from "../support/Support"; -import { assert } from "../support/Support"; +import { type StringMap, assert } from "../support/Support"; export type JSONSchema = StringMap | boolean; diff --git a/packages/quicktype-core/src/input/PostmanCollection.ts b/packages/quicktype-core/src/input/PostmanCollection.ts index 7d4a4b7b2..ce554ffb5 100644 --- a/packages/quicktype-core/src/input/PostmanCollection.ts +++ b/packages/quicktype-core/src/input/PostmanCollection.ts @@ -1,4 +1,5 @@ import { parseJSON } from "../support/Support"; + import { type JSONSourceData } from "./Inputs"; function isValidJSON (s: string): boolean { diff --git a/packages/quicktype-core/src/input/io/NodeIO.ts b/packages/quicktype-core/src/input/io/NodeIO.ts index fdc63b6b5..e310087b7 100644 --- a/packages/quicktype-core/src/input/io/NodeIO.ts +++ b/packages/quicktype-core/src/input/io/NodeIO.ts @@ -1,12 +1,15 @@ import * as fs from "fs"; -import { type Readable } from "readable-stream"; -import { isNode } from "browser-or-node"; -import { getStream } from "./get-stream"; + import { defined, exceptionToString } from "@glideapps/ts-necessities"; +import { isNode } from "browser-or-node"; +import fetch from "cross-fetch"; +import isURL from "is-url"; +import { type Readable } from "readable-stream"; + +// eslint-disable-next-line import/no-cycle import { messageError, panic } from "../../index"; -import isURL from "is-url"; -import fetch from "cross-fetch"; +import { getStream } from "./get-stream"; interface HttpHeaders { [key: string]: string; diff --git a/packages/quicktype-core/src/input/io/get-stream/buffer-stream.ts b/packages/quicktype-core/src/input/io/get-stream/buffer-stream.ts index 16ea64a20..063f2794e 100644 --- a/packages/quicktype-core/src/input/io/get-stream/buffer-stream.ts +++ b/packages/quicktype-core/src/input/io/get-stream/buffer-stream.ts @@ -1,6 +1,7 @@ -import { type Options } from "."; import { PassThrough } from "readable-stream"; +import { type Options } from "."; + export default function bufferStream(opts: Options) { opts = Object.assign({}, opts); diff --git a/packages/quicktype-core/src/input/io/get-stream/index.ts b/packages/quicktype-core/src/input/io/get-stream/index.ts index d8d067cae..4ae2d3ae7 100644 --- a/packages/quicktype-core/src/input/io/get-stream/index.ts +++ b/packages/quicktype-core/src/input/io/get-stream/index.ts @@ -1,4 +1,5 @@ import { type Readable } from "readable-stream"; + import bufferStream from "./buffer-stream"; export interface Options { diff --git a/packages/quicktype-core/src/language/All.ts b/packages/quicktype-core/src/language/All.ts index 91cb4b1a0..ee6648e59 100644 --- a/packages/quicktype-core/src/language/All.ts +++ b/packages/quicktype-core/src/language/All.ts @@ -2,31 +2,32 @@ import { iterableFind } from "collection-utils"; import { type TargetLanguage } from "../TargetLanguage"; -import { CSharpTargetLanguage } from "./CSharp"; -import { GoTargetLanguage } from "./Golang"; import { CJSONTargetLanguage } from "./CJSON"; import { CPlusPlusTargetLanguage } from "./CPlusPlus"; -import { ObjectiveCTargetLanguage } from "./Objective-C"; +import { CrystalTargetLanguage } from "./Crystal"; +import { CSharpTargetLanguage } from "./CSharp"; +import { DartTargetLanguage } from "./Dart"; +import { ElmTargetLanguage } from "./Elm"; +import { GoTargetLanguage } from "./Golang"; +import { HaskellTargetLanguage } from "./Haskell"; import { JavaTargetLanguage } from "./Java"; import { JavaScriptTargetLanguage } from "./JavaScript"; +// eslint-disable-next-line import/no-cycle import { JavaScriptPropTypesTargetLanguage } from "./JavaScriptPropTypes"; -import { TypeScriptTargetLanguage, FlowTargetLanguage } from "./TypeScriptFlow"; -import { SwiftTargetLanguage } from "./Swift"; +import { JSONSchemaTargetLanguage } from "./JSONSchema"; import { KotlinTargetLanguage } from "./Kotlin"; +import { ObjectiveCTargetLanguage } from "./Objective-C"; +import { PhpTargetLanguage } from "./Php"; +import { PikeTargetLanguage } from "./Pike"; +import { PythonTargetLanguage } from "./Python"; +import { RubyTargetLanguage } from "./ruby"; +import { RustTargetLanguage } from "./Rust"; import { Scala3TargetLanguage } from "./Scala3"; import { SmithyTargetLanguage } from "./Smithy4s"; -import { ElmTargetLanguage } from "./Elm"; -import { JSONSchemaTargetLanguage } from "./JSONSchema"; -import { RustTargetLanguage } from "./Rust"; -import { CrystalTargetLanguage } from "./Crystal"; -import { RubyTargetLanguage } from "./ruby"; -import { DartTargetLanguage } from "./Dart"; -import { PythonTargetLanguage } from "./Python"; -import { PikeTargetLanguage } from "./Pike"; -import { HaskellTargetLanguage } from "./Haskell"; -import { TypeScriptZodTargetLanguage } from "./TypeScriptZod"; -import { PhpTargetLanguage } from "./Php"; +import { SwiftTargetLanguage } from "./Swift"; import { TypeScriptEffectSchemaTargetLanguage } from "./TypeScriptEffectSchema"; +import { FlowTargetLanguage, TypeScriptTargetLanguage } from "./TypeScriptFlow"; +import { TypeScriptZodTargetLanguage } from "./TypeScriptZod"; export const all: TargetLanguage[] = [ new CSharpTargetLanguage(), @@ -54,18 +55,15 @@ export const all: TargetLanguage[] = [ new HaskellTargetLanguage(), new TypeScriptZodTargetLanguage(), new TypeScriptEffectSchemaTargetLanguage(), - new PhpTargetLanguage(), + new PhpTargetLanguage() ]; -export function languageNamed (name: string, targetLanguages?: TargetLanguage[]): TargetLanguage | undefined { +export function languageNamed(name: string, targetLanguages?: TargetLanguage[]): TargetLanguage | undefined { if (targetLanguages === undefined) { targetLanguages = all; } - const maybeTargetLanguage = iterableFind( - targetLanguages, - l => l.names.includes(name) || l.displayName === name, - ); + const maybeTargetLanguage = iterableFind(targetLanguages, l => l.names.includes(name) || l.displayName === name); if (maybeTargetLanguage !== undefined) return maybeTargetLanguage; return iterableFind(targetLanguages, l => l.extension === name); } diff --git a/packages/quicktype-core/src/language/CJSON.ts b/packages/quicktype-core/src/language/CJSON.ts index 84d1c41eb..0bfd40f57 100644 --- a/packages/quicktype-core/src/language/CJSON.ts +++ b/packages/quicktype-core/src/language/CJSON.ts @@ -22,30 +22,25 @@ */ /* Imports */ -import { TargetLanguage } from "../TargetLanguage"; -import { type Type, type TypeKind } from "../Type"; -import { ClassType, ArrayType, MapType, EnumType, UnionType } from "../Type"; -import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { type NameStyle, type Name, type Namer } from "../Naming"; -import { funPrefixNamer } from "../Naming"; +import { getAccessorName } from "../attributes/AccessorNames"; +import { enumCaseValues } from "../attributes/EnumValues"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { type Name, type NameStyle, type Namer, funPrefixNamer } from "../Naming"; +import { type RenderContext } from "../Renderer"; +import { EnumOption, type Option, type OptionValues, StringOption, getOptionValues } from "../RendererOptions"; import { type Sourcelike } from "../Source"; -import { type NamingStyle } from "../support/Strings"; import { + type NamingStyle, allUpperWordStyle, - legalizeCharacters, isAscii, isLetterOrUnderscoreOrDigit, + legalizeCharacters, makeNameStyle } from "../support/Strings"; -import { defined, assertNever, panic, numberEnumValues } from "../support/Support"; -import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Option, type OptionValues } from "../RendererOptions"; -import { EnumOption, StringOption, getOptionValues } from "../RendererOptions"; -import { assert } from "../support/Support"; -import { type RenderContext } from "../Renderer"; -import { getAccessorName } from "../attributes/AccessorNames"; -import { enumCaseValues } from "../attributes/EnumValues"; +import { assert, assertNever, defined, numberEnumValues, panic } from "../support/Support"; +import { TargetLanguage } from "../TargetLanguage"; +import { ArrayType, ClassType, EnumType, MapType, type Type, type TypeKind, UnionType } from "../Type"; +import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; /* Naming styles */ const pascalValue: [string, NamingStyle] = ["pascal-case", "pascal"]; diff --git a/packages/quicktype-core/src/language/CPlusPlus.ts b/packages/quicktype-core/src/language/CPlusPlus.ts index f5ec4f5f0..b75f834f6 100644 --- a/packages/quicktype-core/src/language/CPlusPlus.ts +++ b/packages/quicktype-core/src/language/CPlusPlus.ts @@ -1,42 +1,56 @@ import { - setUnion, arrayIntercalate, - toReadonlyArray, - iterableFirst, iterableFind, + iterableFirst, iterableSome, + setUnion, + toReadonlyArray, withDefault } from "collection-utils"; -import { TargetLanguage } from "../TargetLanguage"; -import { type Type, type TypeKind, type ClassProperty } from "../Type"; -import { ClassType, ArrayType, MapType, EnumType, UnionType } from "../Type"; -import { nullableFromUnion, matchType, removeNullFromUnion, isNamedType, directlyReachableTypes } from "../TypeUtils"; -import { type NameStyle, type Name, type Namer } from "../Naming"; -import { funPrefixNamer, DependencyName } from "../Naming"; -import { type Sourcelike } from "../Source"; -import { maybeAnnotated } from "../Source"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { type NamingStyle } from "../support/Strings"; +import { getAccessorName } from "../attributes/AccessorNames"; import { - legalizeCharacters, + type MinMaxConstraint, + minMaxLengthForType, + minMaxValueForType, + patternForType +} from "../attributes/Constraints"; +import { enumCaseValues } from "../attributes/EnumValues"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { type Declaration } from "../DeclarationIR"; +import { DependencyName, type Name, type NameStyle, type Namer, funPrefixNamer } from "../Naming"; +import { type RenderContext } from "../Renderer"; +import { + BooleanOption, + EnumOption, + type Option, + type OptionValues, + StringOption, + getOptionValues +} from "../RendererOptions"; +import { type Sourcelike, maybeAnnotated } from "../Source"; +import { + type NamingStyle, isAscii, isLetterOrUnderscoreOrDigit, - stringEscape, - makeNameStyle + legalizeCharacters, + makeNameStyle, + stringEscape } from "../support/Strings"; -import { defined, assertNever, panic, numberEnumValues } from "../support/Support"; -import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Option, type OptionValues } from "../RendererOptions"; -import { StringOption, EnumOption, BooleanOption, getOptionValues } from "../RendererOptions"; -import { assert } from "../support/Support"; -import { type Declaration } from "../DeclarationIR"; -import { type RenderContext } from "../Renderer"; -import { getAccessorName } from "../attributes/AccessorNames"; -import { enumCaseValues } from "../attributes/EnumValues"; -import { type MinMaxConstraint } from "../attributes/Constraints"; -import { minMaxValueForType, minMaxLengthForType, patternForType } from "../attributes/Constraints"; +import { assert, assertNever, defined, numberEnumValues, panic } from "../support/Support"; +import { TargetLanguage } from "../TargetLanguage"; +import { + ArrayType, + type ClassProperty, + ClassType, + EnumType, + MapType, + type Type, + type TypeKind, + UnionType +} from "../Type"; +import { directlyReachableTypes, isNamedType, matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; const pascalValue: [string, NamingStyle] = ["pascal-case", "pascal"]; const underscoreValue: [string, NamingStyle] = ["underscore-case", "underscore"]; @@ -164,12 +178,12 @@ export class CPlusPlusTargetLanguage extends TargetLanguage { } function constraintsForType(t: Type): - | { - minMax?: MinMaxConstraint; - minMaxLength?: MinMaxConstraint; - pattern?: string; - } - | undefined { +| { + minMax?: MinMaxConstraint; + minMaxLength?: MinMaxConstraint; + pattern?: string; +} +| undefined { const minMax = minMaxValueForType(t); const minMaxLength = minMaxLengthForType(t); const pattern = patternForType(t); @@ -1361,11 +1375,11 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { pattern === undefined ? this._nulloptType : [ - this._stringType.getType(), - "(", - this._stringType.createStringLiteral([stringEscape(pattern)]), - ")" - ], + this._stringType.getType(), + "(", + this._stringType.createStringLiteral([stringEscape(pattern)]), + ")" + ], ")" ]); }); diff --git a/packages/quicktype-core/src/language/CSharp.ts b/packages/quicktype-core/src/language/CSharp.ts index f87193182..54c0de48d 100644 --- a/packages/quicktype-core/src/language/CSharp.ts +++ b/packages/quicktype-core/src/language/CSharp.ts @@ -1,57 +1,64 @@ import { arrayIntercalate } from "collection-utils"; +import unicode from "unicode-properties"; +import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; +import { minMaxLengthForType, minMaxValueForType } from "../attributes/Constraints"; +import { ConvenienceRenderer, type ForbiddenWordsInfo, inferredNameOrder } from "../ConvenienceRenderer"; +import { DependencyName, type Name, type Namer, SimpleName, funPrefixNamer } from "../Naming"; +import { type RenderContext } from "../Renderer"; import { - type Type, - type ClassProperty, - type TransformedStringTypeKind, - type PrimitiveStringTypeKind, - type PrimitiveType -} from "../Type"; -import { EnumType, UnionType, ClassType, ArrayType } from "../Type"; -import { matchType, nullableFromUnion, removeNullFromUnion, directlyReachableSingleNamedType } from "../TypeUtils"; -import { type Sourcelike } from "../Source"; -import { maybeAnnotated, modifySource } from "../Source"; -import { type WordInName } from "../support/Strings"; + BooleanOption, + EnumOption, + type Option, + type OptionValues, + StringOption, + getOptionValues +} from "../RendererOptions"; +import { type Sourcelike, maybeAnnotated, modifySource } from "../Source"; import { - utf16LegalizeCharacters, - utf16StringEscape, - splitIntoWords, + type WordInName, + camelCase, combineWords, firstUpperWordStyle, - camelCase + splitIntoWords, + utf16LegalizeCharacters, + utf16StringEscape } from "../support/Strings"; -import { defined, assert, panic, assertNever } from "../support/Support"; -import { type Name, type Namer } from "../Naming"; -import { DependencyName, funPrefixNamer, SimpleName } from "../Naming"; -import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { ConvenienceRenderer, inferredNameOrder } from "../ConvenienceRenderer"; +import { assert, assertNever, defined, panic } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; -import { type Option, type OptionValues } from "../RendererOptions"; -import { StringOption, EnumOption, BooleanOption, getOptionValues } from "../RendererOptions"; -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { type StringTypeMapping } from "../TypeBuilder"; -import { type Transformer, type Transformation } from "../Transformers"; import { - followTargetType, - transformationForType, - DecodingTransformer, - DecodingChoiceTransformer, - UnionInstantiationTransformer, + ArrayDecodingTransformer, + ArrayEncodingTransformer, ChoiceTransformer, - UnionMemberMatchTransformer, + DecodingChoiceTransformer, + DecodingTransformer, EncodingTransformer, + MinMaxLengthCheckTransformer, + MinMaxValueTransformer, + ParseStringTransformer, StringMatchTransformer, StringProducerTransformer, - ParseStringTransformer, StringifyTransformer, - ArrayDecodingTransformer, - ArrayEncodingTransformer, - MinMaxLengthCheckTransformer, - MinMaxValueTransformer + type Transformation, + type Transformer, + UnionInstantiationTransformer, + UnionMemberMatchTransformer, + followTargetType, + transformationForType } from "../Transformers"; -import { type RenderContext } from "../Renderer"; -import { minMaxLengthForType, minMaxValueForType } from "../attributes/Constraints"; -import unicode from "unicode-properties"; +import { + ArrayType, + type ClassProperty, + ClassType, + EnumType, + type PrimitiveStringTypeKind, + type PrimitiveType, + type TransformedStringTypeKind, + type Type, + UnionType +} from "../Type"; +import { type StringTypeMapping } from "../TypeBuilder"; +import { directlyReachableSingleNamedType, matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; export enum Framework { Newtonsoft = "Newtonsoft", diff --git a/packages/quicktype-core/src/language/Crystal.ts b/packages/quicktype-core/src/language/Crystal.ts index 05708f30a..1376c488c 100644 --- a/packages/quicktype-core/src/language/Crystal.ts +++ b/packages/quicktype-core/src/language/Crystal.ts @@ -1,29 +1,26 @@ -import { TargetLanguage } from "../TargetLanguage"; -import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; +import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../Naming"; +import { type RenderContext } from "../Renderer"; +import { type Option } from "../RendererOptions"; +import { type Sourcelike, maybeAnnotated } from "../Source"; import { - legalizeCharacters, - splitIntoWords, - isLetterOrUnderscoreOrDigit, - combineWords, allLowerWordStyle, + combineWords, + escapeNonPrintableMapper, firstUpperWordStyle, intToHex, - utf32ConcatMap, - escapeNonPrintableMapper, - isPrintable, isAscii, - isLetterOrUnderscore + isLetterOrUnderscore, + isLetterOrUnderscoreOrDigit, + isPrintable, + legalizeCharacters, + splitIntoWords, + utf32ConcatMap } from "../support/Strings"; -import { type Name, type Namer } from "../Naming"; -import { funPrefixNamer } from "../Naming"; -import { type UnionType, type Type, type ClassType, type EnumType } from "../Type"; +import { TargetLanguage } from "../TargetLanguage"; +import { type ClassType, type EnumType, type Type, type UnionType } from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { type Sourcelike } from "../Source"; -import { maybeAnnotated } from "../Source"; -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { type Option } from "../RendererOptions"; -import { type RenderContext } from "../Renderer"; export class CrystalTargetLanguage extends TargetLanguage { protected makeRenderer(renderContext: RenderContext): CrystalRenderer { diff --git a/packages/quicktype-core/src/language/Dart.ts b/packages/quicktype-core/src/language/Dart.ts index a30e797a1..71360e7d1 100644 --- a/packages/quicktype-core/src/language/Dart.ts +++ b/packages/quicktype-core/src/language/Dart.ts @@ -1,15 +1,9 @@ -import { - type ClassProperty, - type ClassType, - type PrimitiveStringTypeKind, - type TransformedStringTypeKind, - type Type, - type UnionType -} from "../Type"; -import { EnumType } from "../Type"; -import { directlyReachableSingleNamedType, matchType, nullableFromUnion } from "../TypeUtils"; -import { type Sourcelike } from "../Source"; -import { maybeAnnotated, modifySource } from "../Source"; +import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { DependencyName, type Name, type Namer, funPrefixNamer } from "../Naming"; +import { type RenderContext } from "../Renderer"; +import { BooleanOption, type Option, type OptionValues, StringOption, getOptionValues } from "../RendererOptions"; +import { type Sourcelike, maybeAnnotated, modifySource } from "../Source"; import { allLowerWordStyle, allUpperWordStyle, @@ -27,19 +21,19 @@ import { utf16ConcatMap, utf16LegalizeCharacters } from "../support/Strings"; - -import { type StringTypeMapping } from "../TypeBuilder"; - -import { type Name, type Namer } from "../Naming"; -import { DependencyName, funPrefixNamer } from "../Naming"; -import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { TargetLanguage } from "../TargetLanguage"; -import { type Option, type OptionValues } from "../RendererOptions"; -import { BooleanOption, getOptionValues, StringOption } from "../RendererOptions"; -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; import { defined } from "../support/Support"; -import { type RenderContext } from "../Renderer"; +import { TargetLanguage } from "../TargetLanguage"; +import { + type ClassProperty, + type ClassType, + EnumType, + type PrimitiveStringTypeKind, + type TransformedStringTypeKind, + type Type, + type UnionType +} from "../Type"; +import { type StringTypeMapping } from "../TypeBuilder"; +import { directlyReachableSingleNamedType, matchType, nullableFromUnion } from "../TypeUtils"; export const dartOptions = { nullSafety: new BooleanOption("null-safety", "Null Safety", true), @@ -204,8 +198,8 @@ function dartNameStyle(startWithUpper: boolean, upperUnderscore: boolean, origin const firstWordStyle = upperUnderscore ? allUpperWordStyle : startWithUpper - ? firstUpperWordStyle - : allLowerWordStyle; + ? firstUpperWordStyle + : allLowerWordStyle; const restWordStyle = upperUnderscore ? allUpperWordStyle : firstUpperWordStyle; return combineWords( words, diff --git a/packages/quicktype-core/src/language/Elm.ts b/packages/quicktype-core/src/language/Elm.ts index a9c81776e..426764b63 100644 --- a/packages/quicktype-core/src/language/Elm.ts +++ b/packages/quicktype-core/src/language/Elm.ts @@ -1,33 +1,35 @@ -import { mapContains, arrayIntercalate } from "collection-utils"; +import { arrayIntercalate, mapContains } from "collection-utils"; -import { TargetLanguage } from "../TargetLanguage"; -import { type Option, type OptionValues } from "../RendererOptions"; -import { EnumOption, StringOption, BooleanOption, getOptionValues } from "../RendererOptions"; -import { type Type, type ClassType, type EnumType, type ClassProperty } from "../Type"; -import { UnionType } from "../Type"; -import { matchType, nullableFromUnion } from "../TypeUtils"; -import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Namer, type Name } from "../Naming"; -import { DependencyName, funPrefixNamer } from "../Naming"; +import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { DependencyName, type Name, type Namer, funPrefixNamer } from "../Naming"; +import { type RenderContext } from "../Renderer"; import { - legalizeCharacters, - isLetterOrUnderscoreOrDigit, - isLetterOrUnderscore, + BooleanOption, + EnumOption, + type Option, + type OptionValues, + StringOption, + getOptionValues +} from "../RendererOptions"; +import { type MultiWord, type Sourcelike, annotated, multiWord, parenIfNeeded, singleWord } from "../Source"; +import { + allLowerWordStyle, + allUpperWordStyle, + combineWords, decapitalize, - stringEscape, + firstUpperWordStyle, isAscii, + isLetterOrUnderscore, + isLetterOrUnderscoreOrDigit, + legalizeCharacters, splitIntoWords, - combineWords, - firstUpperWordStyle, - allLowerWordStyle, - allUpperWordStyle + stringEscape } from "../support/Strings"; import { defined } from "../support/Support"; -import { type Sourcelike, type MultiWord } from "../Source"; -import { annotated, singleWord, multiWord, parenIfNeeded } from "../Source"; -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { type RenderContext } from "../Renderer"; +import { TargetLanguage } from "../TargetLanguage"; +import { type ClassProperty, type ClassType, type EnumType, type Type, UnionType } from "../Type"; +import { matchType, nullableFromUnion } from "../TypeUtils"; export const elmOptions = { justTypes: new BooleanOption("just-types", "Plain types only", false), diff --git a/packages/quicktype-core/src/language/Golang.ts b/packages/quicktype-core/src/language/Golang.ts index 0dd4afcb5..277c083f5 100644 --- a/packages/quicktype-core/src/language/Golang.ts +++ b/packages/quicktype-core/src/language/Golang.ts @@ -1,29 +1,25 @@ -import { type TypeKind, type Type, type ClassType, type EnumType, type ClassProperty } from "../Type"; -import { UnionType } from "../Type"; -import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { type Name, type Namer } from "../Naming"; -import { DependencyName, funPrefixNamer } from "../Naming"; +import { type PrimitiveStringTypeKind, type StringTypeMapping, type TransformedStringTypeKind } from ".."; +import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; +import { ConvenienceRenderer } from "../ConvenienceRenderer"; +import { DependencyName, type Name, type Namer, funPrefixNamer } from "../Naming"; +import { type RenderContext } from "../Renderer"; +import { BooleanOption, type Option, type OptionValues, StringOption, getOptionValues } from "../RendererOptions"; +import { type Sourcelike, maybeAnnotated, modifySource } from "../Source"; import { - legalizeCharacters, + allUpperWordStyle, + camelCase, + combineWords, + firstUpperWordStyle, isLetterOrUnderscore, isLetterOrUnderscoreOrDigit, - stringEscape, + legalizeCharacters, splitIntoWords, - combineWords, - firstUpperWordStyle, - allUpperWordStyle, - camelCase + stringEscape } from "../support/Strings"; import { assert, defined } from "../support/Support"; -import { type Option, type OptionValues } from "../RendererOptions"; -import { StringOption, BooleanOption, getOptionValues } from "../RendererOptions"; -import { type Sourcelike } from "../Source"; -import { maybeAnnotated, modifySource } from "../Source"; -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; import { TargetLanguage } from "../TargetLanguage"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type RenderContext } from "../Renderer"; -import { type StringTypeMapping, type TransformedStringTypeKind, type PrimitiveStringTypeKind } from ".."; +import { type ClassProperty, type ClassType, type EnumType, type Type, type TypeKind, UnionType } from "../Type"; +import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; export const goOptions = { justTypes: new BooleanOption("just-types", "Plain types only", false), diff --git a/packages/quicktype-core/src/language/Haskell.ts b/packages/quicktype-core/src/language/Haskell.ts index f33ce9927..7b7b7ef49 100644 --- a/packages/quicktype-core/src/language/Haskell.ts +++ b/packages/quicktype-core/src/language/Haskell.ts @@ -1,28 +1,32 @@ import { mapContains } from "collection-utils"; -import { TargetLanguage } from "../TargetLanguage"; -import { type Option, type OptionValues } from "../RendererOptions"; -import { EnumOption, StringOption, BooleanOption, getOptionValues } from "../RendererOptions"; -import { type Type, type ClassType, type UnionType, type EnumType, type ClassProperty } from "../Type"; -import { matchType, nullableFromUnion } from "../TypeUtils"; -import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Namer, type Name } from "../Naming"; -import { funPrefixNamer } from "../Naming"; + +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../Naming"; +import { type RenderContext } from "../Renderer"; import { - legalizeCharacters, - isLetterOrUnderscoreOrDigit, - isLetterOrUnderscore, - stringEscape, - isAscii, - splitIntoWords, + BooleanOption, + EnumOption, + type Option, + type OptionValues, + StringOption, + getOptionValues +} from "../RendererOptions"; +import { type MultiWord, type Sourcelike, multiWord, parenIfNeeded, singleWord } from "../Source"; +import { + allLowerWordStyle, + allUpperWordStyle, combineWords, firstUpperWordStyle, - allLowerWordStyle, - allUpperWordStyle + isAscii, + isLetterOrUnderscore, + isLetterOrUnderscoreOrDigit, + legalizeCharacters, + splitIntoWords, + stringEscape } from "../support/Strings"; -import { type Sourcelike, type MultiWord } from "../Source"; -import { singleWord, multiWord, parenIfNeeded } from "../Source"; -import { type RenderContext } from "../Renderer"; +import { TargetLanguage } from "../TargetLanguage"; +import { type ClassProperty, type ClassType, type EnumType, type Type, type UnionType } from "../Type"; +import { matchType, nullableFromUnion } from "../TypeUtils"; export const haskellOptions = { justTypes: new BooleanOption("just-types", "Plain types only", false), diff --git a/packages/quicktype-core/src/language/JSONSchema.ts b/packages/quicktype-core/src/language/JSONSchema.ts index 612bd7310..ab7e85b1e 100644 --- a/packages/quicktype-core/src/language/JSONSchema.ts +++ b/packages/quicktype-core/src/language/JSONSchema.ts @@ -1,25 +1,28 @@ -import { mapFirst, iterableFirst } from "collection-utils"; +import { iterableFirst, mapFirst } from "collection-utils"; -import { TargetLanguage } from "../TargetLanguage"; -import { type Type, type UnionType, type EnumType, type ObjectType } from "../Type"; -import { transformedStringTypeTargetTypeKindsMap } from "../Type"; -import { matchTypeExhaustive } from "../TypeUtils"; +import { addDescriptionToSchema } from "../attributes/Description"; import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Namer, type Name } from "../Naming"; -import { funPrefixNamer } from "../Naming"; +import { type Name, type Namer, funPrefixNamer } from "../Naming"; +import { type RenderContext } from "../Renderer"; +import { type Option } from "../RendererOptions"; import { - legalizeCharacters, - splitIntoWords, + allUpperWordStyle, combineWords, firstUpperWordStyle, - allUpperWordStyle + legalizeCharacters, + splitIntoWords } from "../support/Strings"; import { defined, panic } from "../support/Support"; -import { type StringTypeMapping } from "../TypeBuilder"; -import { getNoStringTypeMapping } from "../TypeBuilder"; -import { addDescriptionToSchema } from "../attributes/Description"; -import { type Option } from "../RendererOptions"; -import { type RenderContext } from "../Renderer"; +import { TargetLanguage } from "../TargetLanguage"; +import { + type EnumType, + type ObjectType, + type Type, + type UnionType, + transformedStringTypeTargetTypeKindsMap +} from "../Type"; +import { type StringTypeMapping, getNoStringTypeMapping } from "../TypeBuilder"; +import { matchTypeExhaustive } from "../TypeUtils"; export class JSONSchemaTargetLanguage extends TargetLanguage { public constructor() { diff --git a/packages/quicktype-core/src/language/Java.ts b/packages/quicktype-core/src/language/Java.ts index 25b975ad2..7080be5e9 100644 --- a/packages/quicktype-core/src/language/Java.ts +++ b/packages/quicktype-core/src/language/Java.ts @@ -1,14 +1,18 @@ +import { type PrimitiveStringTypeKind, type StringTypeMapping, type TransformedStringTypeKind } from ".."; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Name, type Namer } from "../Naming"; -import { DependencyName, funPrefixNamer } from "../Naming"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { DependencyName, type Name, type Namer, funPrefixNamer } from "../Naming"; import { type RenderContext } from "../Renderer"; -import { type Option, type OptionValues } from "../RendererOptions"; -import { BooleanOption, EnumOption, getOptionValues, StringOption } from "../RendererOptions"; -import { type Sourcelike } from "../Source"; -import { maybeAnnotated } from "../Source"; -import { acronymOption, acronymStyle, AcronymStyleOptions } from "../support/Acronyms"; +import { + BooleanOption, + EnumOption, + type Option, + type OptionValues, + StringOption, + getOptionValues +} from "../RendererOptions"; +import { type Sourcelike, maybeAnnotated } from "../Source"; +import { AcronymStyleOptions, acronymOption, acronymStyle } from "../support/Acronyms"; import { allLowerWordStyle, allUpperWordStyle, @@ -26,10 +30,17 @@ import { } from "../support/Strings"; import { assert, assertNever, defined, panic } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; -import { type ClassProperty, type Type, type TypeKind } from "../Type"; -import { ArrayType, ClassType, EnumType, MapType, UnionType } from "../Type"; +import { + ArrayType, + type ClassProperty, + ClassType, + EnumType, + MapType, + type Type, + type TypeKind, + UnionType +} from "../Type"; import { directlyReachableSingleNamedType, matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { type StringTypeMapping, type TransformedStringTypeKind, type PrimitiveStringTypeKind } from ".."; export const javaOptions = { useList: new EnumOption( diff --git a/packages/quicktype-core/src/language/JavaScript.ts b/packages/quicktype-core/src/language/JavaScript.ts index 5b1b1b7c8..0cf29f4ff 100644 --- a/packages/quicktype-core/src/language/JavaScript.ts +++ b/packages/quicktype-core/src/language/JavaScript.ts @@ -1,39 +1,35 @@ import { arrayIntercalate } from "collection-utils"; +import { ConvenienceRenderer } from "../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../Naming"; +import { type RenderContext } from "../Renderer"; +import { BooleanOption, EnumOption, type Option, type OptionValues, getOptionValues } from "../RendererOptions"; +import { type Sourcelike, modifySource } from "../Source"; +import { AcronymStyleOptions, acronymOption, acronymStyle } from "../support/Acronyms"; +import { ConvertersOptions, convertersOption } from "../support/Converters"; import { - type TransformedStringTypeKind, - type PrimitiveStringTypeKind, - type Type, - type ClassProperty, - type ClassType, - type ObjectType -} from "../Type"; -import { matchType, directlyReachableSingleNamedType } from "../TypeUtils"; -import { acronymOption, acronymStyle, AcronymStyleOptions } from "../support/Acronyms"; -import { convertersOption, ConvertersOptions } from "../support/Converters"; - -import { - utf16LegalizeCharacters, - utf16StringEscape, - splitIntoWords, + allLowerWordStyle, + camelCase, capitalize, combineWords, firstUpperWordStyle, - camelCase, - allLowerWordStyle + splitIntoWords, + utf16LegalizeCharacters, + utf16StringEscape } from "../support/Strings"; import { panic } from "../support/Support"; - -import { type Sourcelike } from "../Source"; -import { modifySource } from "../Source"; -import { type Namer, type Name } from "../Naming"; -import { funPrefixNamer } from "../Naming"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; import { TargetLanguage } from "../TargetLanguage"; +import { + type ClassProperty, + type ClassType, + type ObjectType, + type PrimitiveStringTypeKind, + type TransformedStringTypeKind, + type Type +} from "../Type"; import { type StringTypeMapping } from "../TypeBuilder"; -import { type Option, type OptionValues } from "../RendererOptions"; -import { BooleanOption, getOptionValues, EnumOption } from "../RendererOptions"; -import { type RenderContext } from "../Renderer"; +import { directlyReachableSingleNamedType, matchType } from "../TypeUtils"; + import { isES3IdentifierPart, isES3IdentifierStart } from "./JavaScriptUnicodeMaps"; export const javaScriptOptions = { diff --git a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts index 3b9348f0b..cbdd4e6ad 100644 --- a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts +++ b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts @@ -1,20 +1,27 @@ -import { TargetLanguage } from "../TargetLanguage"; -import { type Option, type OptionValues } from "../RendererOptions"; -import { getOptionValues, EnumOption } from "../RendererOptions"; -import { type RenderContext } from "../Renderer"; +import { panic } from "@glideapps/ts-necessities"; +import { arrayIntercalate } from "collection-utils"; + import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Name, type Namer } from "../Naming"; -import { funPrefixNamer } from "../Naming"; -import { acronymOption, acronymStyle, AcronymStyleOptions } from "../support/Acronyms"; -import { type ClassProperty, type ClassType, type ObjectType, type Sourcelike, type Type } from ".."; -import { capitalize, combineWords, firstUpperWordStyle, matchType, panic, splitIntoWords } from ".."; -import { allLowerWordStyle, utf16StringEscape } from "../support/Strings"; -import { isES3IdentifierStart } from "./JavaScriptUnicodeMaps"; -import { legalizeName } from "./JavaScript"; +import { type Name, type Namer, funPrefixNamer } from "../Naming"; +import { type RenderContext } from "../Renderer"; +import { EnumOption, type Option, type OptionValues, getOptionValues } from "../RendererOptions"; +import { type Sourcelike } from "../Source"; +import { AcronymStyleOptions, acronymOption, acronymStyle } from "../support/Acronyms"; import { convertersOption } from "../support/Converters"; -import { directlyReachableSingleNamedType } from "../TypeUtils"; -import { arrayIntercalate } from "collection-utils"; -import { PrimitiveType } from "../Type"; +import { + allLowerWordStyle, + capitalize, + combineWords, + firstUpperWordStyle, + splitIntoWords, + utf16StringEscape +} from "../support/Strings"; +import { TargetLanguage } from "../TargetLanguage"; +import { type ClassProperty, type ClassType, type ObjectType, PrimitiveType, type Type } from "../Type"; +import { directlyReachableSingleNamedType, matchType } from "../TypeUtils"; + +import { legalizeName } from "./JavaScript"; +import { isES3IdentifierStart } from "./JavaScriptUnicodeMaps"; export const javaScriptPropTypesOptions = { acronymStyle: acronymOption(AcronymStyleOptions.Pascal), diff --git a/packages/quicktype-core/src/language/Kotlin.ts b/packages/quicktype-core/src/language/Kotlin.ts index b2f46b466..f6fcebb04 100644 --- a/packages/quicktype-core/src/language/Kotlin.ts +++ b/packages/quicktype-core/src/language/Kotlin.ts @@ -1,14 +1,12 @@ -import { iterableSome, arrayIntercalate } from "collection-utils"; +import { arrayIntercalate, iterableSome } from "collection-utils"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Name, type Namer } from "../Naming"; -import { funPrefixNamer } from "../Naming"; -import { type Option, type OptionValues } from "../RendererOptions"; -import { EnumOption, StringOption, getOptionValues } from "../RendererOptions"; -import { type Sourcelike } from "../Source"; -import { maybeAnnotated, modifySource } from "../Source"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../Naming"; +import { type RenderContext } from "../Renderer"; +import { EnumOption, type Option, type OptionValues, StringOption, getOptionValues } from "../RendererOptions"; +import { type Sourcelike, maybeAnnotated, modifySource } from "../Source"; +import { AcronymStyleOptions, acronymOption, acronymStyle } from "../support/Acronyms"; import { allLowerWordStyle, allUpperWordStyle, @@ -27,11 +25,18 @@ import { } from "../support/Strings"; import { assertNever, mustNotHappen } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; -import { type ClassProperty, type EnumType, type ObjectType, type PrimitiveType, type Type } from "../Type"; -import { ArrayType, ClassType, MapType, UnionType } from "../Type"; +import { + ArrayType, + type ClassProperty, + ClassType, + type EnumType, + MapType, + type ObjectType, + type PrimitiveType, + type Type, + UnionType +} from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { type RenderContext } from "../Renderer"; -import { acronymOption, acronymStyle, AcronymStyleOptions } from "../support/Acronyms"; export enum Framework { None = "None", diff --git a/packages/quicktype-core/src/language/Objective-C.ts b/packages/quicktype-core/src/language/Objective-C.ts index 2dc5612f1..f6d3e47d5 100644 --- a/packages/quicktype-core/src/language/Objective-C.ts +++ b/packages/quicktype-core/src/language/Objective-C.ts @@ -1,34 +1,35 @@ -import { iterableSome, iterableFirst, mapContains, mapFirst, mapSome } from "collection-utils"; +import { iterableFirst, iterableSome, mapContains, mapFirst, mapSome } from "collection-utils"; +import unicode from "unicode-properties"; -import { TargetLanguage } from "../TargetLanguage"; -import { type ClassProperty } from "../Type"; -import { Type, ClassType, EnumType, ArrayType, MapType, UnionType } from "../Type"; -import { matchType, nullableFromUnion, isAnyOrNull } from "../TypeUtils"; -import { type Name } from "../Naming"; -import { Namer, funPrefixNamer } from "../Naming"; -import { type Sourcelike } from "../Source"; -import { modifySource } from "../Source"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { type Name, Namer, funPrefixNamer } from "../Naming"; +import { type RenderContext } from "../Renderer"; import { - splitIntoWords, - combineWords, - firstUpperWordStyle, - allUpperWordStyle, + BooleanOption, + EnumOption, + type Option, + type OptionValues, + StringOption, + getOptionValues +} from "../RendererOptions"; +import { type Sourcelike, modifySource } from "../Source"; +import { + addPrefixIfNecessary, allLowerWordStyle, + allUpperWordStyle, camelCase, - utf16LegalizeCharacters, - stringEscape, - addPrefixIfNecessary, + combineWords, + fastIsUpperCase, + firstUpperWordStyle, repeatString, - fastIsUpperCase + splitIntoWords, + stringEscape, + utf16LegalizeCharacters } from "../support/Strings"; -import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Option, type OptionValues } from "../RendererOptions"; -import { StringOption, BooleanOption, EnumOption, getOptionValues } from "../RendererOptions"; import { assert, defined } from "../support/Support"; -import { type RenderContext } from "../Renderer"; - -import unicode from "unicode-properties"; +import { TargetLanguage } from "../TargetLanguage"; +import { ArrayType, type ClassProperty, ClassType, EnumType, MapType, Type, UnionType } from "../Type"; +import { isAnyOrNull, matchType, nullableFromUnion } from "../TypeUtils"; export type MemoryAttribute = "assign" | "strong" | "copy"; export interface OutputFeatures { diff --git a/packages/quicktype-core/src/language/Php.ts b/packages/quicktype-core/src/language/Php.ts index 8a7eaa40b..fd0888dcf 100644 --- a/packages/quicktype-core/src/language/Php.ts +++ b/packages/quicktype-core/src/language/Php.ts @@ -1,14 +1,13 @@ +import * as _ from "lodash"; + +import { type PrimitiveStringTypeKind, type StringTypeMapping, type TransformedStringTypeKind } from ".."; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Name, type Namer } from "../Naming"; -import { DependencyName, funPrefixNamer } from "../Naming"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { DependencyName, type Name, type Namer, funPrefixNamer } from "../Naming"; import { type RenderContext } from "../Renderer"; -import { type Option, type OptionValues } from "../RendererOptions"; -import { BooleanOption, getOptionValues } from "../RendererOptions"; -import { type Sourcelike } from "../Source"; -import { maybeAnnotated } from "../Source"; -import { acronymOption, acronymStyle, AcronymStyleOptions } from "../support/Acronyms"; +import { BooleanOption, type Option, type OptionValues, getOptionValues } from "../RendererOptions"; +import { type Sourcelike, maybeAnnotated } from "../Source"; +import { AcronymStyleOptions, acronymOption, acronymStyle } from "../support/Acronyms"; import { allLowerWordStyle, allUpperWordStyle, @@ -27,8 +26,6 @@ import { defined } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; import { type ClassProperty, type ClassType, type EnumType, type Type, type UnionType } from "../Type"; import { directlyReachableSingleNamedType, matchType, nullableFromUnion } from "../TypeUtils"; -import { type StringTypeMapping, type TransformedStringTypeKind, type PrimitiveStringTypeKind } from ".."; -import * as _ from "lodash"; export const phpOptions = { withGet: new BooleanOption("with-get", "Create Getter", true), diff --git a/packages/quicktype-core/src/language/Pike.ts b/packages/quicktype-core/src/language/Pike.ts index 637bedcac..dc57a3fc4 100644 --- a/packages/quicktype-core/src/language/Pike.ts +++ b/packages/quicktype-core/src/language/Pike.ts @@ -1,16 +1,12 @@ -import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Name, type Namer } from "../Naming"; -import { funPrefixNamer } from "../Naming"; -import { type Option } from "../RendererOptions"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../Naming"; import { type RenderContext } from "../Renderer"; -import { type MultiWord, type Sourcelike } from "../Source"; -import { multiWord, parenIfNeeded, singleWord } from "../Source"; +import { type Option } from "../RendererOptions"; +import { type MultiWord, type Sourcelike, multiWord, parenIfNeeded, singleWord } from "../Source"; +import { isLetterOrUnderscoreOrDigit, legalizeCharacters, makeNameStyle, stringEscape } from "../support/Strings"; import { TargetLanguage } from "../TargetLanguage"; -import { type Type, type ClassType, type EnumType, type UnionType } from "../Type"; -import { ArrayType, MapType, PrimitiveType } from "../Type"; +import { ArrayType, type ClassType, type EnumType, MapType, PrimitiveType, type Type, type UnionType } from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { legalizeCharacters, isLetterOrUnderscoreOrDigit, stringEscape, makeNameStyle } from "../support/Strings"; export const pikeOptions = {}; diff --git a/packages/quicktype-core/src/language/Python.ts b/packages/quicktype-core/src/language/Python.ts index 5edc549b2..b6092a9d1 100644 --- a/packages/quicktype-core/src/language/Python.ts +++ b/packages/quicktype-core/src/language/Python.ts @@ -1,51 +1,54 @@ -import { TargetLanguage } from "../TargetLanguage"; -import { type StringTypeMapping } from "../TypeBuilder"; -import { type TransformedStringTypeKind, type PrimitiveStringTypeKind, type Type, type ClassProperty } from "../Type"; -import { EnumType, ClassType, UnionType } from "../Type"; +import { + arrayIntercalate, + iterableFirst, + iterableSome, + mapSortBy, + mapUpdateInto, + setUnionInto +} from "collection-utils"; +import unicode from "unicode-properties"; + +import { ConvenienceRenderer, type ForbiddenWordsInfo, topLevelNameOrder } from "../ConvenienceRenderer"; +import { DependencyName, type Name, type Namer, funPrefixNamer } from "../Naming"; import { type RenderContext } from "../Renderer"; -import { type Option, type OptionValues } from "../RendererOptions"; -import { getOptionValues, EnumOption, BooleanOption } from "../RendererOptions"; -import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { ConvenienceRenderer, topLevelNameOrder } from "../ConvenienceRenderer"; -import { type Namer, type Name } from "../Naming"; -import { funPrefixNamer, DependencyName } from "../Naming"; +import { BooleanOption, EnumOption, type Option, type OptionValues, getOptionValues } from "../RendererOptions"; +import { type MultiWord, type Sourcelike, modifySource, multiWord, parenIfNeeded, singleWord } from "../Source"; import { - splitIntoWords, + allLowerWordStyle, + allUpperWordStyle, combineWords, firstUpperWordStyle, - utf16LegalizeCharacters, - allUpperWordStyle, - allLowerWordStyle, + originalWord, + splitIntoWords, stringEscape, - originalWord + utf16LegalizeCharacters } from "../support/Strings"; -import { assertNever, panic, defined } from "../support/Support"; -import { type Sourcelike, type MultiWord } from "../Source"; -import { multiWord, singleWord, parenIfNeeded, modifySource } from "../Source"; -import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { type Transformer } from "../Transformers"; +import { assertNever, defined, panic } from "../support/Support"; +import { TargetLanguage } from "../TargetLanguage"; import { - followTargetType, - transformationForType, - DecodingChoiceTransformer, ChoiceTransformer, + DecodingChoiceTransformer, DecodingTransformer, - UnionInstantiationTransformer, + EncodingTransformer, ParseStringTransformer, - UnionMemberMatchTransformer, StringifyTransformer, - EncodingTransformer + type Transformer, + UnionInstantiationTransformer, + UnionMemberMatchTransformer, + followTargetType, + transformationForType } from "../Transformers"; import { - arrayIntercalate, - setUnionInto, - mapUpdateInto, - iterableSome, - mapSortBy, - iterableFirst -} from "collection-utils"; - -import unicode from "unicode-properties"; + type ClassProperty, + ClassType, + EnumType, + type PrimitiveStringTypeKind, + type TransformedStringTypeKind, + type Type, + UnionType +} from "../Type"; +import { type StringTypeMapping } from "../TypeBuilder"; +import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; const forbiddenTypeNames = [ "Any", diff --git a/packages/quicktype-core/src/language/Rust.ts b/packages/quicktype-core/src/language/Rust.ts index 9c69ed654..f73a67f7b 100644 --- a/packages/quicktype-core/src/language/Rust.ts +++ b/packages/quicktype-core/src/language/Rust.ts @@ -1,34 +1,29 @@ import { mapFirst } from "collection-utils"; -import { TargetLanguage } from "../TargetLanguage"; -import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; +import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../Naming"; +import { type RenderContext } from "../Renderer"; +import { BooleanOption, EnumOption, type Option, type OptionValues, getOptionValues } from "../RendererOptions"; +import { type Sourcelike, maybeAnnotated } from "../Source"; import { - legalizeCharacters, - splitIntoWords, - isLetterOrUnderscoreOrDigit, - combineWords, allLowerWordStyle, + combineWords, + escapeNonPrintableMapper, firstUpperWordStyle, intToHex, - utf32ConcatMap, - escapeNonPrintableMapper, - isPrintable, isAscii, - isLetterOrUnderscore + isLetterOrUnderscore, + isLetterOrUnderscoreOrDigit, + isPrintable, + legalizeCharacters, + splitIntoWords, + utf32ConcatMap } from "../support/Strings"; -import { type Name, type Namer } from "../Naming"; -import { funPrefixNamer } from "../Naming"; -import { type Type, type ClassType, type EnumType } from "../Type"; -import { UnionType } from "../Type"; -import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { type Sourcelike } from "../Source"; -import { maybeAnnotated } from "../Source"; -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { type Option, type OptionValues } from "../RendererOptions"; -import { BooleanOption, EnumOption, getOptionValues } from "../RendererOptions"; import { defined } from "../support/Support"; -import { type RenderContext } from "../Renderer"; +import { TargetLanguage } from "../TargetLanguage"; +import { type ClassType, type EnumType, type Type, UnionType } from "../Type"; +import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; export enum Density { Normal = "Normal", diff --git a/packages/quicktype-core/src/language/Scala3.ts b/packages/quicktype-core/src/language/Scala3.ts index 843c2ad4d..a736ecada 100644 --- a/packages/quicktype-core/src/language/Scala3.ts +++ b/packages/quicktype-core/src/language/Scala3.ts @@ -1,12 +1,9 @@ import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Name, type Namer } from "../Naming"; -import { funPrefixNamer } from "../Naming"; -import { type Option, type OptionValues } from "../RendererOptions"; -import { EnumOption, StringOption, getOptionValues } from "../RendererOptions"; -import { type Sourcelike } from "../Source"; -import { maybeAnnotated } from "../Source"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../Naming"; +import { type RenderContext } from "../Renderer"; +import { EnumOption, type Option, type OptionValues, StringOption, getOptionValues } from "../RendererOptions"; +import { type Sourcelike, maybeAnnotated } from "../Source"; import { allLowerWordStyle, allUpperWordStyle, @@ -20,10 +17,17 @@ import { } from "../support/Strings"; import { assertNever } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; -import { type ClassProperty, type ClassType, type EnumType, type ObjectType, type Type, type UnionType } from "../Type"; -import { ArrayType, MapType } from "../Type"; +import { + ArrayType, + type ClassProperty, + type ClassType, + type EnumType, + MapType, + type ObjectType, + type Type, + type UnionType +} from "../Type"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { type RenderContext } from "../Renderer"; export enum Framework { None = "None", diff --git a/packages/quicktype-core/src/language/Smithy4s.ts b/packages/quicktype-core/src/language/Smithy4s.ts index 0b28a824e..24ba6b028 100644 --- a/packages/quicktype-core/src/language/Smithy4s.ts +++ b/packages/quicktype-core/src/language/Smithy4s.ts @@ -1,12 +1,9 @@ import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Name, type Namer } from "../Naming"; -import { funPrefixNamer } from "../Naming"; -import { type Option, type OptionValues } from "../RendererOptions"; -import { EnumOption, StringOption, getOptionValues } from "../RendererOptions"; -import { type Sourcelike } from "../Source"; -import { maybeAnnotated } from "../Source"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../Naming"; +import { type RenderContext } from "../Renderer"; +import { EnumOption, type Option, type OptionValues, StringOption, getOptionValues } from "../RendererOptions"; +import { type Sourcelike, maybeAnnotated } from "../Source"; import { allLowerWordStyle, allUpperWordStyle, @@ -20,10 +17,17 @@ import { } from "../support/Strings"; import { assertNever } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; -import { type ClassProperty, type ClassType, type EnumType, type ObjectType, type Type, type UnionType } from "../Type"; -import { ArrayType, MapType } from "../Type"; +import { + ArrayType, + type ClassProperty, + type ClassType, + type EnumType, + MapType, + type ObjectType, + type Type, + type UnionType +} from "../Type"; import { matchCompoundType, matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { type RenderContext } from "../Renderer"; export enum Framework { None = "None" diff --git a/packages/quicktype-core/src/language/Swift.ts b/packages/quicktype-core/src/language/Swift.ts index 25cf19e02..627218116 100644 --- a/packages/quicktype-core/src/language/Swift.ts +++ b/packages/quicktype-core/src/language/Swift.ts @@ -1,50 +1,53 @@ import { arrayIntercalate } from "collection-utils"; -import { assert, defined } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; -import { - type Type, - type ClassType, - type UnionType, - type TypeKind, - type ClassProperty, - type TransformedStringTypeKind, - type PrimitiveStringTypeKind -} from "../Type"; -import { EnumType, ArrayType, MapType } from "../Type"; -import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { type Name, type Namer } from "../Naming"; -import { funPrefixNamer } from "../Naming"; -import { type Option, type OptionValues } from "../RendererOptions"; -import { BooleanOption, EnumOption, StringOption, getOptionValues } from "../RendererOptions"; -import { type Sourcelike } from "../Source"; -import { maybeAnnotated, modifySource } from "../Source"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { type DateTimeRecognizer, DefaultDateTimeRecognizer } from "../DateTime"; +import { type Name, type Namer, funPrefixNamer } from "../Naming"; +import { type ForEachPosition, type RenderContext } from "../Renderer"; import { - legalizeCharacters, + BooleanOption, + EnumOption, + type Option, + type OptionValues, + StringOption, + getOptionValues +} from "../RendererOptions"; +import { type Sourcelike, maybeAnnotated, modifySource } from "../Source"; +import { AcronymStyleOptions, acronymOption, acronymStyle } from "../support/Acronyms"; +import { + addPrefixIfNecessary, + allLowerWordStyle, + allUpperWordStyle, + camelCase, + combineWords, + escapeNonPrintableMapper, + firstUpperWordStyle, + intToHex, + isDigit, isLetterOrUnderscore, isNumeric, - isDigit, - utf32ConcatMap, - escapeNonPrintableMapper, isPrintable, - intToHex, + legalizeCharacters, splitIntoWords, - combineWords, - firstUpperWordStyle, - allLowerWordStyle, - allUpperWordStyle, - camelCase, - addPrefixIfNecessary + utf32ConcatMap } from "../support/Strings"; -import { type RenderContext, type ForEachPosition } from "../Renderer"; +import { assert, defined, panic } from "../support/Support"; +import { TargetLanguage } from "../TargetLanguage"; +import { + ArrayType, + type ClassProperty, + type ClassType, + EnumType, + MapType, + type PrimitiveStringTypeKind, + type TransformedStringTypeKind, + type Type, + type TypeKind, + type UnionType +} from "../Type"; import { type StringTypeMapping } from "../TypeBuilder"; -import { panic } from "../support/Support"; -import { type DateTimeRecognizer } from "../DateTime"; -import { DefaultDateTimeRecognizer } from "../DateTime"; -import { acronymOption, acronymStyle, AcronymStyleOptions } from "../support/Acronyms"; +import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; const MAX_SAMELINE_PROPERTIES = 4; diff --git a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts index 772260388..9db2d827a 100644 --- a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts +++ b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts @@ -1,13 +1,11 @@ import { arrayIntercalate } from "collection-utils"; -import { type ClassProperty, type ObjectType, type Type } from "../Type"; -import { ArrayType, EnumType, MapType } from "../Type"; -import { matchType } from "../TypeUtils"; -import { type Name, type Namer } from "../Naming"; -import { funPrefixNamer } from "../Naming"; + +import { ConvenienceRenderer } from "../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../Naming"; import { type RenderContext } from "../Renderer"; -import { type Option, type OptionValues } from "../RendererOptions"; -import { BooleanOption, getOptionValues } from "../RendererOptions"; -import { acronymStyle, AcronymStyleOptions } from "../support/Acronyms"; +import { BooleanOption, type Option, type OptionValues, getOptionValues } from "../RendererOptions"; +import { type Sourcelike } from "../Source"; +import { AcronymStyleOptions, acronymStyle } from "../support/Acronyms"; import { allLowerWordStyle, capitalize, @@ -18,11 +16,12 @@ import { stringEscape, utf16StringEscape } from "../support/Strings"; +import { panic } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; +import { ArrayType, type ClassProperty, EnumType, MapType, type ObjectType, type Type } from "../Type"; +import { matchType } from "../TypeUtils"; + import { legalizeName } from "./JavaScript"; -import { type Sourcelike } from "../Source"; -import { panic } from "../support/Support"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; export const typeScriptEffectSchemaOptions = { justSchema: new BooleanOption("just-schema", "Schema only", false) diff --git a/packages/quicktype-core/src/language/TypeScriptFlow.ts b/packages/quicktype-core/src/language/TypeScriptFlow.ts index e7a12f58c..f63c2d473 100644 --- a/packages/quicktype-core/src/language/TypeScriptFlow.ts +++ b/packages/quicktype-core/src/language/TypeScriptFlow.ts @@ -1,19 +1,20 @@ -import { type Type, type ClassType } from "../Type"; -import { ArrayType, UnionType, EnumType } from "../Type"; -import { matchType, nullableFromUnion, isNamedType } from "../TypeUtils"; -import { utf16StringEscape, camelCase } from "../support/Strings"; - -import { type Sourcelike, type MultiWord } from "../Source"; -import { modifySource, singleWord, parenIfNeeded, multiWord } from "../Source"; -import { type Name, type Namer } from "../Naming"; -import { funPrefixNamer } from "../Naming"; -import { type Option, type OptionValues } from "../RendererOptions"; -import { BooleanOption, getOptionValues } from "../RendererOptions"; -import { type JavaScriptTypeAnnotations } from "./JavaScript"; -import { javaScriptOptions, JavaScriptTargetLanguage, JavaScriptRenderer, legalizeName } from "./JavaScript"; +import { type Name, type Namer, funPrefixNamer } from "../Naming"; +import { type RenderContext } from "../Renderer"; +import { BooleanOption, type Option, type OptionValues, getOptionValues } from "../RendererOptions"; +import { type MultiWord, type Sourcelike, modifySource, multiWord, parenIfNeeded, singleWord } from "../Source"; +import { camelCase, utf16StringEscape } from "../support/Strings"; import { defined, panic } from "../support/Support"; import { type TargetLanguage } from "../TargetLanguage"; -import { type RenderContext } from "../Renderer"; +import { ArrayType, type ClassType, EnumType, type Type, UnionType } from "../Type"; +import { isNamedType, matchType, nullableFromUnion } from "../TypeUtils"; + +import { + JavaScriptRenderer, + JavaScriptTargetLanguage, + type JavaScriptTypeAnnotations, + javaScriptOptions, + legalizeName +} from "./JavaScript"; import { isES3IdentifierStart } from "./JavaScriptUnicodeMaps"; export const tsFlowOptions = Object.assign({}, javaScriptOptions, { diff --git a/packages/quicktype-core/src/language/TypeScriptZod.ts b/packages/quicktype-core/src/language/TypeScriptZod.ts index abc84f71e..d52c4eff7 100644 --- a/packages/quicktype-core/src/language/TypeScriptZod.ts +++ b/packages/quicktype-core/src/language/TypeScriptZod.ts @@ -1,22 +1,10 @@ -import { type StringTypeMapping } from "TypeBuilder"; import { arrayIntercalate } from "collection-utils"; + import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Name, type Namer } from "../Naming"; -import { funPrefixNamer } from "../Naming"; +import { type Name, type Namer, funPrefixNamer } from "../Naming"; import { type RenderContext } from "../Renderer"; -import { type Option, type OptionValues } from "../RendererOptions"; -import { BooleanOption, getOptionValues } from "../RendererOptions"; +import { BooleanOption, type Option, type OptionValues, getOptionValues } from "../RendererOptions"; import { type Sourcelike } from "../Source"; -import { TargetLanguage } from "../TargetLanguage"; -import { - type ClassProperty, - type EnumType, - type PrimitiveStringTypeKind, - type TransformedStringTypeKind, - type Type -} from "../Type"; -import { ArrayType, ClassType, ObjectType, SetOperationType } from "../Type"; -import { matchType } from "../TypeUtils"; import { AcronymStyleOptions, acronymStyle } from "../support/Acronyms"; import { allLowerWordStyle, @@ -29,6 +17,21 @@ import { utf16StringEscape } from "../support/Strings"; import { panic } from "../support/Support"; +import { TargetLanguage } from "../TargetLanguage"; +import { + ArrayType, + type ClassProperty, + ClassType, + type EnumType, + ObjectType, + type PrimitiveStringTypeKind, + SetOperationType, + type TransformedStringTypeKind, + type Type +} from "../Type"; +import { type StringTypeMapping } from "../TypeBuilder"; +import { matchType } from "../TypeUtils"; + import { legalizeName } from "./JavaScript"; export const typeScriptZodOptions = { diff --git a/packages/quicktype-core/src/language/ruby/index.ts b/packages/quicktype-core/src/language/ruby/index.ts index 1776a3964..10abe40d6 100644 --- a/packages/quicktype-core/src/language/ruby/index.ts +++ b/packages/quicktype-core/src/language/ruby/index.ts @@ -1,38 +1,46 @@ import unicode from "unicode-properties"; -import { type Sourcelike } from "../../Source"; -import { modifySource } from "../../Source"; -import { type Name } from "../../Naming"; -import { Namer } from "../../Naming"; -import { type ForbiddenWordsInfo } from "../../ConvenienceRenderer"; -import { ConvenienceRenderer } from "../../ConvenienceRenderer"; -import { TargetLanguage } from "../../TargetLanguage"; -import { type Option, type OptionValues } from "../../RendererOptions"; -import { BooleanOption, EnumOption, getOptionValues, StringOption } from "../../RendererOptions"; - -import * as keywords from "./keywords"; - -const forbiddenForObjectProperties = Array.from(new Set([...keywords.keywords, ...keywords.reservedProperties])); - -import { type Type, type EnumType, type UnionType, type ClassProperty } from "../../Type"; -import { ClassType, ArrayType, MapType } from "../../Type"; -import { matchType, nullableFromUnion, removeNullFromUnion } from "../../TypeUtils"; - +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../../ConvenienceRenderer"; +import { type Name, Namer } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { + BooleanOption, + EnumOption, + type Option, + type OptionValues, + StringOption, + getOptionValues +} from "../../RendererOptions"; +import { type Sourcelike, modifySource } from "../../Source"; import { - legalizeCharacters, - splitIntoWords, - combineWords, - firstUpperWordStyle, - allUpperWordStyle, allLowerWordStyle, - utf32ConcatMap, - isPrintable, + allUpperWordStyle, + combineWords, escapeNonPrintableMapper, + firstUpperWordStyle, intToHex, + isLetterOrUnderscore, + isPrintable, + legalizeCharacters, snakeCase, - isLetterOrUnderscore + splitIntoWords, + utf32ConcatMap } from "../../support/Strings"; -import { type RenderContext } from "../../Renderer"; +import { TargetLanguage } from "../../TargetLanguage"; +import { + ArrayType, + type ClassProperty, + ClassType, + type EnumType, + MapType, + type Type, + type UnionType +} from "../../Type"; +import { matchType, nullableFromUnion, removeNullFromUnion } from "../../TypeUtils"; + +import * as keywords from "./keywords"; + +const forbiddenForObjectProperties = Array.from(new Set([...keywords.keywords, ...keywords.reservedProperties])); function unicodeEscape(codePoint: number): string { return "\\u{" + intToHex(codePoint, 0) + "}"; diff --git a/packages/quicktype-core/src/rewrites/CombineClasses.ts b/packages/quicktype-core/src/rewrites/CombineClasses.ts index 4dac053fb..3fc7a29fc 100644 --- a/packages/quicktype-core/src/rewrites/CombineClasses.ts +++ b/packages/quicktype-core/src/rewrites/CombineClasses.ts @@ -1,12 +1,10 @@ -import { type Type, type ClassProperty } from "../Type"; -import { ClassType, setOperationCasesEqual } from "../Type"; -import { nonNullTypeCases, combineTypeAttributesOfTypes } from "../TypeUtils"; - import { type GraphRewriteBuilder } from "../GraphRewriting"; +import { type RunContext } from "../Run"; import { assert, panic } from "../support/Support"; +import { type ClassProperty, ClassType, type Type, setOperationCasesEqual } from "../Type"; import { type TypeGraph, type TypeRef } from "../TypeGraph"; +import { combineTypeAttributesOfTypes, nonNullTypeCases } from "../TypeUtils"; import { unifyTypes, unionBuilderForUnification } from "../UnifyClasses"; -import { type RunContext } from "../Run"; const REQUIRED_OVERLAP = 3 / 4; diff --git a/packages/quicktype-core/src/rewrites/ExpandStrings.ts b/packages/quicktype-core/src/rewrites/ExpandStrings.ts index 0482f0032..c1ee3331e 100644 --- a/packages/quicktype-core/src/rewrites/ExpandStrings.ts +++ b/packages/quicktype-core/src/rewrites/ExpandStrings.ts @@ -1,22 +1,22 @@ import { + areEqual, iterableFirst, - mapFilter, - iterableSome, iterableReduce, - setUnion, + iterableSome, + mapFilter, setIntersect, setIsSuperset, - areEqual + setUnion } from "collection-utils"; -import { type PrimitiveType } from "../Type"; -import { stringTypesForType } from "../TypeUtils"; -import { type TypeGraph, type TypeRef } from "../TypeGraph"; -import { type GraphRewriteBuilder } from "../GraphRewriting"; -import { assert, defined } from "../support/Support"; -import { emptyTypeAttributes } from "../attributes/TypeAttributes"; import { StringTypes } from "../attributes/StringTypes"; +import { emptyTypeAttributes } from "../attributes/TypeAttributes"; +import { type GraphRewriteBuilder } from "../GraphRewriting"; import { type RunContext } from "../Run"; +import { assert, defined } from "../support/Support"; +import { type PrimitiveType } from "../Type"; +import { type TypeGraph, type TypeRef } from "../TypeGraph"; +import { stringTypesForType } from "../TypeUtils"; const MIN_LENGTH_FOR_ENUM = 10; diff --git a/packages/quicktype-core/src/rewrites/FlattenStrings.ts b/packages/quicktype-core/src/rewrites/FlattenStrings.ts index fa43717e5..6982a94da 100644 --- a/packages/quicktype-core/src/rewrites/FlattenStrings.ts +++ b/packages/quicktype-core/src/rewrites/FlattenStrings.ts @@ -1,12 +1,12 @@ import { iterableFirst } from "collection-utils"; -import { type PrimitiveType, type UnionType, type Type } from "../Type"; -import { stringTypesForType, combineTypeAttributesOfTypes } from "../TypeUtils"; -import { type TypeGraph, type TypeRef } from "../TypeGraph"; -import { type StringTypeMapping } from "../TypeBuilder"; +import { combineTypeAttributes } from "../attributes/TypeAttributes"; import { type GraphRewriteBuilder } from "../GraphRewriting"; import { assert, defined } from "../support/Support"; -import { combineTypeAttributes } from "../attributes/TypeAttributes"; +import { type PrimitiveType, type Type, type UnionType } from "../Type"; +import { type StringTypeMapping } from "../TypeBuilder"; +import { type TypeGraph, type TypeRef } from "../TypeGraph"; +import { combineTypeAttributesOfTypes, stringTypesForType } from "../TypeUtils"; // A union needs replacing if it contains more than one string type, one of them being // a basic string type. diff --git a/packages/quicktype-core/src/rewrites/FlattenUnions.ts b/packages/quicktype-core/src/rewrites/FlattenUnions.ts index a834002e8..cca90fca4 100644 --- a/packages/quicktype-core/src/rewrites/FlattenUnions.ts +++ b/packages/quicktype-core/src/rewrites/FlattenUnions.ts @@ -1,16 +1,14 @@ -import { setFilter, iterableSome } from "collection-utils"; +import { iterableSome, setFilter } from "collection-utils"; -import { type TypeGraph, type TypeRef } from "../TypeGraph"; -import { derefTypeRef } from "../TypeGraph"; -import { type Type } from "../Type"; -import { UnionType, IntersectionType } from "../Type"; -import { makeGroupsToFlatten } from "../TypeUtils"; -import { assert } from "../support/Support"; -import { type StringTypeMapping } from "../TypeBuilder"; +import { emptyTypeAttributes } from "../attributes/TypeAttributes"; import { type GraphRewriteBuilder } from "../GraphRewriting"; -import { unifyTypes, UnifyUnionBuilder } from "../UnifyClasses"; import { messageAssert } from "../Messages"; -import { emptyTypeAttributes } from "../attributes/TypeAttributes"; +import { assert } from "../support/Support"; +import { IntersectionType, type Type, UnionType } from "../Type"; +import { type StringTypeMapping } from "../TypeBuilder"; +import { type TypeGraph, type TypeRef, derefTypeRef } from "../TypeGraph"; +import { makeGroupsToFlatten } from "../TypeUtils"; +import { UnifyUnionBuilder, unifyTypes } from "../UnifyClasses"; export function flattenUnions( graph: TypeGraph, diff --git a/packages/quicktype-core/src/rewrites/InferMaps.ts b/packages/quicktype-core/src/rewrites/InferMaps.ts index 43e30182c..e63803745 100644 --- a/packages/quicktype-core/src/rewrites/InferMaps.ts +++ b/packages/quicktype-core/src/rewrites/InferMaps.ts @@ -1,15 +1,13 @@ -import { iterableFirst, iterableEvery, setMap } from "collection-utils"; +import { iterableEvery, iterableFirst, setMap } from "collection-utils"; -import { type Type, type ClassProperty } from "../Type"; -import { ClassType, setOperationCasesEqual, isPrimitiveStringTypeKind } from "../Type"; -import { removeNullFromType } from "../TypeUtils"; +import { type GraphRewriteBuilder } from "../GraphRewriting"; +import { type MarkovChain, evaluate, load } from "../MarkovChain"; import { defined, panic } from "../support/Support"; -import { type TypeGraph, type TypeRef } from "../TypeGraph"; +import { type ClassProperty, ClassType, type Type, isPrimitiveStringTypeKind, setOperationCasesEqual } from "../Type"; import { type StringTypeMapping } from "../TypeBuilder"; -import { type GraphRewriteBuilder } from "../GraphRewriting"; +import { type TypeGraph, type TypeRef } from "../TypeGraph"; +import { removeNullFromType } from "../TypeUtils"; import { unifyTypes, unionBuilderForUnification } from "../UnifyClasses"; -import { type MarkovChain } from "../MarkovChain"; -import { load, evaluate } from "../MarkovChain"; const mapSizeThreshold = 20; const stringMapSizeThreshold = 50; diff --git a/packages/quicktype-core/src/rewrites/ReplaceObjectType.ts b/packages/quicktype-core/src/rewrites/ReplaceObjectType.ts index 99acbc145..2e8504d62 100644 --- a/packages/quicktype-core/src/rewrites/ReplaceObjectType.ts +++ b/packages/quicktype-core/src/rewrites/ReplaceObjectType.ts @@ -1,11 +1,11 @@ -import { setFilter, iterableFirst, mapMap, setMap } from "collection-utils"; +import { iterableFirst, mapMap, setFilter, setMap } from "collection-utils"; -import { type TypeGraph, type TypeRef } from "../TypeGraph"; -import { type StringTypeMapping } from "../TypeBuilder"; +import { emptyTypeAttributes } from "../attributes/TypeAttributes"; import { type GraphRewriteBuilder } from "../GraphRewriting"; -import { type ObjectType, type ClassProperty } from "../Type"; import { defined } from "../support/Support"; -import { emptyTypeAttributes } from "../attributes/TypeAttributes"; +import { type ClassProperty, type ObjectType } from "../Type"; +import { type StringTypeMapping } from "../TypeBuilder"; +import { type TypeGraph, type TypeRef } from "../TypeGraph"; export function replaceObjectType( graph: TypeGraph, diff --git a/packages/quicktype-core/src/rewrites/ResolveIntersections.ts b/packages/quicktype-core/src/rewrites/ResolveIntersections.ts index a3a3016be..ffe2f8a64 100644 --- a/packages/quicktype-core/src/rewrites/ResolveIntersections.ts +++ b/packages/quicktype-core/src/rewrites/ResolveIntersections.ts @@ -1,36 +1,41 @@ import { - iterableFirst, iterableEvery, - setFilter, + iterableFind, + iterableFirst, + mapMap, mapMapEntries, mapMergeWithInto, - mapMap, mapUpdateInto, - setMap, - iterableFind, + setFilter, setIntersect, + setMap, setUnionInto } from "collection-utils"; -import { type TypeGraph, type TypeRef } from "../TypeGraph"; -import { type StringTypeMapping, type TypeBuilder } from "../TypeBuilder"; +import { + type TypeAttributes, + combineTypeAttributes, + emptyTypeAttributes, + makeTypeAttributesInferred +} from "../attributes/TypeAttributes"; import { type GraphRewriteBuilder, type TypeLookerUp } from "../GraphRewriting"; -import { type UnionTypeProvider, type TypeAttributeMap } from "../UnionBuilder"; -import { UnionBuilder } from "../UnionBuilder"; -import { type Type, type PrimitiveTypeKind, type TypeKind } from "../Type"; +import { assert, defined, mustNotHappen, panic } from "../support/Support"; import { + ArrayType, + GenericClassProperty, IntersectionType, + ObjectType, + type PrimitiveTypeKind, + type Type, + type TypeKind, UnionType, - ArrayType, - isPrimitiveTypeKind, isNumberTypeKind, - GenericClassProperty, - ObjectType + isPrimitiveTypeKind } from "../Type"; -import { setOperationMembersRecursively, matchTypeExhaustive, makeGroupsToFlatten } from "../TypeUtils"; -import { assert, defined, panic, mustNotHappen } from "../support/Support"; -import { type TypeAttributes } from "../attributes/TypeAttributes"; -import { combineTypeAttributes, emptyTypeAttributes, makeTypeAttributesInferred } from "../attributes/TypeAttributes"; +import { type StringTypeMapping, type TypeBuilder } from "../TypeBuilder"; +import { type TypeGraph, type TypeRef } from "../TypeGraph"; +import { makeGroupsToFlatten, matchTypeExhaustive, setOperationMembersRecursively } from "../TypeUtils"; +import { type TypeAttributeMap, UnionBuilder, type UnionTypeProvider } from "../UnionBuilder"; function canResolve(t: IntersectionType): boolean { const members = setOperationMembersRecursively(t, undefined)[0]; diff --git a/packages/quicktype-core/src/support/Acronyms.ts b/packages/quicktype-core/src/support/Acronyms.ts index 24a40dec1..8c3eabcf1 100644 --- a/packages/quicktype-core/src/support/Acronyms.ts +++ b/packages/quicktype-core/src/support/Acronyms.ts @@ -1,5 +1,7 @@ import { EnumOption } from "../RendererOptions"; -import { allUpperWordStyle, firstUpperWordStyle, originalWord, allLowerWordStyle } from "./Strings"; + +// eslint-disable-next-line import/no-cycle +import { allLowerWordStyle, allUpperWordStyle, firstUpperWordStyle, originalWord } from "./Strings"; export const acronyms: string[] = [ "aaa", @@ -1096,7 +1098,7 @@ export const acronyms: string[] = [ "zma", "zoi", "zope", - "zpl", + "zpl" ]; export enum AcronymStyleOptions { @@ -1114,19 +1116,19 @@ export const acronymOption = function (defaultOption: AcronymStyleOptions) { [AcronymStyleOptions.Original, AcronymStyleOptions.Original], [AcronymStyleOptions.Pascal, AcronymStyleOptions.Pascal], [AcronymStyleOptions.Camel, AcronymStyleOptions.Camel], - [AcronymStyleOptions.Lower, AcronymStyleOptions.Lower], + [AcronymStyleOptions.Lower, AcronymStyleOptions.Lower] ], defaultOption, - "secondary", + "secondary" ); }; -export function acronymStyle (style: AcronymStyleOptions): (s: string) => string { - const options: { [key: string]: (s: string) => string, } = { +export function acronymStyle(style: AcronymStyleOptions): (s: string) => string { + const options: { [key: string]: (s: string) => string } = { [AcronymStyleOptions.Pascal]: allUpperWordStyle, [AcronymStyleOptions.Camel]: firstUpperWordStyle, [AcronymStyleOptions.Original]: originalWord, - [AcronymStyleOptions.Lower]: allLowerWordStyle, + [AcronymStyleOptions.Lower]: allLowerWordStyle }; return options[style]; diff --git a/packages/quicktype-core/src/support/Strings.ts b/packages/quicktype-core/src/support/Strings.ts index 555b861f3..1ea40e3d6 100644 --- a/packages/quicktype-core/src/support/Strings.ts +++ b/packages/quicktype-core/src/support/Strings.ts @@ -1,7 +1,11 @@ -import { assert, defined, panic, assertNever } from "./Support"; -import { acronyms } from "./Acronyms"; +import unicode from "unicode-properties"; + import { messageAssert } from "../Messages"; +// eslint-disable-next-line import/no-cycle +import { acronyms } from "./Acronyms"; +import { assert, assertNever, defined, panic } from "./Support"; + export type NamingStyle = | "pascal" | "camel" @@ -10,8 +14,6 @@ export type NamingStyle = | "pascal-upper-acronyms" | "camel-upper-acronyms"; -import unicode from "unicode-properties"; - function computeAsciiMap(mapper: (codePoint: number) => string): { charNoEscapeMap: number[]; charStringMap: string[]; diff --git a/packages/quicktype-core/src/support/Support.ts b/packages/quicktype-core/src/support/Support.ts index 0fef6624a..31e78fd4b 100644 --- a/packages/quicktype-core/src/support/Support.ts +++ b/packages/quicktype-core/src/support/Support.ts @@ -1,8 +1,9 @@ import { Base64 } from "js-base64"; import * as pako from "pako"; -import { messageError } from "../Messages"; import * as YAML from "yaml"; +import { messageError } from "../Messages"; + export interface StringMap { [name: string]: any; } diff --git a/packages/quicktype-graphql-input/src/index.ts b/packages/quicktype-graphql-input/src/index.ts index c2cc29cbb..a6c1f53e2 100644 --- a/packages/quicktype-graphql-input/src/index.ts +++ b/packages/quicktype-graphql-input/src/index.ts @@ -1,39 +1,35 @@ +import { iterableFirst, mapFromObject, setMap } from "collection-utils"; +import * as graphql from "graphql/language"; import { + type DirectiveNode, type DocumentNode, - type SelectionSetNode, - type SelectionNode, - type OperationDefinitionNode, + type FieldNode, type FragmentDefinitionNode, - type DirectiveNode, - type FieldNode + type OperationDefinitionNode, + type SelectionNode, + type SelectionSetNode } from "graphql/language/ast"; -import * as graphql from "graphql/language"; -import { setMap, iterableFirst, mapFromObject } from "collection-utils"; - import { type ClassProperty, + type Input, + type RunContext, + StringTypes, + type TypeAttributes, type TypeBuilder, + TypeNames, type TypeRef, - type TypeAttributes, - type Input, - type RunContext -} from "quicktype-core"; -import { UnionType, - removeNullFromUnion, assertNever, - panic, - TypeNames, + derefTypeRef, + emptyTypeAttributes, makeNamesTypeAttributes, - namesTypeAttributeKind, messageAssert, - emptyTypeAttributes, - StringTypes, - derefTypeRef + namesTypeAttributeKind, + panic, + removeNullFromUnion } from "quicktype-core"; -import { type GraphQLSchema } from "./GraphQLSchema"; -import { TypeKind } from "./GraphQLSchema"; +import { type GraphQLSchema, TypeKind } from "./GraphQLSchema"; interface GQLType { description?: string; diff --git a/packages/quicktype-typescript-input/src/index.ts b/packages/quicktype-typescript-input/src/index.ts index 47696ce83..dc31c6e9d 100644 --- a/packages/quicktype-typescript-input/src/index.ts +++ b/packages/quicktype-typescript-input/src/index.ts @@ -1,15 +1,12 @@ +import { type PartialArgs, generateSchema } from "@mark.probst/typescript-json-schema"; +import { type JSONSchemaSourceData, defined, messageError } from "quicktype-core"; import * as ts from "typescript"; -import { type PartialArgs} from "@mark.probst/typescript-json-schema"; -import { generateSchema } from "@mark.probst/typescript-json-schema"; - -import { type JSONSchemaSourceData} from "quicktype-core"; -import { defined, messageError } from "quicktype-core"; const settings: PartialArgs = { required: true, titles: true, topRef: true, - noExtraProps: true, + noExtraProps: true }; const compilerOptions: ts.CompilerOptions = { @@ -20,18 +17,18 @@ const compilerOptions: ts.CompilerOptions = { module: ts.ModuleKind.CommonJS, strictNullChecks: true, typeRoots: [], - rootDir: ".", + rootDir: "." }; // FIXME: We're stringifying and then parsing this schema again. Just pass around // the schema directly. -export function schemaForTypeScriptSources (sourceFileNames: string[]): JSONSchemaSourceData { +export function schemaForTypeScriptSources(sourceFileNames: string[]): JSONSchemaSourceData { const program = ts.createProgram(sourceFileNames, compilerOptions); const diagnostics = ts.getPreEmitDiagnostics(program); const error = diagnostics.find(d => d.category === ts.DiagnosticCategory.Error); if (error !== undefined) { return messageError("TypeScriptCompilerError", { - message: ts.flattenDiagnosticMessageText(error.messageText, "\n"), + message: ts.flattenDiagnosticMessageText(error.messageText, "\n") }); } diff --git a/src/CompressedJSONFromStream.ts b/src/CompressedJSONFromStream.ts index c442b2f8f..40db6d87b 100644 --- a/src/CompressedJSONFromStream.ts +++ b/src/CompressedJSONFromStream.ts @@ -1,8 +1,8 @@ import { type Readable } from "readable-stream"; -import { type Value } from "quicktype-core"; -import { CompressedJSON } from "quicktype-core"; import { Parser } from "stream-json"; +import { CompressedJSON, type Value } from "quicktype-core"; + const methodMap: { [name: string]: string } = { startObject: "pushObjectContext", endObject: "finishObject", diff --git a/src/GraphQLIntrospection.ts b/src/GraphQLIntrospection.ts index b62122ec5..840cf3c5a 100644 --- a/src/GraphQLIntrospection.ts +++ b/src/GraphQLIntrospection.ts @@ -1,19 +1,19 @@ -import { panic } from "quicktype-core"; -import { introspectionQuery } from "graphql"; import { exceptionToString } from "@glideapps/ts-necessities"; - import fetch from "cross-fetch"; +import { introspectionQuery } from "graphql"; + +import { panic } from "quicktype-core"; // https://github.com/apollographql/apollo-codegen/blob/master/src/downloadSchema.ts -const defaultHeaders: { [name: string]: string, } = { +const defaultHeaders: { [name: string]: string } = { Accept: "application/json", - "Content-Type": "application/json", + "Content-Type": "application/json" }; const headerRegExp = /^([^:]+):\s*(.*)$/; -export async function introspectServer (url: string, method: string, headerStrings: string[]): Promise { - const headers: { [name: string]: string, } = {}; +export async function introspectServer(url: string, method: string, headerStrings: string[]): Promise { + const headers: { [name: string]: string } = {}; for (const name of Object.getOwnPropertyNames(defaultHeaders)) { headers[name] = defaultHeaders[name]; @@ -33,7 +33,7 @@ export async function introspectServer (url: string, method: string, headerStrin const response = await fetch(url, { method, headers: headers, - body: JSON.stringify({ query: introspectionQuery }), + body: JSON.stringify({ query: introspectionQuery }) }); result = await response.json(); diff --git a/src/TypeSource.ts b/src/TypeSource.ts index ab0580889..1c58e2e73 100644 --- a/src/TypeSource.ts +++ b/src/TypeSource.ts @@ -1,6 +1,6 @@ import { type Readable } from "readable-stream"; -import { type JSONSourceData, type JSONSchemaSourceData } from "quicktype-core"; +import { type JSONSchemaSourceData, type JSONSourceData } from "quicktype-core"; import { type GraphQLSourceData } from "quicktype-graphql-input"; export interface JSONTypeSource extends JSONSourceData { diff --git a/src/URLGrammar.ts b/src/URLGrammar.ts index 25ac55c5c..3ffdc26a8 100644 --- a/src/URLGrammar.ts +++ b/src/URLGrammar.ts @@ -1,6 +1,6 @@ -import { panic, checkStringMap, checkArray } from "quicktype-core"; +import { checkArray, checkStringMap, panic } from "quicktype-core"; -function expand (json: any): string[] { +function expand(json: any): string[] { if (typeof json === "string") { return [json]; } @@ -37,9 +37,9 @@ function expand (json: any): string[] { return panic(`Value is not a valid URL grammar: ${json}`); } -export function urlsFromURLGrammar (json: any): { [name: string]: string[], } { +export function urlsFromURLGrammar(json: any): { [name: string]: string[] } { const topLevelMap = checkStringMap(json); - const results: { [name: string]: string[], } = {}; + const results: { [name: string]: string[] } = {}; for (const name of Object.getOwnPropertyNames(topLevelMap)) { results[name] = expand(topLevelMap[name]); diff --git a/src/index.ts b/src/index.ts index a71cfe3f5..6804ef731 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,65 +1,63 @@ #!/usr/bin/env node import * as fs from "fs"; import * as path from "path"; + +import { exceptionToString } from "@glideapps/ts-necessities"; +import chalk from "chalk"; +// eslint-disable-next-line @typescript-eslint/no-redeclare +import { definedMap, hasOwnProperty, mapFromObject, mapMap, withDefault } from "collection-utils"; +import commandLineArgs from "command-line-args"; +import getUsage from "command-line-usage"; import * as _ from "lodash"; import { type Readable } from "readable-stream"; -import { hasOwnProperty, definedMap, withDefault, mapFromObject, mapMap } from "collection-utils"; -import { exceptionToString } from "@glideapps/ts-necessities"; +import stringToStream from "string-to-stream"; +import _wordwrap from "wordwrap"; import { + FetchingJSONSchemaStore, + InputData, + IssueAnnotationData, + JSONInput, + JSONSchemaInput, + type JSONSourceData, + type OptionDefinition, type Options, type RendererOptions, type SerializedRenderResult, type TargetLanguage, - type OptionDefinition, - type JSONSourceData -} from "quicktype-core"; -import { + assert, + assertNever, + capitalize, + defaultTargetLanguages, + defined, + getStream, getTargetLanguage, - quicktypeMultiFile, + inferenceFlagNames, + inferenceFlags, languageNamed, - InputData, - JSONSchemaInput, - defaultTargetLanguages, - IssueAnnotationData, + messageAssert, + messageError, panic, - assert, - defined, - assertNever, parseJSON, - trainMarkovChain, - messageError, - messageAssert, + quicktypeMultiFile, + readFromFileOrURL, + readableFromFileOrURL, sourcesFromPostmanCollection, - inferenceFlags, - inferenceFlagNames, splitIntoWords, - capitalize, - JSONInput, - getStream, - readableFromFileOrURL, - readFromFileOrURL, - FetchingJSONSchemaStore + trainMarkovChain } from "quicktype-core"; -import { schemaForTypeScriptSources } from "quicktype-typescript-input"; import { GraphQLInput } from "quicktype-graphql-input"; +import { schemaForTypeScriptSources } from "quicktype-typescript-input"; -import { urlsFromURLGrammar } from "./URLGrammar"; -import { introspectServer } from "./GraphQLIntrospection"; -import { type JSONTypeSource, type TypeSource, type GraphQLTypeSource, type SchemaTypeSource } from "./TypeSource"; -import { CompressedJSONFromStream } from "./CompressedJSONFromStream"; - -import stringToStream from "string-to-stream"; +import packageJSON from "../package.json"; -import commandLineArgs from "command-line-args"; -import getUsage from "command-line-usage"; -import chalk from "chalk"; +import { CompressedJSONFromStream } from "./CompressedJSONFromStream"; +import { introspectServer } from "./GraphQLIntrospection"; +import { type GraphQLTypeSource, type JSONTypeSource, type SchemaTypeSource, type TypeSource } from "./TypeSource"; +import { urlsFromURLGrammar } from "./URLGrammar"; -import _wordwrap from "wordwrap"; const wordWrap: (s: string) => string = _wordwrap(90); -import packageJSON from "../package.json"; - export interface CLIOptions { // We use this to access the inference flags [option: string]: any; From a47609a2c2665076a70cf9f99b7e800072e9b71f Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Fri, 12 Apr 2024 09:28:49 -0700 Subject: [PATCH 36/94] reduce excess style rules --- .eslintrc.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.eslintrc.json b/.eslintrc.json index c14276ec1..a5cf75933 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -69,10 +69,11 @@ "@typescript-eslint/consistent-type-definitions": ["error", "interface"], "@typescript-eslint/consistent-type-imports": ["error", { "prefer": "type-imports" }], "@typescript-eslint/explicit-function-return-type": "warn", - "@typescript-eslint/indent": ["error", 4], + "@typescript-eslint/indent": "off", "@typescript-eslint/quotes": ["error", "double", { "avoidEscape": true }], "@typescript-eslint/member-delimiter-style": "off", "@typescript-eslint/naming-convention": "error", + "@typescript-eslint/no-base-to-string": "warn", "@typescript-eslint/no-empty-interface": "warn", "@typescript-eslint/no-extra-parens": "off", "@typescript-eslint/no-misused-promises": ["error", { "checksVoidReturn": false }], From b53613620264b5b9d4bdc9547ded2dad0e4f8707 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Fri, 12 Apr 2024 19:26:56 -0700 Subject: [PATCH 37/94] fix any types fixup! fix any types fixup! fix any types --- .../quicktype-core/src/ConvenienceRenderer.ts | 6 +- packages/quicktype-core/src/GraphRewriting.ts | 2 +- packages/quicktype-core/src/Messages.ts | 13 ++-- .../quicktype-core/src/RendererOptions.ts | 15 ++--- packages/quicktype-core/src/Run.ts | 5 +- packages/quicktype-core/src/TargetLanguage.ts | 13 ++-- packages/quicktype-core/src/Transformers.ts | 37 ++++++----- packages/quicktype-core/src/Type.ts | 9 +-- packages/quicktype-core/src/TypeGraph.ts | 6 +- packages/quicktype-core/src/TypeUtils.ts | 2 +- .../src/attributes/AccessorNames.ts | 6 +- .../src/attributes/Description.ts | 4 +- .../src/attributes/StringTypes.ts | 2 +- .../src/attributes/TypeAttributes.ts | 6 +- .../src/input/CompressedJSON.ts | 4 +- packages/quicktype-core/src/input/Inputs.ts | 1 + .../src/input/JSONSchemaInput.ts | 61 +++++++++---------- .../src/input/PostmanCollection.ts | 11 ++-- .../src/input/io/get-stream/buffer-stream.ts | 1 + .../src/input/io/get-stream/index.ts | 1 + packages/quicktype-core/src/language/CJSON.ts | 7 ++- .../quicktype-core/src/language/CPlusPlus.ts | 34 +++++------ .../quicktype-core/src/language/CSharp.ts | 8 +-- .../quicktype-core/src/language/Crystal.ts | 3 +- packages/quicktype-core/src/language/Dart.ts | 5 +- packages/quicktype-core/src/language/Elm.ts | 5 +- .../quicktype-core/src/language/Golang.ts | 5 +- .../quicktype-core/src/language/Haskell.ts | 8 +-- .../quicktype-core/src/language/JSONSchema.ts | 11 ++-- packages/quicktype-core/src/language/Java.ts | 5 +- .../quicktype-core/src/language/JavaScript.ts | 8 +-- .../src/language/JavaScriptPropTypes.ts | 9 +-- .../quicktype-core/src/language/Kotlin.ts | 8 +-- .../src/language/Objective-C.ts | 8 +-- packages/quicktype-core/src/language/Php.ts | 5 +- packages/quicktype-core/src/language/Pike.ts | 3 +- .../quicktype-core/src/language/Python.ts | 5 +- packages/quicktype-core/src/language/Rust.ts | 7 ++- .../quicktype-core/src/language/Scala3.ts | 8 +-- .../quicktype-core/src/language/Smithy4s.ts | 8 +-- packages/quicktype-core/src/language/Swift.ts | 5 +- .../src/language/TypeScriptEffectSchema.ts | 5 +- .../src/language/TypeScriptFlow.ts | 12 ++-- .../src/language/TypeScriptZod.ts | 8 +-- .../quicktype-core/src/language/ruby/index.ts | 5 +- .../quicktype-core/src/support/Support.ts | 43 +++++++------ packages/quicktype-core/src/types.ts | 6 ++ packages/quicktype-graphql-input/src/index.ts | 6 +- src/CompressedJSONFromStream.ts | 5 +- src/URLGrammar.ts | 6 +- src/index.ts | 7 ++- 51 files changed, 250 insertions(+), 223 deletions(-) create mode 100644 packages/quicktype-core/src/types.ts diff --git a/packages/quicktype-core/src/ConvenienceRenderer.ts b/packages/quicktype-core/src/ConvenienceRenderer.ts index 8de7ac678..df5e02578 100644 --- a/packages/quicktype-core/src/ConvenienceRenderer.ts +++ b/packages/quicktype-core/src/ConvenienceRenderer.ts @@ -775,7 +775,7 @@ export abstract class ConvenienceRenderer extends Renderer { protected forEachSpecificNamedType( blankLocations: BlankLineConfig, - types: Iterable<[any, T]>, + types: Iterable<[T, T]>, f: (t: T, name: Name, position: ForEachPosition) => void ): void { this.forEachWithBlankLines(types, blankLocations, (t, _, pos) => f(t, this.nameForNamedType(t), pos)); @@ -788,7 +788,7 @@ export abstract class ConvenienceRenderer extends Renderer { | ((o: ObjectType, objectName: Name, position: ForEachPosition) => void) ): void { // FIXME: This is ugly. - this.forEachSpecificNamedType(blankLocations, defined(this._namedObjects).entries(), f as any); + this.forEachSpecificNamedType(blankLocations, defined(this._namedObjects).entries(), f); } protected forEachEnum( @@ -834,7 +834,7 @@ export abstract class ConvenienceRenderer extends Renderer { if (t instanceof ObjectType) { // FIXME: This is ugly. We can't runtime check that the function // takes full object types if we have them. - (objectFunc as any)(t, name, pos); + objectFunc(t, name, pos); } else if (t instanceof EnumType) { enumFunc(t, name, pos); } else if (t instanceof UnionType) { diff --git a/packages/quicktype-core/src/GraphRewriting.ts b/packages/quicktype-core/src/GraphRewriting.ts index 546877575..d3c78d811 100644 --- a/packages/quicktype-core/src/GraphRewriting.ts +++ b/packages/quicktype-core/src/GraphRewriting.ts @@ -222,7 +222,7 @@ export abstract class BaseGraphRewriteBuilder extends TypeBuilder implements Typ private _printIndent = 0; public constructor( - protected readonly originalGraph: TypeGraph, + public readonly originalGraph: TypeGraph, stringTypeMapping: StringTypeMapping, alphabetizeProperties: boolean, graphHasProvenanceAttributes: boolean, diff --git a/packages/quicktype-core/src/Messages.ts b/packages/quicktype-core/src/Messages.ts index 6f35dae1c..0c945480a 100644 --- a/packages/quicktype-core/src/Messages.ts +++ b/packages/quicktype-core/src/Messages.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import { type Ref } from "./input/JSONSchemaInput"; import { type StringMap } from "./support/Support"; @@ -6,9 +7,9 @@ export type ErrorProperties = // Misc | { - kind: "MiscJSONParseError"; - properties: { address: string; description: string; message: string }; - } + kind: "MiscJSONParseError"; + properties: { address: string; description: string; message: string }; + } | { kind: "MiscReadError"; properties: { fileOrURL: string; message: string } } | { kind: "MiscUnicodeHighSurrogateWithoutLowSurrogate"; properties: {} } | { kind: "MiscInvalidMinMaxConstraint"; properties: { max: number; min: number } } @@ -36,9 +37,9 @@ export type ErrorProperties = | { kind: "SchemaIDMustHaveAddress"; properties: { id: string; ref: Ref } } | { kind: "SchemaWrongAccessorEntryArrayLength"; properties: { operation: string; ref: Ref } } | { - kind: "SchemaSetOperationCasesIsNotArray"; - properties: { cases: any; operation: string; ref: Ref }; - } + kind: "SchemaSetOperationCasesIsNotArray"; + properties: { cases: any; operation: string; ref: Ref }; + } | { kind: "SchemaMoreThanOneUnionMemberName"; properties: { names: string[] } } | { kind: "SchemaCannotGetTypesFromBoolean"; properties: { ref: string } } | { kind: "SchemaCannotIndexArrayWithNonNumber"; properties: { actual: string; ref: Ref } } diff --git a/packages/quicktype-core/src/RendererOptions.ts b/packages/quicktype-core/src/RendererOptions.ts index 9e4b17542..77f95c228 100644 --- a/packages/quicktype-core/src/RendererOptions.ts +++ b/packages/quicktype-core/src/RendererOptions.ts @@ -3,6 +3,7 @@ import { hasOwnProperty } from "collection-utils"; import { messageError } from "./Messages"; import { assert } from "./support/Support"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "./types"; /** * Primary options show up in the web UI in the "Language" settings tab, @@ -13,7 +14,7 @@ export type OptionKind = "primary" | "secondary"; export interface OptionDefinition { alias?: string; defaultOption?: boolean; - defaultValue?: any; + defaultValue?: FixMeOptionsAnyType; description: string; kind?: OptionKind; legalValues?: string[]; @@ -37,7 +38,7 @@ export abstract class Option { assert(definition.kind !== undefined, "Renderer option kind must be defined"); } - public getValue(values: { [name: string]: any }): T { + public getValue(values: FixMeOptionsType): T { const value = values[this.definition.name]; if (value === undefined) { return this.definition.defaultValue; @@ -54,11 +55,11 @@ export abstract class Option { export type OptionValueType = O extends Option ? T : never; export type OptionValues = { [P in keyof T]: OptionValueType }; -export function getOptionValues }>( +export function getOptionValues }>( options: T, - untypedOptionValues: { [name: string]: any } + untypedOptionValues: FixMeOptionsType ): OptionValues { - const optionValues: { [name: string]: any } = {}; + const optionValues: FixMeOptionsType = {}; for (const name of Object.getOwnPropertyNames(options)) { optionValues[name] = options[name].getValue(untypedOptionValues); } @@ -101,7 +102,7 @@ export class BooleanOption extends Option { }; } - public getValue(values: { [name: string]: any }): boolean { + public getValue(values: FixMeOptionsType): boolean { let value = values[this.definition.name]; if (value === undefined) { value = this.definition.defaultValue; @@ -177,7 +178,7 @@ export class EnumOption extends Option { } } - public getValue(values: { [name: string]: any }): T { + public getValue(values: FixMeOptionsType): T { let name: string = values[this.definition.name]; if (name === undefined) { name = this.definition.defaultValue; diff --git a/packages/quicktype-core/src/Run.ts b/packages/quicktype-core/src/Run.ts index 42a5e5b31..dac66c17e 100644 --- a/packages/quicktype-core/src/Run.ts +++ b/packages/quicktype-core/src/Run.ts @@ -20,6 +20,7 @@ import { type MultiFileRenderResult, type TargetLanguage } from "./TargetLanguag import { type TransformedStringTypeKind } from "./Type"; import { type StringTypeMapping, TypeBuilder } from "./TypeBuilder"; import { type TypeGraph, noneToAny, optionalToNullable, removeIndirectionIntersections } from "./TypeGraph"; +import { type FixMeOptionsType } from "./types"; export function getTargetLanguage(nameOrInstance: string | TargetLanguage): TargetLanguage { if (typeof nameOrInstance === "object") { @@ -231,9 +232,9 @@ class Run implements RunContext { // we sometimes get. this._options = Object.assign({}, defaultOptions, defaultInferenceFlags); for (const k of Object.getOwnPropertyNames(options)) { - const v = (options as any)[k]; + const v = (options as FixMeOptionsType)[k]; if (v !== undefined) { - (this._options as any)[k] = v; + (this._options as FixMeOptionsType)[k] = v; } } } diff --git a/packages/quicktype-core/src/TargetLanguage.ts b/packages/quicktype-core/src/TargetLanguage.ts index 07fe51409..19f6bfea7 100644 --- a/packages/quicktype-core/src/TargetLanguage.ts +++ b/packages/quicktype-core/src/TargetLanguage.ts @@ -1,6 +1,6 @@ import { mapMap } from "collection-utils"; -import { type ConvenienceRenderer } from "./ConvenienceRenderer"; +import { ConvenienceRenderer } from "./ConvenienceRenderer"; import { type DateTimeRecognizer, DefaultDateTimeRecognizer } from "./DateTime"; import { type RenderContext, type Renderer } from "./Renderer"; import { type Option, type OptionDefinition } from "./RendererOptions"; @@ -10,6 +10,7 @@ import { defined } from "./support/Support"; import { type Type } from "./Type"; import { type StringTypeMapping } from "./TypeBuilder"; import { type TypeGraph } from "./TypeGraph"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "./types"; export type MultiFileRenderResult = ReadonlyMap; @@ -20,7 +21,7 @@ export abstract class TargetLanguage { public readonly extension: string ) {} - protected abstract getOptions(): Array>; + protected abstract getOptions(): Array>; public get optionDefinitions(): OptionDefinition[] { return this.getOptions().map(o => o.definition); @@ -41,14 +42,14 @@ export abstract class TargetLanguage { return defined(this.names[0]); } - protected abstract makeRenderer(renderContext: RenderContext, optionValues: { [name: string]: any }): Renderer; + protected abstract makeRenderer(renderContext: RenderContext, optionValues: FixMeOptionsType): Renderer; public renderGraphAndSerialize( typeGraph: TypeGraph, givenOutputFilename: string, alphabetizeProperties: boolean, leadingComments: Comment[] | undefined, - rendererOptions: { [name: string]: any }, + rendererOptions: FixMeOptionsType, indentation?: string ): MultiFileRenderResult { if (indentation === undefined) { @@ -57,8 +58,8 @@ export abstract class TargetLanguage { const renderContext = { typeGraph, leadingComments }; const renderer = this.makeRenderer(renderContext, rendererOptions); - if ((renderer as any).setAlphabetizeProperties !== undefined) { - (renderer as ConvenienceRenderer).setAlphabetizeProperties(alphabetizeProperties); + if (renderer instanceof ConvenienceRenderer) { + renderer.setAlphabetizeProperties(alphabetizeProperties); } const renderResult = renderer.render(givenOutputFilename); diff --git a/packages/quicktype-core/src/Transformers.ts b/packages/quicktype-core/src/Transformers.ts index 01de933a8..b1b93bfa3 100644 --- a/packages/quicktype-core/src/Transformers.ts +++ b/packages/quicktype-core/src/Transformers.ts @@ -54,8 +54,7 @@ export abstract class Transformer { public abstract reconstitute(builder: TBuilder): Transformer; - public equals(other: any): boolean { - if (!(other instanceof Transformer)) return false; + public equals(other: T): boolean { return this.sourceTypeRef === other.sourceTypeRef; } @@ -97,7 +96,7 @@ export abstract class ProducerTransformer extends Transformer { return super.getNumberOfNodes() + getNumberOfNodes(this.consumer); } - public equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; if (!(other instanceof ProducerTransformer)) return false; return areEqual(this.consumer, other.consumer); @@ -132,7 +131,7 @@ export abstract class MatchTransformer extends Transformer { return super.getNumberOfNodes() + this.transformer.getNumberOfNodes(); } - public equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; if (!(other instanceof MatchTransformer)) return false; return this.transformer.equals(other.transformer); @@ -180,7 +179,7 @@ export class DecodingTransformer extends ProducerTransformer { ); } - public equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; return other instanceof DecodingTransformer; } @@ -203,7 +202,7 @@ export class EncodingTransformer extends Transformer { return new EncodingTransformer(builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef)); } - public equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; if (!(other instanceof EncodingTransformer)) return false; return true; @@ -283,7 +282,7 @@ export class ArrayDecodingTransformer extends ProducerTransformer { return h; } - public equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; if (!(other instanceof ArrayDecodingTransformer)) return false; if (!areEqual(this._itemTargetTypeRef, other._itemTargetTypeRef)) return false; @@ -343,7 +342,7 @@ export class ArrayEncodingTransformer extends Transformer { return addHashCode(h, this.itemTransformer.hashCode()); } - public equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; if (!(other instanceof ArrayEncodingTransformer)) return false; if (!areEqual(this._itemTargetTypeRef, other._itemTargetTypeRef)) return false; @@ -415,7 +414,7 @@ export class ChoiceTransformer extends Transformer { ); } - public equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; if (!(other instanceof ChoiceTransformer)) return false; return areEqual(this.transformers, other.transformers); @@ -597,7 +596,7 @@ export class DecodingChoiceTransformer extends Transformer { ); } - public equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; if (!(other instanceof DecodingChoiceTransformer)) return false; if (!areEqual(this.nullTransformer, other.nullTransformer)) return false; @@ -673,7 +672,7 @@ export class UnionMemberMatchTransformer extends MatchTransformer { ); } - public equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; if (!(other instanceof UnionMemberMatchTransformer)) return false; return this.memberTypeRef === other.memberTypeRef; @@ -736,7 +735,7 @@ export class StringMatchTransformer extends MatchTransformer { ); } - public equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; if (!(other instanceof StringMatchTransformer)) return false; return this.stringCase !== other.stringCase; @@ -773,7 +772,7 @@ export class UnionInstantiationTransformer extends Transformer { return new UnionInstantiationTransformer(builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef)); } - public equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; return other instanceof UnionInstantiationTransformer; } @@ -825,7 +824,7 @@ export class StringProducerTransformer extends ProducerTransformer { ); } - public equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; if (!(other instanceof StringProducerTransformer)) return false; return this.result === other.result; @@ -869,7 +868,7 @@ export class ParseStringTransformer extends ProducerTransformer { ); } - public equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; return other instanceof ParseStringTransformer; } @@ -903,7 +902,7 @@ export class StringifyTransformer extends ProducerTransformer { ); } - public equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; return other instanceof StringifyTransformer; } @@ -957,7 +956,7 @@ export class MinMaxLengthCheckTransformer extends ProducerTransformer { ); } - public equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; return ( other instanceof MinMaxLengthCheckTransformer && @@ -1015,7 +1014,7 @@ export class MinMaxValueTransformer extends ProducerTransformer { ); } - public equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; return ( other instanceof MinMaxValueTransformer && this.minimum === other.minimum && this.maximum === other.maximum @@ -1058,7 +1057,7 @@ export class Transformation { ); } - public equals(other: any): boolean { + public equals(other: T): boolean { if (!(other instanceof Transformation)) return false; return this._targetTypeRef === other._targetTypeRef && this.transformer.equals(other.transformer); } diff --git a/packages/quicktype-core/src/Type.ts b/packages/quicktype-core/src/Type.ts index 6184f712b..d5bab5cf2 100644 --- a/packages/quicktype-core/src/Type.ts +++ b/packages/quicktype-core/src/Type.ts @@ -112,7 +112,8 @@ export class TypeIdentity { public constructor( private readonly _kind: TypeKind, - private readonly _components: readonly any[] + // FIXME: strongly type this + private readonly _components: readonly unknown[] ) { let h = hashCodeInit; h = addHashCode(h, hashCodeOf(this._kind)); @@ -123,7 +124,7 @@ export class TypeIdentity { this._hashCode = h; } - public equals(other: any): boolean { + public equals(other: T): boolean { if (!(other instanceof TypeIdentity)) return false; if (this._kind !== other._kind) return false; const n = this._components.length; @@ -197,7 +198,7 @@ export abstract class Type { return this.kind; } - public equals(other: any): boolean { + public equals(other: T): boolean { if (!(other instanceof Type)) return false; return this.typeRef === other.typeRef; } @@ -434,7 +435,7 @@ export class GenericClassProperty { public readonly isOptional: boolean ) {} - public equals(other: any): boolean { + public equals(other: GenericClassProperty): boolean { if (!(other instanceof GenericClassProperty)) { return false; } diff --git a/packages/quicktype-core/src/TypeGraph.ts b/packages/quicktype-core/src/TypeGraph.ts index 98df9370f..3e229bd51 100644 --- a/packages/quicktype-core/src/TypeGraph.ts +++ b/packages/quicktype-core/src/TypeGraph.ts @@ -25,7 +25,7 @@ const indexMask = (1 << indexBits) - 1; const serialBits = 31 - indexBits; const serialMask = (1 << serialBits) - 1; -export function isTypeRef(x: any): x is TypeRef { +export function isTypeRef(x: unknown): x is TypeRef { return typeof x === "number"; } @@ -292,7 +292,7 @@ export class TypeGraph { return result; } - private setPrintOnRewrite(): void { + public setPrintOnRewrite(): void { this._printOnRewrite = true; } @@ -448,7 +448,7 @@ export class TypeGraph { return this._parents[t.index]; } - private printGraph(): void { + public printGraph(): void { const types = defined(this._types); for (let i = 0; i < types.length; i++) { const t = types[i]; diff --git a/packages/quicktype-core/src/TypeUtils.ts b/packages/quicktype-core/src/TypeUtils.ts index 07fdd4e65..f4ab36d34 100644 --- a/packages/quicktype-core/src/TypeUtils.ts +++ b/packages/quicktype-core/src/TypeUtils.ts @@ -131,7 +131,7 @@ export function isAnyOrNull(t: Type): boolean { // introduced. export function removeNullFromUnion( t: UnionType, - sortBy: boolean | ((t: Type) => any) = false + sortBy: boolean | ((t: Type) => string | number) = false ): [PrimitiveType | null, ReadonlySet] { function sort(s: ReadonlySet): ReadonlySet { if (sortBy === false) return s; diff --git a/packages/quicktype-core/src/attributes/AccessorNames.ts b/packages/quicktype-core/src/attributes/AccessorNames.ts index cb19ca59e..01621a65b 100644 --- a/packages/quicktype-core/src/attributes/AccessorNames.ts +++ b/packages/quicktype-core/src/attributes/AccessorNames.ts @@ -168,12 +168,12 @@ export function unionMemberName(u: UnionType, member: Type, language: string): [ return [first, isFixed]; } -function isAccessorEntry(x: any): x is string | { [language: string]: string } { +function isAccessorEntry(x: unknown): x is string | { [language: string]: string } { if (typeof x === "string") { return true; } - return isStringMap(x, (v: any): v is string => typeof v === "string"); + return isStringMap(x, (v: unknown): v is string => typeof v === "string"); } function makeAccessorEntry(ae: string | { [language: string]: string }): AccessorEntry { @@ -181,7 +181,7 @@ function makeAccessorEntry(ae: string | { [language: string]: string }): Accesso return mapFromObject(ae); } -export function makeAccessorNames(x: any): AccessorNames { +export function makeAccessorNames(x: unknown): AccessorNames { // FIXME: Do proper error reporting const stringMap = checkStringMap(x, isAccessorEntry); return mapMap(mapFromObject(stringMap), makeAccessorEntry); diff --git a/packages/quicktype-core/src/attributes/Description.ts b/packages/quicktype-core/src/attributes/Description.ts index 01022e7dd..a1f64efcd 100644 --- a/packages/quicktype-core/src/attributes/Description.ts +++ b/packages/quicktype-core/src/attributes/Description.ts @@ -123,8 +123,8 @@ export function descriptionAttributeProducer( } if (types.has("object") && typeof schema.properties === "object") { - const propertyDescriptions = mapFilterMap(mapFromObject(schema.properties), propSchema => { - if (typeof propSchema === "object") { + const propertyDescriptions = mapFilterMap(mapFromObject(schema.properties), propSchema => { + if (propSchema && typeof propSchema === "object" && "description" in propSchema) { const desc = propSchema.description; if (typeof desc === "string") { return new Set([desc]); diff --git a/packages/quicktype-core/src/attributes/StringTypes.ts b/packages/quicktype-core/src/attributes/StringTypes.ts index 343eeebe0..ae8539a24 100644 --- a/packages/quicktype-core/src/attributes/StringTypes.ts +++ b/packages/quicktype-core/src/attributes/StringTypes.ts @@ -109,7 +109,7 @@ export class StringTypes { return new StringTypes(this.cases, new Set(kinds)); } - public equals(other: any): boolean { + public equals(other: T): boolean { if (!(other instanceof StringTypes)) return false; return areEqual(this.cases, other.cases) && areEqual(this.transformations, other.transformations); } diff --git a/packages/quicktype-core/src/attributes/TypeAttributes.ts b/packages/quicktype-core/src/attributes/TypeAttributes.ts index 164f9878d..e8a3a61cd 100644 --- a/packages/quicktype-core/src/attributes/TypeAttributes.ts +++ b/packages/quicktype-core/src/attributes/TypeAttributes.ts @@ -86,7 +86,7 @@ export class TypeAttributeKind { return mapFilter(a, (_, k) => k !== this); } - public equals(other: any): boolean { + public equals(other: TypeAttributeKind): boolean { if (!(other instanceof TypeAttributeKind)) { return false; } @@ -99,6 +99,8 @@ export class TypeAttributeKind { } } +// FIXME: strongly type this +// eslint-disable-next-line @typescript-eslint/no-explicit-any export type TypeAttributes = ReadonlyMap, any>; export const emptyTypeAttributes: TypeAttributes = new Map(); @@ -126,6 +128,8 @@ export function combineTypeAttributes( const attributesByKind = mapTranspose(attributeArray); + // FIXME: strongly type this + // eslint-disable-next-line @typescript-eslint/no-explicit-any function combine(attrs: any[], kind: TypeAttributeKind): any { assert(attrs.length > 0, "Cannot combine zero type attributes"); if (attrs.length === 1) return attrs[0]; diff --git a/packages/quicktype-core/src/input/CompressedJSON.ts b/packages/quicktype-core/src/input/CompressedJSON.ts index 2aa3355cf..15e6122d0 100644 --- a/packages/quicktype-core/src/input/CompressedJSON.ts +++ b/packages/quicktype-core/src/input/CompressedJSON.ts @@ -255,7 +255,7 @@ export abstract class CompressedJSON { this._ctx = this._contextStack.pop(); } - public equals(other: any): boolean { + public equals(other: CompressedJSON): boolean { return this === other; } @@ -319,7 +319,7 @@ export class CompressedJSONFromString extends CompressedJSON { this.pushObjectContext(); for (const key of Object.getOwnPropertyNames(json)) { this.setPropertyKey(key); - this.process((json as any)[key]); + this.process(json[key as keyof typeof json]); } this.finishObject(); diff --git a/packages/quicktype-core/src/input/Inputs.ts b/packages/quicktype-core/src/input/Inputs.ts index 031d84ead..be10e48d2 100644 --- a/packages/quicktype-core/src/input/Inputs.ts +++ b/packages/quicktype-core/src/input/Inputs.ts @@ -166,6 +166,7 @@ export function jsonInputForTargetLanguage( export class InputData { // FIXME: Make into a Map, indexed by kind. + // eslint-disable-next-line @typescript-eslint/no-explicit-any private _inputs: Set> = new Set(); protected addInput(input: Input): void { diff --git a/packages/quicktype-core/src/input/JSONSchemaInput.ts b/packages/quicktype-core/src/input/JSONSchemaInput.ts index 03ce2ea6c..0938bae22 100644 --- a/packages/quicktype-core/src/input/JSONSchemaInput.ts +++ b/packages/quicktype-core/src/input/JSONSchemaInput.ts @@ -78,25 +78,27 @@ function keyOrIndex(pe: PathElement): string | undefined { function pathElementEquals(a: PathElement, b: PathElement): boolean { if (a.kind !== b.kind) return false; - switch (a.kind) { - case PathElementKind.Type: - return a.index === (b as any).index; - case PathElementKind.KeyOrIndex: - return a.key === (b as any).key; - default: - return true; + + if (a.kind === PathElementKind.Type && b.kind === PathElementKind.Type) { + return a.index === b.index; } + + if (a.kind === PathElementKind.KeyOrIndex && b.kind === PathElementKind.KeyOrIndex) { + return a.key === b.key; + } + + return true; } function withRef(refOrLoc: Ref | (() => Ref) | Location): { ref: Ref }; function withRef(refOrLoc: Ref | (() => Ref) | Location, props?: T): T & { ref: Ref }; -function withRef(refOrLoc: Ref | (() => Ref) | Location, props?: T): any { +function withRef(refOrLoc: Ref | (() => Ref) | Location, props?: T): unknown { const ref = typeof refOrLoc === "function" ? refOrLoc() : refOrLoc instanceof Ref ? refOrLoc : refOrLoc.canonicalRef; return Object.assign({ ref }, props ?? {}); } -function checkJSONSchemaObject(x: any, refOrLoc: Ref | (() => Ref)): StringMap { +function checkJSONSchemaObject(x: unknown, refOrLoc: Ref | (() => Ref)): StringMap { if (Array.isArray(x)) { return messageError("SchemaArrayIsInvalidSchema", withRef(refOrLoc)); } @@ -112,7 +114,7 @@ function checkJSONSchemaObject(x: any, refOrLoc: Ref | (() => Ref)): StringMap { return x; } -function checkJSONSchema(x: any, refOrLoc: Ref | (() => Ref)): JSONSchema { +function checkJSONSchema(x: unknown, refOrLoc: Ref | (() => Ref)): JSONSchema { if (typeof x === "boolean") return x; return checkJSONSchemaObject(x, refOrLoc); } @@ -293,7 +295,7 @@ export class Ref { return address + "#" + this.path.map(elementToString).join("/"); } - private lookup(local: any, path: readonly PathElement[], root: JSONSchema): JSONSchema { + private lookup(local: unknown, path: readonly PathElement[], root: JSONSchema): JSONSchema { const refMaker = () => new Ref(this.addressURI, path); const first = path[0]; if (first === undefined) { @@ -338,7 +340,7 @@ export class Ref { return this.lookup(root, this.path, root); } - public equals(other: any): boolean { + public equals(other: R): boolean { if (!(other instanceof Ref)) return false; if (this.addressURI !== undefined && other.addressURI !== undefined) { if (!this.addressURI.equals(other.addressURI)) return false; @@ -389,7 +391,7 @@ class Location { this.virtualRef = virtualRef ?? canonicalRef; } - public updateWithID(id: any) { + public updateWithID(id: string | unknown) { if (typeof id !== "string") return this; const parsed = Ref.parse(id); const virtual = this.haveID ? parsed.resolveAgainst(this.virtualRef) : parsed; @@ -424,7 +426,7 @@ class Canonizer { public constructor(private readonly _ctx: RunContext) {} - private addIDs(schema: any, loc: Location) { + private addIDs(schema: unknown, loc: Location) { if (schema === null) return; if (Array.isArray(schema)) { for (let i = 0; i < schema.length; i++) { @@ -439,7 +441,7 @@ class Canonizer { } const locWithoutID = loc; - const maybeID = schema.$id; + const maybeID = "$id" in schema ? schema.$id : undefined; if (typeof maybeID === "string") { loc = loc.updateWithID(maybeID); } @@ -453,11 +455,11 @@ class Canonizer { } for (const property of Object.getOwnPropertyNames(schema)) { - this.addIDs(schema[property], loc.push(property)); + this.addIDs(schema[property as keyof typeof schema], loc.push(property)); } } - public addSchema(schema: any, address: string): boolean { + public addSchema(schema: unknown, address: string): boolean { if (this._schemaAddressesAdded.has(address)) return false; this.addIDs(schema, new Location(Ref.root(address), Ref.root(undefined))); @@ -479,7 +481,7 @@ class Canonizer { } } -function checkTypeList(typeOrTypes: any, loc: Location): ReadonlySet { +function checkTypeList(typeOrTypes: string | string[], loc: Location): ReadonlySet { let set: Set; if (typeof typeOrTypes === "string") { set = new Set([typeOrTypes]); @@ -508,7 +510,7 @@ function checkTypeList(typeOrTypes: any, loc: Location): ReadonlySet { return set; } -function checkRequiredArray(arr: any, loc: Location): string[] { +function checkRequiredArray(arr: string[], loc: Location): string[] { if (!Array.isArray(arr)) { return messageError("SchemaRequiredMustBeStringOrStringArray", withRef(loc, { actual: arr })); } @@ -678,7 +680,7 @@ async function addTypesInSchema( attributes: TypeAttributes, properties: StringMap, requiredArray: string[], - additionalProperties: any, + additionalProperties: unknown, sortKey: (k: string) => number | string = (k: string) => k.toLowerCase() ): Promise { const required = new Set(requiredArray); @@ -734,16 +736,16 @@ async function addTypesInSchema( } if (enumArray !== undefined) { - let predicate: (x: any) => boolean; + let predicate: (x: unknown) => boolean; switch (name) { case "null": - predicate = (x: any) => x === null; + predicate = (x: unknown) => x === null; break; case "integer": - predicate = (x: any) => typeof x === "number" && x === Math.floor(x); + predicate = (x: unknown) => typeof x === "number" && x === Math.floor(x); break; default: - predicate = (x: any) => typeof x === name; + predicate = (x: unknown) => typeof x === name; break; } @@ -916,13 +918,12 @@ async function addTypesInSchema( return await makeObject(loc, objectAttributes, properties, required, additionalProperties, orderKey); } - async function makeTypesFromCases(cases: any, kind: string): Promise { + async function makeTypesFromCases(cases: unknown[], kind: string): Promise { const kindLoc = loc.push(kind); if (!Array.isArray(cases)) { return messageError("SchemaSetOperationCasesIsNotArray", withRef(kindLoc, { operation: kind, cases })); } - // FIXME: This cast shouldn't be necessary, but TypeScript forces our hand. return await arrayMapSync(cases, async (t, index) => { const caseLoc = kindLoc.push(index.toString()); return await toType( @@ -936,7 +937,7 @@ async function addTypesInSchema( const intersectionType = typeBuilder.getUniqueIntersectionType(typeAttributes, undefined); setTypeForLocation(loc, intersectionType); - async function convertOneOrAnyOf(cases: any, kind: string): Promise { + async function convertOneOrAnyOf(cases: unknown[], kind: string): Promise { const typeRefs = await makeTypesFromCases(cases, kind); let unionAttributes = makeTypeAttributesInferred(typeAttributes); if (kind === "oneOf") { @@ -971,7 +972,7 @@ async function addTypesInSchema( const needStringEnum = includedTypes.has("string") && enumArray !== undefined && - enumArray.find((x: any) => typeof x === "string") !== undefined; + enumArray.find(x => typeof x === "string") !== undefined; const needUnion = typeSet !== undefined || schema.properties !== undefined || @@ -1007,9 +1008,7 @@ async function addTypesInSchema( ); if (needStringEnum || isConst) { - const cases = isConst - ? [schema.const] - : ((enumArray as any[]).filter(x => typeof x === "string") as string[]); + const cases = isConst ? [schema.const] : enumArray?.filter(x => typeof x === "string") ?? []; unionTypes.push(typeBuilder.getStringType(stringAttributes, StringTypes.fromCases(cases))); } else if (includedTypes.has("string")) { unionTypes.push(makeStringType(stringAttributes)); diff --git a/packages/quicktype-core/src/input/PostmanCollection.ts b/packages/quicktype-core/src/input/PostmanCollection.ts index ce554ffb5..fd191a8c6 100644 --- a/packages/quicktype-core/src/input/PostmanCollection.ts +++ b/packages/quicktype-core/src/input/PostmanCollection.ts @@ -2,7 +2,7 @@ import { parseJSON } from "../support/Support"; import { type JSONSourceData } from "./Inputs"; -function isValidJSON (s: string): boolean { +function isValidJSON(s: string): boolean { try { JSON.parse(s); return true; @@ -11,14 +11,15 @@ function isValidJSON (s: string): boolean { } } -export function sourcesFromPostmanCollection ( +export function sourcesFromPostmanCollection( collectionJSON: string, - collectionJSONAddress?: string, -): { description: string | undefined, sources: Array>, } { + collectionJSONAddress?: string +): { description: string | undefined; sources: Array> } { const sources: Array> = []; const descriptions: string[] = []; - function processCollection (c: any): void { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + function processCollection(c: any): void { if (typeof c !== "object") return; if (Array.isArray(c.item)) { for (const item of c.item) { diff --git a/packages/quicktype-core/src/input/io/get-stream/buffer-stream.ts b/packages/quicktype-core/src/input/io/get-stream/buffer-stream.ts index 063f2794e..846f6a0a5 100644 --- a/packages/quicktype-core/src/input/io/get-stream/buffer-stream.ts +++ b/packages/quicktype-core/src/input/io/get-stream/buffer-stream.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import { PassThrough } from "readable-stream"; import { type Options } from "."; diff --git a/packages/quicktype-core/src/input/io/get-stream/index.ts b/packages/quicktype-core/src/input/io/get-stream/index.ts index 4ae2d3ae7..6cf051d51 100644 --- a/packages/quicktype-core/src/input/io/get-stream/index.ts +++ b/packages/quicktype-core/src/input/io/get-stream/index.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import { type Readable } from "readable-stream"; import bufferStream from "./buffer-stream"; diff --git a/packages/quicktype-core/src/language/CJSON.ts b/packages/quicktype-core/src/language/CJSON.ts index 0bfd40f57..88e78f414 100644 --- a/packages/quicktype-core/src/language/CJSON.ts +++ b/packages/quicktype-core/src/language/CJSON.ts @@ -13,7 +13,7 @@ * To print json string from json data use the following: char * string = cJSON_Print(); * To delete json data use the following: cJSON_Delete(); * - * TODO list for futur enhancements: + * TODO list for future enhancements: * - Management of Class, Union and TopLevel should be mutualized to reduce code size and to permit Union and TopLevel having recursive Array/Map * - Types check should be added to verify unwanted inputs (for example a Number passed while a String is expected, etc) * - Constraints should be implemented (verification of Enum values, min/max values for Numbers and min/max length for Strings, regex) @@ -40,6 +40,7 @@ import { import { assert, assertNever, defined, numberEnumValues, panic } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; import { ArrayType, ClassType, EnumType, MapType, type Type, type TypeKind, UnionType } from "../Type"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; /* Naming styles */ @@ -142,7 +143,7 @@ export class CJSONTargetLanguage extends TargetLanguage { * Return cJSON generator options * @return cJSON generator options array */ - protected getOptions(): Array> { + protected getOptions(): Array> { return [ cJSONOptions.typeSourceStyle, cJSONOptions.typeIntegerSize, @@ -177,7 +178,7 @@ export class CJSONTargetLanguage extends TargetLanguage { * @param untypedOptionValues * @return cJSON renderer */ - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): CJSONRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): CJSONRenderer { return new CJSONRenderer(this, renderContext, getOptionValues(cJSONOptions, untypedOptionValues)); } } diff --git a/packages/quicktype-core/src/language/CPlusPlus.ts b/packages/quicktype-core/src/language/CPlusPlus.ts index b75f834f6..c787a8778 100644 --- a/packages/quicktype-core/src/language/CPlusPlus.ts +++ b/packages/quicktype-core/src/language/CPlusPlus.ts @@ -50,6 +50,7 @@ import { type TypeKind, UnionType } from "../Type"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; import { directlyReachableTypes, isNamedType, matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; const pascalValue: [string, NamingStyle] = ["pascal-case", "pascal"]; @@ -143,7 +144,7 @@ export class CPlusPlusTargetLanguage extends TargetLanguage { super(displayName, names, extension); } - protected getOptions(): Array> { + protected getOptions(): Array> { return [ cPlusPlusOptions.justTypes, cPlusPlusOptions.namespace, @@ -169,21 +170,18 @@ export class CPlusPlusTargetLanguage extends TargetLanguage { return true; } - protected makeRenderer( - renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } - ): CPlusPlusRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): CPlusPlusRenderer { return new CPlusPlusRenderer(this, renderContext, getOptionValues(cPlusPlusOptions, untypedOptionValues)); } } function constraintsForType(t: Type): -| { - minMax?: MinMaxConstraint; - minMaxLength?: MinMaxConstraint; - pattern?: string; -} -| undefined { + | { + minMax?: MinMaxConstraint; + minMaxLength?: MinMaxConstraint; + pattern?: string; + } + | undefined { const minMax = minMaxValueForType(t); const minMaxLength = minMaxLengthForType(t); const pattern = patternForType(t); @@ -1375,11 +1373,11 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { pattern === undefined ? this._nulloptType : [ - this._stringType.getType(), - "(", - this._stringType.createStringLiteral([stringEscape(pattern)]), - ")" - ], + this._stringType.getType(), + "(", + this._stringType.createStringLiteral([stringEscape(pattern)]), + ")" + ], ")" ]); }); @@ -2646,11 +2644,11 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { protected gatherUserNamespaceForwardDecls(): Sourcelike[] { return this.gatherSource(() => { - this.forEachObject("leading-and-interposing", (_: any, className: Name) => + this.forEachObject("leading-and-interposing", (_: unknown, className: Name) => this.emitClassHeaders(className) ); - this.forEachEnum("leading-and-interposing", (_: any, enumName: Name) => this.emitEnumHeaders(enumName)); + this.forEachEnum("leading-and-interposing", (_: unknown, enumName: Name) => this.emitEnumHeaders(enumName)); }); } diff --git a/packages/quicktype-core/src/language/CSharp.ts b/packages/quicktype-core/src/language/CSharp.ts index 54c0de48d..159dab900 100644 --- a/packages/quicktype-core/src/language/CSharp.ts +++ b/packages/quicktype-core/src/language/CSharp.ts @@ -58,6 +58,7 @@ import { UnionType } from "../Type"; import { type StringTypeMapping } from "../TypeBuilder"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; import { directlyReachableSingleNamedType, matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; export enum Framework { @@ -212,7 +213,7 @@ export class CSharpTargetLanguage extends TargetLanguage { super("C#", ["cs", "csharp"], "cs"); } - protected getOptions(): Array> { + protected getOptions(): Array> { return [ cSharpOptions.framework, cSharpOptions.namespace, @@ -254,10 +255,7 @@ export class CSharpTargetLanguage extends TargetLanguage { return need !== "none" && need !== "nullable"; } - protected makeRenderer( - renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } - ): ConvenienceRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): ConvenienceRenderer { const options = getOptionValues(cSharpOptions, untypedOptionValues); switch (options.framework) { diff --git a/packages/quicktype-core/src/language/Crystal.ts b/packages/quicktype-core/src/language/Crystal.ts index 1376c488c..3b06122af 100644 --- a/packages/quicktype-core/src/language/Crystal.ts +++ b/packages/quicktype-core/src/language/Crystal.ts @@ -20,6 +20,7 @@ import { } from "../support/Strings"; import { TargetLanguage } from "../TargetLanguage"; import { type ClassType, type EnumType, type Type, type UnionType } from "../Type"; +import { type FixMeOptionsAnyType } from "../types"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; export class CrystalTargetLanguage extends TargetLanguage { @@ -35,7 +36,7 @@ export class CrystalTargetLanguage extends TargetLanguage { return " "; } - protected getOptions(): Array> { + protected getOptions(): Array> { return []; } } diff --git a/packages/quicktype-core/src/language/Dart.ts b/packages/quicktype-core/src/language/Dart.ts index 71360e7d1..59476c982 100644 --- a/packages/quicktype-core/src/language/Dart.ts +++ b/packages/quicktype-core/src/language/Dart.ts @@ -33,6 +33,7 @@ import { type UnionType } from "../Type"; import { type StringTypeMapping } from "../TypeBuilder"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; import { directlyReachableSingleNamedType, matchType, nullableFromUnion } from "../TypeUtils"; export const dartOptions = { @@ -64,7 +65,7 @@ export class DartTargetLanguage extends TargetLanguage { super("Dart", ["dart"], "dart"); } - protected getOptions(): Array> { + protected getOptions(): Array> { return [ dartOptions.nullSafety, dartOptions.justTypes, @@ -91,7 +92,7 @@ export class DartTargetLanguage extends TargetLanguage { return mapping; } - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): DartRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): DartRenderer { const options = getOptionValues(dartOptions, untypedOptionValues); return new DartRenderer(this, renderContext, options); } diff --git a/packages/quicktype-core/src/language/Elm.ts b/packages/quicktype-core/src/language/Elm.ts index 426764b63..ced7837b4 100644 --- a/packages/quicktype-core/src/language/Elm.ts +++ b/packages/quicktype-core/src/language/Elm.ts @@ -29,6 +29,7 @@ import { import { defined } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; import { type ClassProperty, type ClassType, type EnumType, type Type, UnionType } from "../Type"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; import { matchType, nullableFromUnion } from "../TypeUtils"; export const elmOptions = { @@ -46,7 +47,7 @@ export class ElmTargetLanguage extends TargetLanguage { super("Elm", ["elm"], "elm"); } - protected getOptions(): Array> { + protected getOptions(): Array> { return [elmOptions.justTypes, elmOptions.moduleName, elmOptions.useList]; } @@ -58,7 +59,7 @@ export class ElmTargetLanguage extends TargetLanguage { return true; } - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): ElmRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): ElmRenderer { return new ElmRenderer(this, renderContext, getOptionValues(elmOptions, untypedOptionValues)); } } diff --git a/packages/quicktype-core/src/language/Golang.ts b/packages/quicktype-core/src/language/Golang.ts index 277c083f5..9a2081af6 100644 --- a/packages/quicktype-core/src/language/Golang.ts +++ b/packages/quicktype-core/src/language/Golang.ts @@ -19,6 +19,7 @@ import { import { assert, defined } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; import { type ClassProperty, type ClassType, type EnumType, type Type, type TypeKind, UnionType } from "../Type"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; export const goOptions = { @@ -39,7 +40,7 @@ export class GoTargetLanguage extends TargetLanguage { super("Go", ["go", "golang"], "go"); } - protected getOptions(): Array> { + protected getOptions(): Array> { return [ goOptions.justTypes, goOptions.justTypesAndPackage, @@ -64,7 +65,7 @@ export class GoTargetLanguage extends TargetLanguage { return true; } - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): GoRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): GoRenderer { return new GoRenderer(this, renderContext, getOptionValues(goOptions, untypedOptionValues)); } diff --git a/packages/quicktype-core/src/language/Haskell.ts b/packages/quicktype-core/src/language/Haskell.ts index 7b7b7ef49..16cd16a35 100644 --- a/packages/quicktype-core/src/language/Haskell.ts +++ b/packages/quicktype-core/src/language/Haskell.ts @@ -26,6 +26,7 @@ import { } from "../support/Strings"; import { TargetLanguage } from "../TargetLanguage"; import { type ClassProperty, type ClassType, type EnumType, type Type, type UnionType } from "../Type"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; import { matchType, nullableFromUnion } from "../TypeUtils"; export const haskellOptions = { @@ -42,7 +43,7 @@ export class HaskellTargetLanguage extends TargetLanguage { super("Haskell", ["haskell"], "haskell"); } - protected getOptions(): Array> { + protected getOptions(): Array> { return [haskellOptions.justTypes, haskellOptions.moduleName, haskellOptions.useList]; } @@ -54,10 +55,7 @@ export class HaskellTargetLanguage extends TargetLanguage { return true; } - protected makeRenderer( - renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } - ): HaskellRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): HaskellRenderer { return new HaskellRenderer(this, renderContext, getOptionValues(haskellOptions, untypedOptionValues)); } } diff --git a/packages/quicktype-core/src/language/JSONSchema.ts b/packages/quicktype-core/src/language/JSONSchema.ts index ab7e85b1e..978906075 100644 --- a/packages/quicktype-core/src/language/JSONSchema.ts +++ b/packages/quicktype-core/src/language/JSONSchema.ts @@ -22,6 +22,7 @@ import { transformedStringTypeTargetTypeKindsMap } from "../Type"; import { type StringTypeMapping, getNoStringTypeMapping } from "../TypeBuilder"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; import { matchTypeExhaustive } from "../TypeUtils"; export class JSONSchemaTargetLanguage extends TargetLanguage { @@ -29,7 +30,7 @@ export class JSONSchemaTargetLanguage extends TargetLanguage { super("JSON Schema", ["schema", "json-schema"], "schema"); } - protected getOptions(): Array> { + protected getOptions(): Array> { return []; } @@ -45,10 +46,7 @@ export class JSONSchemaTargetLanguage extends TargetLanguage { return true; } - protected makeRenderer( - renderContext: RenderContext, - _untypedOptionValues: { [name: string]: any } - ): JSONSchemaRenderer { + protected makeRenderer(renderContext: RenderContext, _untypedOptionValues: FixMeOptionsType): JSONSchemaRenderer { return new JSONSchemaRenderer(this, renderContext); } } @@ -72,6 +70,7 @@ function jsonNameStyle(original: string): string { } interface Schema { + // eslint-disable-next-line @typescript-eslint/no-explicit-any [name: string]: any; } @@ -121,7 +120,7 @@ export class JSONSchemaRenderer extends ConvenienceRenderer { } private schemaForType(t: Type): Schema { - const schema = matchTypeExhaustive<{ [name: string]: any }>( + const schema = matchTypeExhaustive( t, _noneType => { return panic("none type should have been replaced"); diff --git a/packages/quicktype-core/src/language/Java.ts b/packages/quicktype-core/src/language/Java.ts index 7080be5e9..6954a13f4 100644 --- a/packages/quicktype-core/src/language/Java.ts +++ b/packages/quicktype-core/src/language/Java.ts @@ -40,6 +40,7 @@ import { type TypeKind, UnionType } from "../Type"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; import { directlyReachableSingleNamedType, matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; export const javaOptions = { @@ -74,7 +75,7 @@ export class JavaTargetLanguage extends TargetLanguage { super("Java", ["java"], "java"); } - protected getOptions(): Array> { + protected getOptions(): Array> { return [ javaOptions.useList, javaOptions.justTypes, @@ -90,7 +91,7 @@ export class JavaTargetLanguage extends TargetLanguage { return true; } - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): JavaRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): JavaRenderer { const options = getOptionValues(javaOptions, untypedOptionValues); if (options.justTypes) { return new JavaRenderer(this, renderContext, options); diff --git a/packages/quicktype-core/src/language/JavaScript.ts b/packages/quicktype-core/src/language/JavaScript.ts index 0cf29f4ff..ff435edc1 100644 --- a/packages/quicktype-core/src/language/JavaScript.ts +++ b/packages/quicktype-core/src/language/JavaScript.ts @@ -28,6 +28,7 @@ import { type Type } from "../Type"; import { type StringTypeMapping } from "../TypeBuilder"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; import { directlyReachableSingleNamedType, matchType } from "../TypeUtils"; import { isES3IdentifierPart, isES3IdentifierStart } from "./JavaScriptUnicodeMaps"; @@ -69,7 +70,7 @@ export class JavaScriptTargetLanguage extends TargetLanguage { super(displayName, names, extension); } - protected getOptions(): Array> { + protected getOptions(): Array> { return [ javaScriptOptions.runtimeTypecheck, javaScriptOptions.runtimeTypecheckIgnoreUnknownProperties, @@ -95,10 +96,7 @@ export class JavaScriptTargetLanguage extends TargetLanguage { return true; } - protected makeRenderer( - renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } - ): JavaScriptRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): JavaScriptRenderer { return new JavaScriptRenderer(this, renderContext, getOptionValues(javaScriptOptions, untypedOptionValues)); } } diff --git a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts index cbdd4e6ad..a2ae5b40c 100644 --- a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts +++ b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts @@ -17,7 +17,8 @@ import { utf16StringEscape } from "../support/Strings"; import { TargetLanguage } from "../TargetLanguage"; -import { type ClassProperty, type ClassType, type ObjectType, PrimitiveType, type Type } from "../Type"; +import { type ClassProperty, type ClassType, type ObjectType, PrimitiveType, type Type, ArrayType } from "../Type"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; import { directlyReachableSingleNamedType, matchType } from "../TypeUtils"; import { legalizeName } from "./JavaScript"; @@ -38,7 +39,7 @@ export const javaScriptPropTypesOptions = { }; export class JavaScriptPropTypesTargetLanguage extends TargetLanguage { - protected getOptions(): Array> { + protected getOptions(): Array> { return [javaScriptPropTypesOptions.acronymStyle, javaScriptPropTypesOptions.converters]; } @@ -52,7 +53,7 @@ export class JavaScriptPropTypesTargetLanguage extends TargetLanguage { protected makeRenderer( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } + untypedOptionValues: FixMeOptionsType ): JavaScriptPropTypesRenderer { return new JavaScriptPropTypesRenderer( this, @@ -271,7 +272,7 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { } else { if (type.kind === "array") { this.ensureBlankLine(); - this.emitExport(name, ["PropTypes.arrayOf(", this.typeMapTypeFor((type as any).items), ")"]); + this.emitExport(name, ["PropTypes.arrayOf(", this.typeMapTypeFor((type as ArrayType).items), ")"]); } else { this.ensureBlankLine(); this.emitExport(name, ["_", name]); diff --git a/packages/quicktype-core/src/language/Kotlin.ts b/packages/quicktype-core/src/language/Kotlin.ts index f6fcebb04..06de856a7 100644 --- a/packages/quicktype-core/src/language/Kotlin.ts +++ b/packages/quicktype-core/src/language/Kotlin.ts @@ -36,6 +36,7 @@ import { type Type, UnionType } from "../Type"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; export enum Framework { @@ -66,7 +67,7 @@ export class KotlinTargetLanguage extends TargetLanguage { super("Kotlin", ["kotlin"], "kt"); } - protected getOptions(): Array> { + protected getOptions(): Array> { return [kotlinOptions.framework, kotlinOptions.acronymStyle, kotlinOptions.packageName]; } @@ -78,10 +79,7 @@ export class KotlinTargetLanguage extends TargetLanguage { return true; } - protected makeRenderer( - renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } - ): ConvenienceRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): ConvenienceRenderer { const options = getOptionValues(kotlinOptions, untypedOptionValues); switch (options.framework) { diff --git a/packages/quicktype-core/src/language/Objective-C.ts b/packages/quicktype-core/src/language/Objective-C.ts index f6d3e47d5..00d678f30 100644 --- a/packages/quicktype-core/src/language/Objective-C.ts +++ b/packages/quicktype-core/src/language/Objective-C.ts @@ -29,6 +29,7 @@ import { import { assert, defined } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; import { ArrayType, type ClassProperty, ClassType, EnumType, MapType, Type, UnionType } from "../Type"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; import { isAnyOrNull, matchType, nullableFromUnion } from "../TypeUtils"; export type MemoryAttribute = "assign" | "strong" | "copy"; @@ -57,7 +58,7 @@ export class ObjectiveCTargetLanguage extends TargetLanguage { super("Objective-C", ["objc", "objective-c", "objectivec"], "m"); } - protected getOptions(): Array> { + protected getOptions(): Array> { return [ objcOptions.justTypes, objcOptions.classPrefix, @@ -67,10 +68,7 @@ export class ObjectiveCTargetLanguage extends TargetLanguage { ]; } - protected makeRenderer( - renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } - ): ObjectiveCRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): ObjectiveCRenderer { return new ObjectiveCRenderer(this, renderContext, getOptionValues(objcOptions, untypedOptionValues)); } } diff --git a/packages/quicktype-core/src/language/Php.ts b/packages/quicktype-core/src/language/Php.ts index fd0888dcf..f3b07ef2f 100644 --- a/packages/quicktype-core/src/language/Php.ts +++ b/packages/quicktype-core/src/language/Php.ts @@ -25,6 +25,7 @@ import { import { defined } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; import { type ClassProperty, type ClassType, type EnumType, type Type, type UnionType } from "../Type"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; import { directlyReachableSingleNamedType, matchType, nullableFromUnion } from "../TypeUtils"; export const phpOptions = { @@ -40,7 +41,7 @@ export class PhpTargetLanguage extends TargetLanguage { super("PHP", ["php"], "php"); } - protected getOptions(): Array> { + protected getOptions(): Array> { return _.values(phpOptions); } @@ -48,7 +49,7 @@ export class PhpTargetLanguage extends TargetLanguage { return true; } - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): PhpRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): PhpRenderer { const options = getOptionValues(phpOptions, untypedOptionValues); return new PhpRenderer(this, renderContext, options); } diff --git a/packages/quicktype-core/src/language/Pike.ts b/packages/quicktype-core/src/language/Pike.ts index dc57a3fc4..fd2a8b2b9 100644 --- a/packages/quicktype-core/src/language/Pike.ts +++ b/packages/quicktype-core/src/language/Pike.ts @@ -6,6 +6,7 @@ import { type MultiWord, type Sourcelike, multiWord, parenIfNeeded, singleWord } import { isLetterOrUnderscoreOrDigit, legalizeCharacters, makeNameStyle, stringEscape } from "../support/Strings"; import { TargetLanguage } from "../TargetLanguage"; import { ArrayType, type ClassType, type EnumType, MapType, PrimitiveType, type Type, type UnionType } from "../Type"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; export const pikeOptions = {}; @@ -75,7 +76,7 @@ export class PikeTargetLanguage extends TargetLanguage { super("Pike", ["pike", "pikelang"], "pmod"); } - protected getOptions(): Array> { + protected getOptions(): Array> { return []; } diff --git a/packages/quicktype-core/src/language/Python.ts b/packages/quicktype-core/src/language/Python.ts index b6092a9d1..1066fcd11 100644 --- a/packages/quicktype-core/src/language/Python.ts +++ b/packages/quicktype-core/src/language/Python.ts @@ -48,6 +48,7 @@ import { UnionType } from "../Type"; import { type StringTypeMapping } from "../TypeBuilder"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; const forbiddenTypeNames = [ @@ -130,7 +131,7 @@ export const pythonOptions = { }; export class PythonTargetLanguage extends TargetLanguage { - protected getOptions(): Array> { + protected getOptions(): Array> { return [pythonOptions.features, pythonOptions.justTypes, pythonOptions.nicePropertyNames]; } @@ -162,7 +163,7 @@ export class PythonTargetLanguage extends TargetLanguage { return t.kind === "integer-string" || t.kind === "bool-string"; } - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): PythonRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): PythonRenderer { const options = getOptionValues(pythonOptions, untypedOptionValues); if (options.justTypes) { return new PythonRenderer(this, renderContext, options); diff --git a/packages/quicktype-core/src/language/Rust.ts b/packages/quicktype-core/src/language/Rust.ts index f73a67f7b..2ffa07689 100644 --- a/packages/quicktype-core/src/language/Rust.ts +++ b/packages/quicktype-core/src/language/Rust.ts @@ -23,6 +23,7 @@ import { import { defined } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; import { type ClassType, type EnumType, type Type, UnionType } from "../Type"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; export enum Density { @@ -112,7 +113,7 @@ const namingStyles: Record = { }; export class RustTargetLanguage extends TargetLanguage { - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): RustRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): RustRenderer { return new RustRenderer(this, renderContext, getOptionValues(rustOptions, untypedOptionValues)); } @@ -120,7 +121,7 @@ export class RustTargetLanguage extends TargetLanguage { super("Rust", ["rust", "rs", "rustlang"], "rs"); } - protected getOptions(): Array> { + protected getOptions(): Array> { return [ rustOptions.density, rustOptions.visibility, @@ -346,7 +347,7 @@ export class RustRenderer extends ConvenienceRenderer { ); } - private breakCycle(t: Type, withIssues: boolean): any { + private breakCycle(t: Type, withIssues: boolean): Sourcelike { const rustType = this.rustType(t, withIssues); const isCycleBreaker = this.isCycleBreakerType(t); diff --git a/packages/quicktype-core/src/language/Scala3.ts b/packages/quicktype-core/src/language/Scala3.ts index a736ecada..38a7cd451 100644 --- a/packages/quicktype-core/src/language/Scala3.ts +++ b/packages/quicktype-core/src/language/Scala3.ts @@ -27,6 +27,7 @@ import { type Type, type UnionType } from "../Type"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; export enum Framework { @@ -745,7 +746,7 @@ export class Scala3TargetLanguage extends TargetLanguage { super("Scala3", ["scala3"], "scala"); } - protected getOptions(): Array> { + protected getOptions(): Array> { return [scala3Options.framework, scala3Options.packageName]; } @@ -757,10 +758,7 @@ export class Scala3TargetLanguage extends TargetLanguage { return true; } - protected makeRenderer( - renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } - ): ConvenienceRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): ConvenienceRenderer { const options = getOptionValues(scala3Options, untypedOptionValues); switch (options.framework) { diff --git a/packages/quicktype-core/src/language/Smithy4s.ts b/packages/quicktype-core/src/language/Smithy4s.ts index 24ba6b028..2abe6f27f 100644 --- a/packages/quicktype-core/src/language/Smithy4s.ts +++ b/packages/quicktype-core/src/language/Smithy4s.ts @@ -27,6 +27,7 @@ import { type Type, type UnionType } from "../Type"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; import { matchCompoundType, matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; export enum Framework { @@ -529,7 +530,7 @@ export class SmithyTargetLanguage extends TargetLanguage { super("Smithy", ["Smithy"], "smithy"); } - protected getOptions(): Array> { + protected getOptions(): Array> { return [SmithyOptions.framework, SmithyOptions.packageName]; } @@ -541,10 +542,7 @@ export class SmithyTargetLanguage extends TargetLanguage { return true; } - protected makeRenderer( - renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } - ): ConvenienceRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): ConvenienceRenderer { const options = getOptionValues(SmithyOptions, untypedOptionValues); switch (options.framework) { diff --git a/packages/quicktype-core/src/language/Swift.ts b/packages/quicktype-core/src/language/Swift.ts index 627218116..d46f56780 100644 --- a/packages/quicktype-core/src/language/Swift.ts +++ b/packages/quicktype-core/src/language/Swift.ts @@ -47,6 +47,7 @@ import { type UnionType } from "../Type"; import { type StringTypeMapping } from "../TypeBuilder"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; const MAX_SAMELINE_PROPERTIES = 4; @@ -141,7 +142,7 @@ export class SwiftTargetLanguage extends TargetLanguage { super("Swift", ["swift", "swift4"], "swift"); } - protected getOptions(): Array> { + protected getOptions(): Array> { return [ swiftOptions.justTypes, swiftOptions.useClasses, @@ -177,7 +178,7 @@ export class SwiftTargetLanguage extends TargetLanguage { return true; } - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): SwiftRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): SwiftRenderer { return new SwiftRenderer(this, renderContext, getOptionValues(swiftOptions, untypedOptionValues)); } diff --git a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts index 9db2d827a..d288fea9a 100644 --- a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts +++ b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts @@ -19,6 +19,7 @@ import { import { panic } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; import { ArrayType, type ClassProperty, EnumType, MapType, type ObjectType, type Type } from "../Type"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; import { matchType } from "../TypeUtils"; import { legalizeName } from "./JavaScript"; @@ -28,7 +29,7 @@ export const typeScriptEffectSchemaOptions = { }; export class TypeScriptEffectSchemaTargetLanguage extends TargetLanguage { - protected getOptions(): Array> { + protected getOptions(): Array> { return []; } @@ -42,7 +43,7 @@ export class TypeScriptEffectSchemaTargetLanguage extends TargetLanguage { protected makeRenderer( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } + untypedOptionValues: FixMeOptionsType ): TypeScriptEffectSchemaRenderer { return new TypeScriptEffectSchemaRenderer( this, diff --git a/packages/quicktype-core/src/language/TypeScriptFlow.ts b/packages/quicktype-core/src/language/TypeScriptFlow.ts index f63c2d473..a0f6216b3 100644 --- a/packages/quicktype-core/src/language/TypeScriptFlow.ts +++ b/packages/quicktype-core/src/language/TypeScriptFlow.ts @@ -6,6 +6,7 @@ import { camelCase, utf16StringEscape } from "../support/Strings"; import { defined, panic } from "../support/Support"; import { type TargetLanguage } from "../TargetLanguage"; import { ArrayType, type ClassType, EnumType, type Type, UnionType } from "../Type"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; import { isNamedType, matchType, nullableFromUnion } from "../TypeUtils"; import { @@ -41,7 +42,7 @@ const tsFlowTypeAnnotations = { }; export abstract class TypeScriptFlowBaseTargetLanguage extends JavaScriptTargetLanguage { - protected getOptions(): Array> { + protected getOptions(): Array> { return [ tsFlowOptions.justTypes, tsFlowOptions.nicePropertyNames, @@ -64,7 +65,7 @@ export abstract class TypeScriptFlowBaseTargetLanguage extends JavaScriptTargetL protected abstract makeRenderer( renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } + untypedOptionValues: FixMeOptionsType ): JavaScriptRenderer; } @@ -73,10 +74,7 @@ export class TypeScriptTargetLanguage extends TypeScriptFlowBaseTargetLanguage { super("TypeScript", ["typescript", "ts", "tsx"], "ts"); } - protected makeRenderer( - renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } - ): TypeScriptRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): TypeScriptRenderer { return new TypeScriptRenderer(this, renderContext, getOptionValues(tsFlowOptions, untypedOptionValues)); } } @@ -348,7 +346,7 @@ export class FlowTargetLanguage extends TypeScriptFlowBaseTargetLanguage { super("Flow", ["flow"], "js"); } - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): FlowRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): FlowRenderer { return new FlowRenderer(this, renderContext, getOptionValues(tsFlowOptions, untypedOptionValues)); } } diff --git a/packages/quicktype-core/src/language/TypeScriptZod.ts b/packages/quicktype-core/src/language/TypeScriptZod.ts index d52c4eff7..57a67d1d2 100644 --- a/packages/quicktype-core/src/language/TypeScriptZod.ts +++ b/packages/quicktype-core/src/language/TypeScriptZod.ts @@ -30,6 +30,7 @@ import { type Type } from "../Type"; import { type StringTypeMapping } from "../TypeBuilder"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; import { matchType } from "../TypeUtils"; import { legalizeName } from "./JavaScript"; @@ -39,7 +40,7 @@ export const typeScriptZodOptions = { }; export class TypeScriptZodTargetLanguage extends TargetLanguage { - protected getOptions(): Array> { + protected getOptions(): Array> { return []; } @@ -62,10 +63,7 @@ export class TypeScriptZodTargetLanguage extends TargetLanguage { return true; } - protected makeRenderer( - renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } - ): TypeScriptZodRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): TypeScriptZodRenderer { return new TypeScriptZodRenderer( this, renderContext, diff --git a/packages/quicktype-core/src/language/ruby/index.ts b/packages/quicktype-core/src/language/ruby/index.ts index 10abe40d6..feb6e7608 100644 --- a/packages/quicktype-core/src/language/ruby/index.ts +++ b/packages/quicktype-core/src/language/ruby/index.ts @@ -36,6 +36,7 @@ import { type Type, type UnionType } from "../../Type"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../../TypeUtils"; import * as keywords from "./keywords"; @@ -69,7 +70,7 @@ export class RubyTargetLanguage extends TargetLanguage { super("Ruby", ["ruby"], "rb"); } - protected getOptions(): Array> { + protected getOptions(): Array> { return [rubyOptions.justTypes, rubyOptions.strictness, rubyOptions.namespace]; } @@ -81,7 +82,7 @@ export class RubyTargetLanguage extends TargetLanguage { return " "; } - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): RubyRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): RubyRenderer { return new RubyRenderer(this, renderContext, getOptionValues(rubyOptions, untypedOptionValues)); } } diff --git a/packages/quicktype-core/src/support/Support.ts b/packages/quicktype-core/src/support/Support.ts index 31e78fd4b..3778ed3ed 100644 --- a/packages/quicktype-core/src/support/Support.ts +++ b/packages/quicktype-core/src/support/Support.ts @@ -5,19 +5,20 @@ import * as YAML from "yaml"; import { messageError } from "../Messages"; export interface StringMap { + // eslint-disable-next-line @typescript-eslint/no-explicit-any [name: string]: any; } -export function isStringMap(x: any): x is StringMap; -export function isStringMap(x: any, checkValue: (v: any) => v is T): x is { [name: string]: T }; -export function isStringMap(x: any, checkValue?: (v: any) => v is T): boolean { +export function isStringMap(x: unknown): x is StringMap; +export function isStringMap(x: unknown, checkValue: (v: unknown) => v is T): x is { [name: string]: T }; +export function isStringMap(x: unknown, checkValue?: (v: unknown) => v is T): boolean { if (typeof x !== "object" || Array.isArray(x) || x === null) { return false; } if (checkValue !== undefined) { for (const k of Object.getOwnPropertyNames(x)) { - const v = x[k]; + const v = x[k as keyof typeof x]; if (!checkValue(v)) { return false; } @@ -27,20 +28,27 @@ export function isStringMap(x: any, checkValue?: (v: any) => v is T): boolean return true; } -export function checkString(x: any): x is string { +export function checkString(x: unknown): x is string { return typeof x === "string"; } -export function checkStringMap(x: any): StringMap; -export function checkStringMap(x: any, checkValue: (v: any) => v is T): { [name: string]: T }; -export function checkStringMap(x: any, checkValue?: (v: any) => v is T): StringMap { - if (isStringMap(x, checkValue as any)) return x; +export function checkStringMap(x: unknown): StringMap; +export function checkStringMap(x: unknown, checkValue: (v: unknown) => v is T): { [name: string]: T }; +export function checkStringMap(x: unknown, checkValue?: (v: unknown) => v is T): StringMap { + if (checkValue && isStringMap(x, checkValue)) { + return x; + } + + if (isStringMap(x)) { + return x; + } + return panic(`Value must be an object, but is ${x}`); } -export function checkArray(x: any): any[]; -export function checkArray(x: any, checkItem: (v: any) => v is T): T[]; -export function checkArray(x: any, checkItem?: (v: any) => v is T): T[] { +export function checkArray(x: unknown): unknown[]; +export function checkArray(x: unknown, checkItem: (v: unknown) => v is T): T[]; +export function checkArray(x: unknown, checkItem?: (v: unknown) => v is T): T[] { if (!Array.isArray(x)) { return panic(`Value must be an array, but is ${x}`); } @@ -67,7 +75,7 @@ export function nonNull(x: T | null): T { } export function assertNever(x: never): never { - return messageError("InternalError", { message: `Unexpected object ${x as any}` }); + return messageError("InternalError", { message: `Unexpected object ${x}` }); } export function assert(condition: boolean, message = "Assertion failed"): void { @@ -102,12 +110,12 @@ export function repeatedCall(n: number, producer: () => T): T[] { return arr; } -export function errorMessage(e: any): string { +export function errorMessage(e: unknown): string { if (e instanceof Error) { return e.message; } - return e.toString(); + return (e as { toString: () => string }).toString(); } export function inflateBase64(encoded: string): string { @@ -115,7 +123,7 @@ export function inflateBase64(encoded: string): string { return pako.inflate(bytes, { to: "string" }); } -export function parseJSON(text: string, description: string, address = ""): any { +export function parseJSON(text: string, description: string, address = ""): unknown { try { // https://gist.github.com/pbakondy/f5045eff725193dad9c7 if (text.charCodeAt(0) === 0xfeff) { @@ -140,7 +148,8 @@ export function indentationString(level: number): string { return " ".repeat(level); } -export function numberEnumValues(e: { [key: string]: any }): number[] { +// FIXME: fix this enum iteration +export function numberEnumValues(e: Record): number[] { const result: number[] = []; for (const k of Object.keys(e)) { const v = e[k]; diff --git a/packages/quicktype-core/src/types.ts b/packages/quicktype-core/src/types.ts new file mode 100644 index 000000000..2b26cc2be --- /dev/null +++ b/packages/quicktype-core/src/types.ts @@ -0,0 +1,6 @@ +// FIXME: remove these when options are strongly types + +/* eslint-disable @typescript-eslint/no-explicit-any */ +export type FixMeOptionsType = Record; + +export type FixMeOptionsAnyType = any; diff --git a/packages/quicktype-graphql-input/src/index.ts b/packages/quicktype-graphql-input/src/index.ts index a6c1f53e2..1b18754ac 100644 --- a/packages/quicktype-graphql-input/src/index.ts +++ b/packages/quicktype-graphql-input/src/index.ts @@ -389,7 +389,7 @@ class GQLSchemaFromJSON implements GQLSchema { public readonly mutationType?: GQLType; - public constructor(json: any) { + public constructor(json: { data: GraphQLSchema }) { const schema: GraphQLSchema = json.data; if (schema.__schema.queryType.name === null) { @@ -498,7 +498,7 @@ class GQLSchemaFromJSON implements GQLSchema { function makeGraphQLQueryTypes( topLevelName: string, builder: TypeBuilder, - json: any, + json: { data: GraphQLSchema }, queryString: string ): Map { const schema = new GQLSchemaFromJSON(json); @@ -546,11 +546,13 @@ function makeGraphQLQueryTypes( export interface GraphQLSourceData { name: string; query: string; + // eslint-disable-next-line @typescript-eslint/no-explicit-any schema: any; } interface GraphQLTopLevel { query: string; + // eslint-disable-next-line @typescript-eslint/no-explicit-any schema: any; } diff --git a/src/CompressedJSONFromStream.ts b/src/CompressedJSONFromStream.ts index 40db6d87b..7d7be8830 100644 --- a/src/CompressedJSONFromStream.ts +++ b/src/CompressedJSONFromStream.ts @@ -23,14 +23,15 @@ export class CompressedJSONFromStream extends CompressedJSON { const combo = new Parser({ packKeys: true, packStrings: true }); combo.on("data", (item: { name: string; value: string | undefined }) => { if (typeof methodMap[item.name] === "string") { - (this as any)[methodMap[item.name]](item.value); + // @ts-expect-error FIXME: strongly type this + this[methodMap[item.name]](item.value); } }); const promise = new Promise((resolve, reject) => { combo.on("end", () => { resolve(this.finish()); }); - combo.on("error", (err: any) => { + combo.on("error", (err: unknown) => { reject(err); }); }); diff --git a/src/URLGrammar.ts b/src/URLGrammar.ts index 3ffdc26a8..3eaaaa1ca 100644 --- a/src/URLGrammar.ts +++ b/src/URLGrammar.ts @@ -1,6 +1,6 @@ import { checkArray, checkStringMap, panic } from "quicktype-core"; -function expand(json: any): string[] { +function expand(json: unknown): string[] { if (typeof json === "string") { return [json]; } @@ -22,7 +22,7 @@ function expand(json: any): string[] { return result; } - if (Object.prototype.hasOwnProperty.call(json, "oneOf")) { + if (typeof json === "object" && json && "oneOf" in json) { const options = checkArray(json.oneOf); const result: string[] = []; for (const j of options) { @@ -37,7 +37,7 @@ function expand(json: any): string[] { return panic(`Value is not a valid URL grammar: ${json}`); } -export function urlsFromURLGrammar(json: any): { [name: string]: string[] } { +export function urlsFromURLGrammar(json: unknown): { [name: string]: string[] } { const topLevelMap = checkStringMap(json); const results: { [name: string]: string[] } = {}; diff --git a/src/index.ts b/src/index.ts index 6804ef731..5006b0bde 100644 --- a/src/index.ts +++ b/src/index.ts @@ -60,6 +60,7 @@ const wordWrap: (s: string) => string = _wordwrap(90); export interface CLIOptions { // We use this to access the inference flags + // eslint-disable-next-line @typescript-eslint/no-explicit-any [option: string]: any; additionalSchema: string[]; allPropertiesOptional: boolean; @@ -199,7 +200,8 @@ async function samplesFromDirectory(dataDir: string, httpHeaders?: string[]): Pr return messageError("DriverCannotMixJSONWithOtherSamples", { dir: dir }); } - const oneUnlessEmpty = (xs: any[]) => Math.sign(xs.length); + // FIXME: rewrite this to be clearer + const oneUnlessEmpty = (xs: TypeSource[]) => Math.sign(xs.length); if (oneUnlessEmpty(schemaSources) + oneUnlessEmpty(graphQLSources) > 1) { return messageError("DriverCannotMixNonJSONInputs", { dir: dir }); } @@ -594,6 +596,8 @@ export function parseCLIOptions(argv: string[], targetLanguage?: TargetLanguage) // according to each option definition's `renderer` field. If `partial` is false this // will throw if it encounters an unknown option. function parseOptions(definitions: OptionDefinition[], argv: string[], partial: boolean): Partial { + // FIXME: update this when options strongly typed + // eslint-disable-next-line @typescript-eslint/no-explicit-any let opts: { [key: string]: any }; try { opts = commandLineArgs(definitions, { argv, partial }); @@ -610,6 +614,7 @@ function parseOptions(definitions: OptionDefinition[], argv: string[], partial: } } + // eslint-disable-next-line @typescript-eslint/no-explicit-any const options: { [key: string]: any; rendererOptions: RendererOptions } = { rendererOptions: {} }; for (const o of definitions) { if (!hasOwnProperty(opts, o.name)) continue; From f0e76151fd7c86658db020f15327552a57434b08 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Fri, 12 Apr 2024 20:26:24 -0700 Subject: [PATCH 38/94] fix misc errors --- packages/quicktype-core/src/Annotation.ts | 1 + packages/quicktype-core/src/TypeGraph.ts | 1 + packages/quicktype-core/src/TypeUtils.ts | 6 +----- packages/quicktype-core/src/UnifyClasses.ts | 2 ++ .../quicktype-core/src/input/JSONSchemaInput.ts | 2 +- .../quicktype-core/src/input/JSONSchemaStore.ts | 4 +++- .../src/input/io/get-stream/index.ts | 10 +++++----- packages/quicktype-core/src/language/CJSON.ts | 4 ++++ packages/quicktype-core/src/language/Dart.ts | 4 ++++ .../src/language/JavaScriptPropTypes.ts | 14 +++++++------- packages/quicktype-core/src/language/Kotlin.ts | 1 + packages/quicktype-core/src/language/Php.ts | 8 ++++---- packages/quicktype-core/src/language/Python.ts | 2 ++ packages/quicktype-core/src/language/Rust.ts | 6 +++++- packages/quicktype-core/src/language/Scala3.ts | 2 +- .../src/language/TypeScriptEffectSchema.ts | 16 ++++++++-------- .../quicktype-core/src/language/TypeScriptZod.ts | 3 +++ .../quicktype-core/src/rewrites/ExpandStrings.ts | 4 +++- .../src/rewrites/ResolveIntersections.ts | 3 ++- packages/quicktype-core/src/support/Strings.ts | 2 ++ src/CompressedJSONFromStream.ts | 2 +- 21 files changed, 61 insertions(+), 36 deletions(-) diff --git a/packages/quicktype-core/src/Annotation.ts b/packages/quicktype-core/src/Annotation.ts index 38cb82622..1b3a937bf 100644 --- a/packages/quicktype-core/src/Annotation.ts +++ b/packages/quicktype-core/src/Annotation.ts @@ -1,3 +1,4 @@ +// eslint-disable-next-line @typescript-eslint/no-extraneous-class export class AnnotationData {} export class IssueAnnotationData extends AnnotationData { diff --git a/packages/quicktype-core/src/TypeGraph.ts b/packages/quicktype-core/src/TypeGraph.ts index 3e229bd51..cdd8d5ea6 100644 --- a/packages/quicktype-core/src/TypeGraph.ts +++ b/packages/quicktype-core/src/TypeGraph.ts @@ -403,6 +403,7 @@ export class TypeGraph { } public rewriteFixedPoint(alphabetizeProperties: boolean, debugPrintReconstitution: boolean): TypeGraph { + // eslint-disable-next-line @typescript-eslint/no-this-alias let graph: TypeGraph = this; for (;;) { const newGraph = this.rewrite( diff --git a/packages/quicktype-core/src/TypeUtils.ts b/packages/quicktype-core/src/TypeUtils.ts index f4ab36d34..f0136fc32 100644 --- a/packages/quicktype-core/src/TypeUtils.ts +++ b/packages/quicktype-core/src/TypeUtils.ts @@ -40,11 +40,7 @@ export function assertIsClass(t: Type): ClassType { } export function setOperationMembersRecursively( - setOperation: T, - combinationKind: CombinationKind | undefined -): [ReadonlySet, TypeAttributes]; -export function setOperationMembersRecursively( - setOperations: T[], + setOperations: T | T[], combinationKind: CombinationKind | undefined ): [ReadonlySet, TypeAttributes]; export function setOperationMembersRecursively( diff --git a/packages/quicktype-core/src/UnifyClasses.ts b/packages/quicktype-core/src/UnifyClasses.ts index f1e6ab3e0..8fe16817c 100644 --- a/packages/quicktype-core/src/UnifyClasses.ts +++ b/packages/quicktype-core/src/UnifyClasses.ts @@ -34,6 +34,8 @@ function getCliqueProperties( } } + // FIXME: refactor this + // eslint-disable-next-line @typescript-eslint/prefer-for-of for (let i = 0; i < properties.length; i++) { let [name, types, isOptional] = properties[i]; const maybeProperty = o.getProperties().get(name); diff --git a/packages/quicktype-core/src/input/JSONSchemaInput.ts b/packages/quicktype-core/src/input/JSONSchemaInput.ts index 0938bae22..244e682be 100644 --- a/packages/quicktype-core/src/input/JSONSchemaInput.ts +++ b/packages/quicktype-core/src/input/JSONSchemaInput.ts @@ -208,7 +208,7 @@ export class Ref { } public push(...keys: string[]): Ref { - let ref: Ref = this; + let ref: Ref = { ...this }; for (const key of keys) { ref = ref.pushElement({ kind: PathElementKind.KeyOrIndex, key }); } diff --git a/packages/quicktype-core/src/input/JSONSchemaStore.ts b/packages/quicktype-core/src/input/JSONSchemaStore.ts index 4292bf08c..02d93e8e0 100644 --- a/packages/quicktype-core/src/input/JSONSchemaStore.ts +++ b/packages/quicktype-core/src/input/JSONSchemaStore.ts @@ -25,7 +25,9 @@ export abstract class JSONSchemaStore { try { schema = await this.fetch(address); - } catch {} + } catch (e) { + // FIXME: handle or log this error + } if (schema === undefined) { if (debugPrint) { diff --git a/packages/quicktype-core/src/input/io/get-stream/index.ts b/packages/quicktype-core/src/input/io/get-stream/index.ts index 6cf051d51..3f1dcbc4b 100644 --- a/packages/quicktype-core/src/input/io/get-stream/index.ts +++ b/packages/quicktype-core/src/input/io/get-stream/index.ts @@ -50,15 +50,15 @@ export async function getStream(inputStream: Readable, opts: Options = {}) { }; }); - p.then(clean, clean); - - return await p.then(() => stream.getBufferedValue()); + return await p.then(clean, clean).then(() => stream.getBufferedValue()); } +// FIXME: should these be async ? export function buffer(stream: Readable, opts: Options = {}) { - getStream(stream, Object.assign({}, opts, { encoding: "buffer" })); + void getStream(stream, Object.assign({}, opts, { encoding: "buffer" })); } +// FIXME: should these be async ? export function array(stream: Readable, opts: Options = {}) { - getStream(stream, Object.assign({}, opts, { array: true })); + void getStream(stream, Object.assign({}, opts, { array: true })); } diff --git a/packages/quicktype-core/src/language/CJSON.ts b/packages/quicktype-core/src/language/CJSON.ts index 88e78f414..ba6891857 100644 --- a/packages/quicktype-core/src/language/CJSON.ts +++ b/packages/quicktype-core/src/language/CJSON.ts @@ -1,3 +1,6 @@ +// FIXME: NEEDS REFACTOR +/* eslint-disable @typescript-eslint/no-shadow */ +/* eslint-disable @typescript-eslint/naming-convention */ /** * CJSON.ts * This file is used to generate cJSON code with quicktype @@ -784,6 +787,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param unionType: union type */ protected emitUnionTypedef(unionType: UnionType): void { + // eslint-disable-next-line @typescript-eslint/no-unused-vars const [_hasNull, nonNulls] = removeNullFromUnion(unionType); const unionName = this.nameForNamedType(unionType); diff --git a/packages/quicktype-core/src/language/Dart.ts b/packages/quicktype-core/src/language/Dart.ts index 59476c982..42b6f3e70 100644 --- a/packages/quicktype-core/src/language/Dart.ts +++ b/packages/quicktype-core/src/language/Dart.ts @@ -461,9 +461,11 @@ export class DartRenderer extends ConvenienceRenderer { return [this.nameForNamedType(classType), ".", this.fromJson, "(", dynamic, ")"]; } + // FIXME: refactor this // If the first time is the unionType type, after nullableFromUnion conversion, // the isNullable property will become false, which is obviously wrong, // so add isNullable property + // eslint-disable-next-line @typescript-eslint/default-param-last protected fromDynamicExpression(isNullable: boolean = false, t: Type, ...dynamic: Sourcelike[]): Sourcelike { return matchType( t, @@ -524,9 +526,11 @@ export class DartRenderer extends ConvenienceRenderer { ); } + // FIXME: refactor this // If the first time is the unionType type, after nullableFromUnion conversion, // the isNullable property will become false, which is obviously wrong, // so add isNullable property + // eslint-disable-next-line @typescript-eslint/default-param-last protected toDynamicExpression(isNullable: boolean = false, t: Type, ...dynamic: Sourcelike[]): Sourcelike { return matchType( t, diff --git a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts index a2ae5b40c..8bd7c0e05 100644 --- a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts +++ b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts @@ -17,7 +17,7 @@ import { utf16StringEscape } from "../support/Strings"; import { TargetLanguage } from "../TargetLanguage"; -import { type ClassProperty, type ClassType, type ObjectType, PrimitiveType, type Type, ArrayType } from "../Type"; +import { type ArrayType, type ClassProperty, type ClassType, type ObjectType, PrimitiveType, type Type } from "../Type"; import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; import { directlyReachableSingleNamedType, matchType } from "../TypeUtils"; @@ -244,18 +244,18 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { const names = source.filter(value => value as Name); // must be behind all these names - for (let i = 0; i < names.length; i++) { - const depName = names[i]; + names.forEach(name => { + const depName = name; // find this name's ordinal, if it has already been added - for (let j = 0; j < order.length; j++) { - const depIndex = order[j]; + order.forEach(orderItem => { + const depIndex = orderItem; if (mapKey[depIndex] === depName) { // this is the index of the dependency, so make sure we come after it ordinal = Math.max(ordinal, depIndex + 1); } - } - } + }); + }); // insert index order.splice(ordinal, 0, index); diff --git a/packages/quicktype-core/src/language/Kotlin.ts b/packages/quicktype-core/src/language/Kotlin.ts index 06de856a7..01bf4cd9d 100644 --- a/packages/quicktype-core/src/language/Kotlin.ts +++ b/packages/quicktype-core/src/language/Kotlin.ts @@ -181,6 +181,7 @@ function unicodeEscape(codePoint: number): string { return "\\u" + intToHex(codePoint, 4); } +// eslint-disable-next-line @typescript-eslint/naming-convention const _stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, unicodeEscape)); function stringEscape(s: string): string { diff --git a/packages/quicktype-core/src/language/Php.ts b/packages/quicktype-core/src/language/Php.ts index f3b07ef2f..617f461fe 100644 --- a/packages/quicktype-core/src/language/Php.ts +++ b/packages/quicktype-core/src/language/Php.ts @@ -367,7 +367,7 @@ export class PhpRenderer extends ConvenienceRenderer { } protected phpToObjConvert(className: Name, t: Type, lhs: Sourcelike[], args: Sourcelike[]) { - matchType( + matchType( t, _anyType => this.emitLine(...lhs, ...args, "; /*any*/"), _nullType => this.emitLine(...lhs, ...args, "; /*null*/"), @@ -429,7 +429,7 @@ export class PhpRenderer extends ConvenienceRenderer { } protected phpFromObjConvert(className: Name, t: Type, lhs: Sourcelike[], args: Sourcelike[]) { - matchType( + matchType( t, _anyType => this.emitLine(...lhs, ...args, "; /*any*/"), _nullType => this.emitLine(...lhs, ...args, "; /*null*/"), @@ -492,7 +492,7 @@ export class PhpRenderer extends ConvenienceRenderer { idx: number, suffix: Sourcelike ) { - matchType( + matchType( t, _anyType => this.emitLine( @@ -593,7 +593,7 @@ export class PhpRenderer extends ConvenienceRenderer { ); }; - matchType( + matchType( t, _anyType => is("defined"), _nullType => is("is_null"), diff --git a/packages/quicktype-core/src/language/Python.ts b/packages/quicktype-core/src/language/Python.ts index 1066fcd11..37e5106b4 100644 --- a/packages/quicktype-core/src/language/Python.ts +++ b/packages/quicktype-core/src/language/Python.ts @@ -581,6 +581,8 @@ export interface ValueOrLambda { // * If `input` is a value, the result is `f(input)`. // * If `input` is a lambda, the result is `lambda x: f(input(x))` function compose(input: ValueOrLambda, f: (arg: Sourcelike) => Sourcelike): ValueOrLambda; +// FIXME: refactor this +// eslint-disable-next-line @typescript-eslint/unified-signatures function compose(input: ValueOrLambda, f: ValueOrLambda): ValueOrLambda; function compose(input: ValueOrLambda, f: ValueOrLambda | ((arg: Sourcelike) => Sourcelike)): ValueOrLambda { if (typeof f === "function") { diff --git a/packages/quicktype-core/src/language/Rust.ts b/packages/quicktype-core/src/language/Rust.ts index 2ffa07689..ca36ca6d8 100644 --- a/packages/quicktype-core/src/language/Rust.ts +++ b/packages/quicktype-core/src/language/Rust.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/naming-convention */ import { mapFirst } from "collection-utils"; import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; @@ -414,7 +415,10 @@ export class RustRenderer extends ConvenienceRenderer { this.forEachClassProperty(c, blankLines, (name, jsonName, prop) => { this.emitDescription(this.descriptionForClassProperty(c, jsonName)); this.emitRenameAttribute(name, jsonName, defaultStyle, preferedNamingStyle); - this._options.skipSerializingNone && this.emitSkipSerializeNone(prop.type); + if (this._options.skipSerializingNone) { + this.emitSkipSerializeNone(prop.type); + } + this.emitLine(this.visibility, name, ": ", this.breakCycle(prop.type, true), ","); }); diff --git a/packages/quicktype-core/src/language/Scala3.ts b/packages/quicktype-core/src/language/Scala3.ts index 38a7cd451..69dc3c9fd 100644 --- a/packages/quicktype-core/src/language/Scala3.ts +++ b/packages/quicktype-core/src/language/Scala3.ts @@ -558,7 +558,7 @@ export class Smithy4sRenderer extends Scala3Renderer { export class CirceRenderer extends Scala3Renderer { private seenUnionTypes: string[] = []; - protected circeEncoderForType(t: Type, _ = false, noOptional = false, paramName: string = ""): Sourcelike { + protected circeEncoderForType(t: Type, __ = false, noOptional = false, paramName: string = ""): Sourcelike { return matchType( t, _anyType => ["Encoder.encodeJson(", paramName, ")"], diff --git a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts index d288fea9a..470a79efb 100644 --- a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts +++ b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts @@ -181,7 +181,7 @@ export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { } } - protected walkObjectNames(type: ObjectType) { + protected walkObjectNames(objectType: ObjectType) { const names: Name[] = []; const recurse = (type: Type) => { @@ -201,7 +201,7 @@ export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { } }; - this.forEachClassProperty(type, "none", (_, __, prop) => { + this.forEachClassProperty(objectType, "none", (_, __, prop) => { recurse(prop.type); }); @@ -232,18 +232,18 @@ export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { const names = this.walkObjectNames(source); // must be behind all these names - for (let i = 0; i < names.length; i++) { - const depName = names[i]; + names.forEach(name => { + const depName = name; // find this name's ordinal, if it has already been added - for (let j = 0; j < order.length; j++) { - const depIndex = order[j]; + order.forEach(orderItem => { + const depIndex = orderItem; if (mapKey[depIndex] === depName) { // this is the index of the dependency, so make sure we come after it ordinal = Math.max(ordinal, depIndex + 1); } - } - } + }); + }); // insert index order.splice(ordinal, 0, index); diff --git a/packages/quicktype-core/src/language/TypeScriptZod.ts b/packages/quicktype-core/src/language/TypeScriptZod.ts index 57a67d1d2..69cd77fda 100644 --- a/packages/quicktype-core/src/language/TypeScriptZod.ts +++ b/packages/quicktype-core/src/language/TypeScriptZod.ts @@ -300,6 +300,9 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { let found = false; // find this childs's ordinal, if it has already been added // faster to go through what we've defined so far than all definitions + + // FIXME: refactor this + // eslint-disable-next-line @typescript-eslint/prefer-for-of for (let j = 0; j < order.length; j++) { const childIndex = order[j]; if (mapTypeRef[childIndex] === childRef) { diff --git a/packages/quicktype-core/src/rewrites/ExpandStrings.ts b/packages/quicktype-core/src/rewrites/ExpandStrings.ts index c1ee3331e..abddcfab5 100644 --- a/packages/quicktype-core/src/rewrites/ExpandStrings.ts +++ b/packages/quicktype-core/src/rewrites/ExpandStrings.ts @@ -68,7 +68,7 @@ export function expandStrings(ctx: RunContext, graph: TypeGraph, inference: Enum const keys = Array.from(cases.keys()); if (isAlwaysEmptyString(keys)) return undefined; - const someCaseIsNotNumber = iterableSome(keys, key => /^(\-|\+)?[0-9]+(\.[0-9]+)?$/.test(key) === false); + const someCaseIsNotNumber = iterableSome(keys, key => /^[-+]?[0-9]+(\.[0-9]+)?$/.test(key) === false); if (!someCaseIsNotNumber) return undefined; } @@ -85,6 +85,8 @@ export function expandStrings(ctx: RunContext, graph: TypeGraph, inference: Enum enumInfos.set(t, enumInfo); } + // FIXME: refactor this + // eslint-disable-next-line no-inner-declarations function findOverlap(newCases: ReadonlySet, newAreSubordinate: boolean): number { return enumSets.findIndex(s => enumCasesOverlap(newCases, s, newAreSubordinate)); } diff --git a/packages/quicktype-core/src/rewrites/ResolveIntersections.ts b/packages/quicktype-core/src/rewrites/ResolveIntersections.ts index ffe2f8a64..a992ead9f 100644 --- a/packages/quicktype-core/src/rewrites/ResolveIntersections.ts +++ b/packages/quicktype-core/src/rewrites/ResolveIntersections.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/brace-style */ import { iterableEvery, iterableFind, @@ -186,7 +187,7 @@ class IntersectionAccumulator public addType(t: Type): TypeAttributes { let attributes = t.getAttributes(); - matchTypeExhaustive( + matchTypeExhaustive( t, _noneType => { return panic("There shouldn't be a none type"); diff --git a/packages/quicktype-core/src/support/Strings.ts b/packages/quicktype-core/src/support/Strings.ts index 1ea40e3d6..bd76ee4f9 100644 --- a/packages/quicktype-core/src/support/Strings.ts +++ b/packages/quicktype-core/src/support/Strings.ts @@ -52,6 +52,7 @@ function precomputedCodePointPredicate(p: CodePointPredicate): CodePointPredicat export function utf16ConcatMap(mapper: (utf16Unit: number) => string): (s: string) => string { const { charStringMap, charNoEscapeMap } = computeAsciiMap(mapper); + // eslint-disable-next-line @typescript-eslint/naming-convention return function stringConcatMap_inner(s: string): string { let cs: string[] | null = null; let start = 0; @@ -94,6 +95,7 @@ function isLowSurrogate(cc: number): boolean { export function utf32ConcatMap(mapper: (codePoint: number) => string): (s: string) => string { const { charStringMap, charNoEscapeMap } = computeAsciiMap(mapper); + // eslint-disable-next-line @typescript-eslint/naming-convention return function stringConcatMap_inner(s: string): string { let cs: string[] | null = null; let start = 0; diff --git a/src/CompressedJSONFromStream.ts b/src/CompressedJSONFromStream.ts index 7d7be8830..16a9c78b0 100644 --- a/src/CompressedJSONFromStream.ts +++ b/src/CompressedJSONFromStream.ts @@ -48,7 +48,7 @@ export class CompressedJSONFromStream extends CompressedJSON { protected handleNumberChunk = (s: string): void => { const ctx = this.context; - if (!ctx.currentNumberIsDouble && /[\.e]/i.test(s)) { + if (!ctx.currentNumberIsDouble && /[.e]/i.test(s)) { ctx.currentNumberIsDouble = true; } }; From c0232f36e45ac222f32c50d0ea80c80518b18621 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Fri, 12 Apr 2024 20:26:39 -0700 Subject: [PATCH 39/94] downgrade remaining to warnings --- .eslintignore | 2 ++ .eslintrc.json | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.eslintignore b/.eslintignore index 0fd88d904..135b09976 100644 --- a/.eslintignore +++ b/.eslintignore @@ -4,3 +4,5 @@ packages/*/dist packages/*/node_modules test/runs test/input + +license diff --git a/.eslintrc.json b/.eslintrc.json index a5cf75933..f35b5c03c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -27,6 +27,8 @@ "rules": { "comma-dangle": "off", "no-extra-parens": "off", + "no-case-declarations": "warn", + "no-duplicate-imports": "error", "canonical/prefer-inline-type-import": "error", "typescript-sort-keys/string-enum": "off", @@ -36,7 +38,6 @@ "ignoreDeclarationSort": true } ], - "no-duplicate-imports": "error", "import/first": "error", "import/order": [ "error", @@ -72,10 +73,10 @@ "@typescript-eslint/indent": "off", "@typescript-eslint/quotes": ["error", "double", { "avoidEscape": true }], "@typescript-eslint/member-delimiter-style": "off", - "@typescript-eslint/naming-convention": "error", "@typescript-eslint/no-base-to-string": "warn", "@typescript-eslint/no-empty-interface": "warn", "@typescript-eslint/no-extra-parens": "off", + "@typescript-eslint/no-loop-func": "warn", "@typescript-eslint/no-misused-promises": ["error", { "checksVoidReturn": false }], "@typescript-eslint/no-unused-vars": ["error", { "vars": "local", "args": "none" }], "@typescript-eslint/no-use-before-define": "warn", @@ -85,6 +86,7 @@ "@typescript-eslint/require-array-sort-compare": "off", "@typescript-eslint/space-before-function-paren": "off", "@typescript-eslint/switch-exhaustiveness-check": "error", + "@typescript-eslint/unbound-method": "warn", "@typescript-eslint/unified-signatures": "error" }, "overrides": [ From 59e877fab6e8bdf0f008adb240a89b4b1645a382 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Fri, 12 Apr 2024 20:55:42 -0700 Subject: [PATCH 40/94] return types --- .../quicktype-core/src/ConvenienceRenderer.ts | 10 ++-- packages/quicktype-core/src/GatherNames.ts | 4 +- .../quicktype-core/src/MakeTransformations.ts | 4 +- packages/quicktype-core/src/MarkovChain.ts | 2 +- packages/quicktype-core/src/Naming.ts | 2 +- packages/quicktype-core/src/Transformers.ts | 8 +-- packages/quicktype-core/src/Type.ts | 7 ++- packages/quicktype-core/src/TypeUtils.ts | 2 +- .../src/attributes/EnumValues.ts | 2 +- .../src/input/JSONSchemaInput.ts | 16 +++--- packages/quicktype-core/src/language/CJSON.ts | 10 ++-- .../quicktype-core/src/language/CPlusPlus.ts | 8 +-- .../quicktype-core/src/language/Crystal.ts | 2 +- packages/quicktype-core/src/language/Dart.ts | 2 +- packages/quicktype-core/src/language/Java.ts | 14 ++--- .../quicktype-core/src/language/JavaScript.ts | 10 ++-- .../src/language/JavaScriptPropTypes.ts | 6 +-- .../quicktype-core/src/language/Kotlin.ts | 26 ++++----- .../src/language/Objective-C.ts | 20 +++---- packages/quicktype-core/src/language/Php.ts | 54 +++++++++++++------ packages/quicktype-core/src/language/Pike.ts | 12 ++--- .../quicktype-core/src/language/Python.ts | 5 +- packages/quicktype-core/src/language/Rust.ts | 6 +-- .../quicktype-core/src/language/Scala3.ts | 8 +-- .../quicktype-core/src/language/Smithy4s.ts | 4 +- packages/quicktype-core/src/language/Swift.ts | 12 ++--- .../src/language/TypeScriptEffectSchema.ts | 8 +-- .../src/language/TypeScriptFlow.ts | 6 +-- .../src/language/TypeScriptZod.ts | 4 +- .../quicktype-core/src/language/ruby/index.ts | 20 +++---- .../quicktype-core/src/support/Acronyms.ts | 2 +- .../quicktype-core/src/support/Converters.ts | 2 +- src/index.ts | 6 +-- 33 files changed, 166 insertions(+), 138 deletions(-) diff --git a/packages/quicktype-core/src/ConvenienceRenderer.ts b/packages/quicktype-core/src/ConvenienceRenderer.ts index df5e02578..2c9c6ff42 100644 --- a/packages/quicktype-core/src/ConvenienceRenderer.ts +++ b/packages/quicktype-core/src/ConvenienceRenderer.ts @@ -681,7 +681,7 @@ export abstract class ConvenienceRenderer extends Renderer { protected forEachDeclaration( blankLocations: BlankLineConfig, f: (decl: Declaration, position: ForEachPosition) => void - ) { + ): void { this.forEachWithBlankLines( iterableEnumerate(defined(this._declarationIR).declarations), blankLocations, @@ -748,7 +748,7 @@ export abstract class ConvenienceRenderer extends Renderer { ): void { const iterateMembers = members ?? u.members; if (sortOrder === null) { - sortOrder = n => defined(this.names.get(n)); + sortOrder = (n): string => defined(this.names.get(n)); } const memberNames = mapFilter(defined(this._memberNamesStoreView).get(u), (_, t) => iterateMembers.has(t)); @@ -922,7 +922,7 @@ export abstract class ConvenienceRenderer extends Renderer { makePropertyRow: (name: Name, jsonName: string, p: ClassProperty) => Sourcelike[] ): void { let table: Sourcelike[][] = []; - const emitTable = () => { + const emitTable = (): void => { if (table.length === 0) return; this.emitTable(table); table = []; @@ -943,7 +943,7 @@ export abstract class ConvenienceRenderer extends Renderer { private processGraph(): void { this._declarationIR = declarationsForGraph( this.typeGraph, - this.needsTypeDeclarationBeforeUse ? t => this.canBeForwardDeclared(t) : undefined, + this.needsTypeDeclarationBeforeUse ? (t): boolean => this.canBeForwardDeclared(t) : undefined, t => this.childrenOfType(t), t => { if (t instanceof UnionType) { @@ -976,7 +976,7 @@ export abstract class ConvenienceRenderer extends Renderer { const processed = new Set(); const queue = Array.from(this.typeGraph.topLevels.values()); - function visit(t: Type) { + function visit(t: Type): void { if (visitedTypes.has(t)) return; for (const c of t.getChildren()) { queue.push(c); diff --git a/packages/quicktype-core/src/GatherNames.ts b/packages/quicktype-core/src/GatherNames.ts index 2dba2afb3..4d8142d07 100644 --- a/packages/quicktype-core/src/GatherNames.ts +++ b/packages/quicktype-core/src/GatherNames.ts @@ -102,7 +102,7 @@ export function gatherNames(graph: TypeGraph, destructive: boolean, debugPrint: // null means there are too many const namesForType = new Map | null>(); - function addNames(t: Type, names: ReadonlySet | null) { + function addNames(t: Type, names: ReadonlySet | null): void { // Always use the type's given names if it has some if (t.hasNames) { const originalNames = t.getNames(); @@ -217,7 +217,7 @@ export function gatherNames(graph: TypeGraph, destructive: boolean, debugPrint: return null; } - function processType(ancestor: Type | undefined, t: Type, alternativeSuffix: string | undefined) { + function processType(ancestor: Type | undefined, t: Type, alternativeSuffix: string | undefined): void { const names = defined(namesForType.get(t)); let processedEntry = pairsProcessed.get(ancestor); diff --git a/packages/quicktype-core/src/MakeTransformations.ts b/packages/quicktype-core/src/MakeTransformations.ts index fc3bf23f5..106eebbd5 100644 --- a/packages/quicktype-core/src/MakeTransformations.ts +++ b/packages/quicktype-core/src/MakeTransformations.ts @@ -118,7 +118,7 @@ function replaceUnion( ? builder.getUnionType(union.getAttributes(), reconstitutedMemberSet) : defined(iterableFirst(reconstitutedMemberSet)); - function memberForKind(kind: TypeKind) { + function memberForKind(kind: TypeKind): number { return defined(reconstitutedMembersByKind.get(kind)); } @@ -127,7 +127,7 @@ function replaceUnion( return new UnionInstantiationTransformer(graph, memberTypeRef); } - function transformerForKind(kind: TypeKind) { + function transformerForKind(kind: TypeKind): DecodingTransformer | undefined { const member = union.findMember(kind); if (member === undefined) return undefined; const memberTypeRef = memberForKind(kind); diff --git a/packages/quicktype-core/src/MarkovChain.ts b/packages/quicktype-core/src/MarkovChain.ts index 9a3fa5f84..dec67dc1f 100644 --- a/packages/quicktype-core/src/MarkovChain.ts +++ b/packages/quicktype-core/src/MarkovChain.ts @@ -123,7 +123,7 @@ export function evaluate(mc: MarkovChain, word: string): number { return evaluateFull(mc, word)[0]; } -function randomInt(lower: number, upper: number) { +function randomInt(lower: number, upper: number): number { const range = upper - lower; return lower + Math.floor(Math.random() * range); } diff --git a/packages/quicktype-core/src/Naming.ts b/packages/quicktype-core/src/Naming.ts index d23dd30fc..94c6ca452 100644 --- a/packages/quicktype-core/src/Naming.ts +++ b/packages/quicktype-core/src/Naming.ts @@ -319,7 +319,7 @@ export class DependencyName extends Name { } } -export function keywordNamespace(name: string, keywords: string[]) { +export function keywordNamespace(name: string, keywords: string[]): Namespace { const ns = new Namespace(name, undefined, [], []); for (const kw of keywords) { ns.add(new FixedName(kw)); diff --git a/packages/quicktype-core/src/Transformers.ts b/packages/quicktype-core/src/Transformers.ts index b1b93bfa3..d6bbb49f7 100644 --- a/packages/quicktype-core/src/Transformers.ts +++ b/packages/quicktype-core/src/Transformers.ts @@ -449,7 +449,7 @@ export class DecodingChoiceTransformer extends Transformer { public get transformers(): readonly Transformer[] { const transformers: Transformer[] = []; - function add(xfer: Transformer | undefined) { + function add(xfer: Transformer | undefined): void { if (xfer === undefined) return; transformers.push(xfer); } @@ -496,7 +496,7 @@ export class DecodingChoiceTransformer extends Transformer { let transformers = new Map(); let memberMatchTransformers = new Map(); - function addCase(reversed: Transformer) { + function addCase(reversed: Transformer): void { if (reversed instanceof UnionMemberMatchTransformer) { const memberType = reversed.memberType; let arr = memberMatchTransformers.get(memberType); @@ -518,7 +518,7 @@ export class DecodingChoiceTransformer extends Transformer { } } - function reverseAndAdd(transformer: Transformer) { + function reverseAndAdd(transformer: Transformer): void { const reversed = transformer.reverse(targetTypeRef, undefined); let cases: readonly Transformer[] = []; // Flatten nested ChoiceTransformers @@ -578,7 +578,7 @@ export class DecodingChoiceTransformer extends Transformer { } public reconstitute(builder: TBuilder): Transformer { - function reconstitute(xf: Transformer | undefined) { + function reconstitute(xf: Transformer | undefined): Transformer | undefined { if (xf === undefined) return undefined; return xf.reconstitute(builder); } diff --git a/packages/quicktype-core/src/Type.ts b/packages/quicktype-core/src/Type.ts index d5bab5cf2..cdbae768e 100644 --- a/packages/quicktype-core/src/Type.ts +++ b/packages/quicktype-core/src/Type.ts @@ -373,7 +373,7 @@ export class ArrayType extends Type { super(typeRef, graph); } - public setItems(itemsRef: TypeRef) { + public setItems(itemsRef: TypeRef): void { if (this._itemsRef !== undefined) { return panic("Can only set array items once"); } @@ -514,7 +514,10 @@ export class ObjectType extends Type { } } - public setProperties(properties: ReadonlyMap, additionalPropertiesRef: TypeRef | undefined) { + public setProperties( + properties: ReadonlyMap, + additionalPropertiesRef: TypeRef | undefined + ): void { assert(this._properties === undefined, "Tried to set object properties twice"); if (this instanceof MapType) { diff --git a/packages/quicktype-core/src/TypeUtils.ts b/packages/quicktype-core/src/TypeUtils.ts index f0136fc32..b2ae456f7 100644 --- a/packages/quicktype-core/src/TypeUtils.ts +++ b/packages/quicktype-core/src/TypeUtils.ts @@ -296,7 +296,7 @@ export function matchType( unionType: (unionType: UnionType) => U, transformedStringType?: (transformedStringType: PrimitiveType) => U ): U { - function typeNotSupported(t: Type) { + function typeNotSupported(t: Type): never { return panic(`Unsupported type ${t.kind} in non-exhaustive match`); } diff --git a/packages/quicktype-core/src/attributes/EnumValues.ts b/packages/quicktype-core/src/attributes/EnumValues.ts index 1f66958e3..05885ada9 100644 --- a/packages/quicktype-core/src/attributes/EnumValues.ts +++ b/packages/quicktype-core/src/attributes/EnumValues.ts @@ -12,7 +12,7 @@ class EnumValuesTypeAttributeKind extends TypeAttributeKind { super("enumValues"); } - public makeInferred(_: AccessorNames) { + public makeInferred(_: AccessorNames): undefined { return undefined; } } diff --git a/packages/quicktype-core/src/input/JSONSchemaInput.ts b/packages/quicktype-core/src/input/JSONSchemaInput.ts index 244e682be..a88e78157 100644 --- a/packages/quicktype-core/src/input/JSONSchemaInput.ts +++ b/packages/quicktype-core/src/input/JSONSchemaInput.ts @@ -296,7 +296,7 @@ export class Ref { } private lookup(local: unknown, path: readonly PathElement[], root: JSONSchema): JSONSchema { - const refMaker = () => new Ref(this.addressURI, path); + const refMaker = (): Ref => new Ref(this.addressURI, path); const first = path[0]; if (first === undefined) { return checkJSONSchema(local, refMaker); @@ -391,7 +391,7 @@ class Location { this.virtualRef = virtualRef ?? canonicalRef; } - public updateWithID(id: string | unknown) { + public updateWithID(id: string | unknown): Location { if (typeof id !== "string") return this; const parsed = Ref.parse(id); const virtual = this.haveID ? parsed.resolveAgainst(this.virtualRef) : parsed; @@ -426,7 +426,7 @@ class Canonizer { public constructor(private readonly _ctx: RunContext) {} - private addIDs(schema: unknown, loc: Location) { + private addIDs(schema: unknown, loc: Location): void { if (schema === null) return; if (Array.isArray(schema)) { for (let i = 0; i < schema.length; i++) { @@ -681,7 +681,7 @@ async function addTypesInSchema( properties: StringMap, requiredArray: string[], additionalProperties: unknown, - sortKey: (k: string) => number | string = (k: string) => k.toLowerCase() + sortKey: (k: string) => number | string = (k: string): string => k.toLowerCase() ): Promise { const required = new Set(requiredArray); const propertiesMap = mapSortBy(mapFromObject(properties), (_, k) => sortKey(k)); @@ -739,13 +739,13 @@ async function addTypesInSchema( let predicate: (x: unknown) => boolean; switch (name) { case "null": - predicate = (x: unknown) => x === null; + predicate = (x): x is null => x === null; break; case "integer": - predicate = (x: unknown) => typeof x === "number" && x === Math.floor(x); + predicate = (x): x is number => typeof x === "number" && x === Math.floor(x); break; default: - predicate = (x: unknown) => typeof x === name; + predicate = (x): x is typeof name => typeof x === name; break; } @@ -908,7 +908,7 @@ async function addTypesInSchema( combineProducedAttributes(({ forObject }) => forObject) ); const order = schema.quicktypePropertyOrder ? schema.quicktypePropertyOrder : []; - const orderKey = (propertyName: string) => { + const orderKey = (propertyName: string): string => { // use the index of the order array const index = order.indexOf(propertyName); // if no index then use the property name diff --git a/packages/quicktype-core/src/language/CJSON.ts b/packages/quicktype-core/src/language/CJSON.ts index ba6891857..3cfe6b976 100644 --- a/packages/quicktype-core/src/language/CJSON.ts +++ b/packages/quicktype-core/src/language/CJSON.ts @@ -498,7 +498,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param fieldType: the variable type * @param fieldName: name of the variable */ - protected emitTypdefAlias(fieldType: Type, fieldName: Name) { + protected emitTypedefAlias(fieldType: Type, fieldName: Name) { if (this._options.addTypedefAlias) { this.emitLine("typedef ", this.quicktypeTypeToCJSON(fieldType, false).cType, " ", fieldName, ";"); this.ensureBlankLine(); @@ -686,7 +686,7 @@ export class CJSONRenderer extends ConvenienceRenderer { true ); this.ensureBlankLine(); - this.emitTypdefAlias(enumType, enumName); + this.emitTypedefAlias(enumType, enumName); } /** @@ -819,7 +819,7 @@ export class CJSONRenderer extends ConvenienceRenderer { true ); this.ensureBlankLine(); - this.emitTypdefAlias(unionType, unionName); + this.emitTypedefAlias(unionType, unionName); } /** @@ -1697,7 +1697,7 @@ export class CJSONRenderer extends ConvenienceRenderer { true ); this.ensureBlankLine(); - this.emitTypdefAlias(classType, className); + this.emitTypedefAlias(classType, className); } /** @@ -3295,7 +3295,7 @@ export class CJSONRenderer extends ConvenienceRenderer { true ); this.ensureBlankLine(); - this.emitTypdefAlias(type, className); + this.emitTypedefAlias(type, className); } /** diff --git a/packages/quicktype-core/src/language/CPlusPlus.ts b/packages/quicktype-core/src/language/CPlusPlus.ts index c787a8778..910f714f9 100644 --- a/packages/quicktype-core/src/language/CPlusPlus.ts +++ b/packages/quicktype-core/src/language/CPlusPlus.ts @@ -1136,7 +1136,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { */ protected generatedTypes(isClassMember: boolean, theType: Type): TypeRecord[] { const result: TypeRecord[] = []; - const recur = (forceInclude: boolean, isVariant: boolean, l: number, t: Type) => { + const recur = (forceInclude: boolean, isVariant: boolean, l: number, t: Type): void => { if (t instanceof ArrayType) { recur(true, isVariant, l + 1, t.items); } else if (t instanceof ClassType) { @@ -1953,7 +1953,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.emitLine("void to_json(json & j, ", this.withConst([ourQualifier, enumName]), " & x);"); } - private isLargeEnum(e: EnumType) { + private isLargeEnum(e: EnumType): boolean { // This is just an estimation. Someone might want to do some // benchmarks to find the optimum value here return e.cases.size > 15; @@ -2125,7 +2125,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.emitLine("#define NLOHMANN_OPT_HELPER"); this.emitNamespaces(["nlohmann"], () => { - const emitAdlStruct = (optType: string, factory: string) => { + const emitAdlStruct = (optType: string, factory: string): void => { this.emitLine("template "); this.emitBlock(["struct adl_serializer<", optType, ">"], true, () => { this.emitBlock( @@ -2995,7 +2995,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } - protected isConversionRequired(t: Type) { + protected isConversionRequired(t: Type): boolean { const originalType = this.cppType( t, { diff --git a/packages/quicktype-core/src/language/Crystal.ts b/packages/quicktype-core/src/language/Crystal.ts index 3b06122af..9816191bc 100644 --- a/packages/quicktype-core/src/language/Crystal.ts +++ b/packages/quicktype-core/src/language/Crystal.ts @@ -322,7 +322,7 @@ export class CrystalRenderer extends ConvenienceRenderer { protected emitStructDefinition(c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); - const structBody = () => + const structBody = (): void => this.forEachClassProperty(c, "none", (name, jsonName, prop) => { this.ensureBlankLine(); this.emitDescription(this.descriptionForClassProperty(c, jsonName)); diff --git a/packages/quicktype-core/src/language/Dart.ts b/packages/quicktype-core/src/language/Dart.ts index 42b6f3e70..d8d471ec9 100644 --- a/packages/quicktype-core/src/language/Dart.ts +++ b/packages/quicktype-core/src/language/Dart.ts @@ -444,7 +444,7 @@ export class DartRenderer extends ConvenienceRenderer { return ["Map.from(", map, ").map((k, v) => MapEntry(k, ", valueMapper, "))"]; } - protected mapClass(isNullable: boolean, classType: ClassType, dynamic: Sourcelike) { + protected mapClass(isNullable: boolean, classType: ClassType, dynamic: Sourcelike): Sourcelike { if (this._options.nullSafety && isNullable && !this._options.requiredProperties) { return [ dynamic, diff --git a/packages/quicktype-core/src/language/Java.ts b/packages/quicktype-core/src/language/Java.ts index 6954a13f4..d800e9fbf 100644 --- a/packages/quicktype-core/src/language/Java.ts +++ b/packages/quicktype-core/src/language/Java.ts @@ -664,7 +664,7 @@ export class JavaRenderer extends ConvenienceRenderer { this.emitLine("}"); } - public emitTryCatch(main: () => void, handler: () => void, exception = "Exception") { + public emitTryCatch(main: () => void, handler: () => void, exception = "Exception"): void { this.emitLine("try {"); this.indent(main); this.emitLine("} catch (", exception, " ex) {"); @@ -672,7 +672,7 @@ export class JavaRenderer extends ConvenienceRenderer { this.emitLine("}"); } - public emitIgnoredTryCatchBlock(f: () => void) { + public emitIgnoredTryCatchBlock(f: () => void): void { this.emitTryCatch(f, () => this.emitLine("// Ignored")); } @@ -913,11 +913,11 @@ export class JavaRenderer extends ConvenienceRenderer { this.finishFile(); } - protected emitEnumSerializationAttributes(_e: EnumType) { + protected emitEnumSerializationAttributes(_e: EnumType): void { // Empty } - protected emitEnumDeserializationAttributes(_e: EnumType) { + protected emitEnumDeserializationAttributes(_e: EnumType): void { // Empty } @@ -1158,7 +1158,7 @@ export class JacksonRenderer extends JavaRenderer { }); }; - const emitStringDeserializer = () => { + const emitStringDeserializer = (): void => { const enumType = u.findMember("enum"); const stringType = u.findMember("string"); @@ -1307,11 +1307,11 @@ export class JacksonRenderer extends JavaRenderer { }); } - protected emitEnumSerializationAttributes(_e: EnumType) { + protected emitEnumSerializationAttributes(_e: EnumType): void { this.emitLine("@JsonValue"); } - protected emitEnumDeserializationAttributes(_e: EnumType) { + protected emitEnumDeserializationAttributes(_e: EnumType): void { this.emitLine("@JsonCreator"); } diff --git a/packages/quicktype-core/src/language/JavaScript.ts b/packages/quicktype-core/src/language/JavaScript.ts index ff435edc1..440502cff 100644 --- a/packages/quicktype-core/src/language/JavaScript.ts +++ b/packages/quicktype-core/src/language/JavaScript.ts @@ -122,7 +122,7 @@ export class JavaScriptRenderer extends ConvenienceRenderer { legalizeName, upper ? firstUpperWordStyle : allLowerWordStyle, firstUpperWordStyle, - upper ? s => capitalize(acronyms(s)) : allLowerWordStyle, + upper ? (s): string => capitalize(acronyms(s)) : allLowerWordStyle, acronyms, "", isES3IdentifierStart @@ -204,13 +204,13 @@ export class JavaScriptRenderer extends ConvenienceRenderer { return ["u(undefined, ", typeMap, ")"]; } - protected emitBlock(source: Sourcelike, end: Sourcelike, emit: () => void) { + protected emitBlock(source: Sourcelike, end: Sourcelike, emit: () => void): void { this.emitLine(source, "{"); this.indent(emit); this.emitLine("}", end); } - private emitTypeMap() { + private emitTypeMap(): void { const { any: anyAnnotation } = this.typeAnnotations; this.emitBlock(`const typeMap${anyAnnotation} = `, ";", () => { @@ -284,7 +284,7 @@ export class JavaScriptRenderer extends ConvenienceRenderer { } protected emitConvertModuleBody(): void { - const converter = (t: Type, name: Name) => { + const converter = (t: Type, name: Name): void => { const typeMap = this.typeMapTypeFor(t); this.emitBlock([this.deserializerFunctionLine(t, name), " "], "", () => { const parsedJson = this._jsOptions.rawType === "json" ? "JSON.parse(json)" : "json"; @@ -553,7 +553,7 @@ function r(name${stringAnnotation}) { }); } - protected emitSourceStructure() { + protected emitSourceStructure(): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } else { diff --git a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts index 8bd7c0e05..6754e83e2 100644 --- a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts +++ b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts @@ -82,7 +82,7 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { legalizeName, upper ? firstUpperWordStyle : allLowerWordStyle, firstUpperWordStyle, - upper ? s => capitalize(acronyms(s)) : allLowerWordStyle, + upper ? (s): string => capitalize(acronyms(s)) : allLowerWordStyle, acronyms, "", isES3IdentifierStart @@ -187,7 +187,7 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { ); } - protected emitBlock(source: Sourcelike, end: Sourcelike, emit: () => void) { + protected emitBlock(source: Sourcelike, end: Sourcelike, emit: () => void): void { this.emitLine(source, "{"); this.indent(emit); this.emitLine("}", end); @@ -281,7 +281,7 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { }); } - private emitObject(name: Name, t: ObjectType) { + private emitObject(name: Name, t: ObjectType): void { this.ensureBlankLine(); this.emitLine("_", name, " = PropTypes.shape({"); this.indent(() => { diff --git a/packages/quicktype-core/src/language/Kotlin.ts b/packages/quicktype-core/src/language/Kotlin.ts index 01bf4cd9d..9ef6d5937 100644 --- a/packages/quicktype-core/src/language/Kotlin.ts +++ b/packages/quicktype-core/src/language/Kotlin.ts @@ -323,7 +323,7 @@ export class KotlinRenderer extends ConvenienceRenderer { return; } - const kotlinType = (p: ClassProperty) => { + const kotlinType = (p: ClassProperty): Sourcelike => { if (p.isOptional) { return [this.kotlinType(p.type, true, true), "?"]; } else { @@ -371,15 +371,15 @@ export class KotlinRenderer extends ConvenienceRenderer { this.emitClassDefinitionMethods(c, className); } - protected emitClassDefinitionMethods(_c: ClassType, _className: Name) { + protected emitClassDefinitionMethods(_c: ClassType, _className: Name): void { this.emitLine(")"); } - protected emitClassAnnotations(_c: Type, _className: Name) { + protected emitClassAnnotations(_c: Type, _className: Name): void { // to be overridden } - protected renameAttribute(_name: Name, _jsonName: string, _required: boolean, _meta: Array<() => void>) { + protected renameAttribute(_name: Name, _jsonName: string, _required: boolean, _meta: Array<() => void>): void { // to be overridden } @@ -433,7 +433,7 @@ export class KotlinRenderer extends ConvenienceRenderer { _nonNulls: ReadonlySet, _maybeNull: PrimitiveType | null, _unionName: Name - ) { + ): void { // to be overridden } @@ -630,7 +630,7 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { this.emitLine("typealias ", className, " = JsonObject"); } - protected emitClassDefinitionMethods(c: ClassType, className: Name) { + protected emitClassDefinitionMethods(c: ClassType, className: Name): void { const isTopLevel = iterableSome(this.topLevels, ([_, top]) => top === c); if (isTopLevel) { this.emitBlock(")", () => { @@ -645,7 +645,7 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { } } - protected renameAttribute(name: Name, jsonName: string, _required: boolean, meta: Array<() => void>) { + protected renameAttribute(name: Name, jsonName: string, _required: boolean, meta: Array<() => void>): void { const rename = this.klaxonRenameAttribute(name, jsonName); if (rename !== undefined) { meta.push(() => this.emitLine(rename)); @@ -701,7 +701,7 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { nonNulls: ReadonlySet, maybeNull: PrimitiveType | null, unionName: Name - ) { + ): void { this.ensureBlankLine(); this.emitLine("public fun toJson(): String = klaxon.toJsonString(when (this) {"); this.indent(() => { @@ -911,7 +911,7 @@ import com.fasterxml.jackson.module.kotlin.*`); this.emitLine("typealias ", className, " = JsonNode"); } - protected emitClassDefinitionMethods(c: ClassType, className: Name) { + protected emitClassDefinitionMethods(c: ClassType, className: Name): void { const isTopLevel = iterableSome(this.topLevels, ([_, top]) => top === c); if (isTopLevel) { this.emitBlock(")", () => { @@ -926,7 +926,7 @@ import com.fasterxml.jackson.module.kotlin.*`); } } - protected renameAttribute(name: Name, jsonName: string, required: boolean, meta: Array<() => void>) { + protected renameAttribute(name: Name, jsonName: string, required: boolean, meta: Array<() => void>): void { const rename = this.jacksonRenameAttribute(name, jsonName, required); if (rename !== undefined) { meta.push(() => this.emitLine(rename)); @@ -974,7 +974,7 @@ private fun ObjectMapper.convert(k: kotlin.reflect.KClass<*>, fromJson: (Jso nonNulls: ReadonlySet, maybeNull: PrimitiveType | null, unionName: Name - ) { + ): void { this.ensureBlankLine(); this.emitLine("fun toJson(): String = mapper.writeValueAsString(when (this) {"); this.indent(() => { @@ -1086,11 +1086,11 @@ export class KotlinXRenderer extends KotlinRenderer { this.emitLine("import kotlinx.serialization.encoding.*"); } - protected emitClassAnnotations(_c: Type, _className: Name) { + protected emitClassAnnotations(_c: Type, _className: Name): void { this.emitLine("@Serializable"); } - protected renameAttribute(name: Name, jsonName: string, _required: boolean, meta: Array<() => void>) { + protected renameAttribute(name: Name, jsonName: string, _required: boolean, meta: Array<() => void>): void { const rename = this._rename(name, jsonName); if (rename !== undefined) { meta.push(() => this.emitLine(rename)); diff --git a/packages/quicktype-core/src/language/Objective-C.ts b/packages/quicktype-core/src/language/Objective-C.ts index 00d678f30..3b46b914b 100644 --- a/packages/quicktype-core/src/language/Objective-C.ts +++ b/packages/quicktype-core/src/language/Objective-C.ts @@ -308,14 +308,14 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { this.emitLine("}"); } - protected emitMethod(declaration: Sourcelike, f: () => void) { + protected emitMethod(declaration: Sourcelike, f: () => void): void { this.emitLine(declaration); this.emitLine("{"); this.indent(f); this.emitLine("}"); } - protected emitExtraComments(...comments: Sourcelike[]) { + protected emitExtraComments(...comments: Sourcelike[]): void { if (!this._options.extraComments) return; for (const comment of comments) { this.emitLine("// ", comment); @@ -496,7 +496,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { return this.implicitlyConvertsFromJSON(t) && "bool" !== t.kind; } - protected emitPropertyAssignment(propertyName: Name, jsonName: string, propertyType: Type) { + protected emitPropertyAssignment(propertyName: Name, jsonName: string, propertyType: Type): void { const name = ["_", propertyName]; matchType( propertyType, @@ -587,7 +587,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { this.emitLine(this.topLevelToJSONPrototype(name, true), ";"); } - private emitTryCatchAsError(inTry: () => void, inCatch: () => void) { + private emitTryCatchAsError(inTry: () => void, inCatch: () => void): void { this.emitLine("@try {"); this.indent(inTry); this.emitLine("} @catch (NSException *exception) {"); @@ -680,7 +680,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { this.emitLine("@end"); } - protected hasIrregularProperties(t: ClassType) { + protected hasIrregularProperties(t: ClassType): boolean { let irregular = false; this.forEachClassProperty(t, "none", (name, jsonName) => { irregular = irregular || stringEscape(jsonName) !== this.sourcelikeToString(name); @@ -688,7 +688,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { return irregular; } - protected hasUnsafeProperties(t: ClassType) { + protected hasUnsafeProperties(t: ClassType): boolean { let unsafe = false; this.forEachClassProperty(t, "none", (_, __, property) => { unsafe = unsafe || !this.implicitlyConvertsToJSON(property.type); @@ -830,7 +830,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { this.emitLine("@end"); } - protected emitMark(label: string) { + protected emitMark(label: string): void { this.ensureBlankLine(); this.emitLine(`#pragma mark - ${label}`); this.ensureBlankLine(); @@ -846,7 +846,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { return camelCaseName; } - private emitPseudoEnumInterface(enumType: EnumType, enumName: Name) { + private emitPseudoEnumInterface(enumType: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(enumType)); this.emitLine("@interface ", enumName, " : NSObject"); @@ -858,7 +858,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { this.emitLine("@end"); } - private emitPseudoEnumImplementation(enumType: EnumType, enumName: Name) { + private emitPseudoEnumImplementation(enumType: EnumType, enumName: Name): void { this.emitLine("@implementation ", enumName); const instances = [enumName, ".", staticEnumValuesIdentifier]; @@ -1084,7 +1084,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { return iterableSome(this.typeGraph.allTypesUnordered(), needsMap); } - protected emitMapFunction() { + protected emitMapFunction(): void { if (this.needsMap) { this.emitMultiline(`static id map(id collection, id (^f)(id value)) { id result = nil; diff --git a/packages/quicktype-core/src/language/Php.ts b/packages/quicktype-core/src/language/Php.ts index 617f461fe..e448bb1ee 100644 --- a/packages/quicktype-core/src/language/Php.ts +++ b/packages/quicktype-core/src/language/Php.ts @@ -261,7 +261,7 @@ export class PhpRenderer extends ConvenienceRenderer { } protected phpType(_reference: boolean, t: Type, isOptional = false, prefix = "?", suffix = ""): Sourcelike { - function optionalize(s: Sourcelike) { + function optionalize(s: Sourcelike): Sourcelike { return [isOptional ? prefix : "", s, isOptional ? suffix : ""]; } @@ -366,7 +366,7 @@ export class PhpRenderer extends ConvenienceRenderer { ); } - protected phpToObjConvert(className: Name, t: Type, lhs: Sourcelike[], args: Sourcelike[]) { + protected phpToObjConvert(className: Name, t: Type, lhs: Sourcelike[], args: Sourcelike[]): void { matchType( t, _anyType => this.emitLine(...lhs, ...args, "; /*any*/"), @@ -419,7 +419,7 @@ export class PhpRenderer extends ConvenienceRenderer { ); } - private transformDateTime(className: Name, attrName: Sourcelike, scopeAttrName: Sourcelike[]) { + private transformDateTime(className: Name, attrName: Sourcelike, scopeAttrName: Sourcelike[]): void { this.emitBlock(["if (!is_a(", scopeAttrName, ", 'DateTime'))"], () => this.emitLine("throw new Exception('Attribute Error:", className, "::", attrName, "');") ); @@ -428,7 +428,7 @@ export class PhpRenderer extends ConvenienceRenderer { // } } - protected phpFromObjConvert(className: Name, t: Type, lhs: Sourcelike[], args: Sourcelike[]) { + protected phpFromObjConvert(className: Name, t: Type, lhs: Sourcelike[], args: Sourcelike[]): void { matchType( t, _anyType => this.emitLine(...lhs, ...args, "; /*any*/"), @@ -491,7 +491,7 @@ export class PhpRenderer extends ConvenienceRenderer { args: Sourcelike[], idx: number, suffix: Sourcelike - ) { + ): void { matchType( t, _anyType => @@ -586,8 +586,8 @@ export class PhpRenderer extends ConvenienceRenderer { ); } - private phpValidate(className: Name, t: Type, attrName: Sourcelike, scopeAttrName: string) { - const is = (isfn: string, myT: Name = className) => { + private phpValidate(className: Name, t: Type, attrName: Sourcelike, scopeAttrName: string): void { + const is = (isfn: string, myT: Name = className): void => { this.emitBlock(["if (!", isfn, "(", scopeAttrName, "))"], () => this.emitLine('throw new Exception("Attribute Error:', myT, "::", attrName, '");') ); @@ -644,7 +644,13 @@ export class PhpRenderer extends ConvenienceRenderer { ); } - protected emitFromMethod(names: FunctionNames, p: ClassProperty, className: Name, _name: Name, desc?: string[]) { + protected emitFromMethod( + names: FunctionNames, + p: ClassProperty, + className: Name, + _name: Name, + desc?: string[] + ): void { this.emitLine("/**"); if (desc !== undefined) { this.emitLine(" * ", desc); @@ -672,7 +678,7 @@ export class PhpRenderer extends ConvenienceRenderer { ); } - protected emitToMethod(names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc?: string[]) { + protected emitToMethod(names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc?: string[]): void { this.emitLine("/**"); if (desc !== undefined) { this.emitLine(" * ", desc); @@ -690,7 +696,13 @@ export class PhpRenderer extends ConvenienceRenderer { }); } - protected emitValidateMethod(names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc?: string[]) { + protected emitValidateMethod( + names: FunctionNames, + p: ClassProperty, + className: Name, + name: Name, + desc?: string[] + ): void { this.emitLine("/**"); if (desc !== undefined) { this.emitLine(" * ", desc); @@ -710,7 +722,13 @@ export class PhpRenderer extends ConvenienceRenderer { ); } - protected emitGetMethod(names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc?: string[]) { + protected emitGetMethod( + names: FunctionNames, + p: ClassProperty, + className: Name, + name: Name, + desc?: string[] + ): void { if (this._options.withGet) { this.emitLine("/**"); if (desc !== undefined) { @@ -746,7 +764,13 @@ export class PhpRenderer extends ConvenienceRenderer { } } - protected emitSetMethod(names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc?: string[]) { + protected emitSetMethod( + names: FunctionNames, + p: ClassProperty, + className: Name, + name: Name, + desc?: string[] + ): void { if (this._options.withSet) { this.emitLine("/**"); if (desc !== undefined) { @@ -772,7 +796,7 @@ export class PhpRenderer extends ConvenienceRenderer { name: Name, desc: string[] | undefined, idx: number - ) { + ): void { if (this._options.withGet) { this.emitLine("/**"); if (desc !== undefined) { @@ -937,11 +961,11 @@ export class PhpRenderer extends ConvenienceRenderer { throw Error("emitUnionDefinition not implemented"); } - protected emitEnumSerializationAttributes(_e: EnumType) { + protected emitEnumSerializationAttributes(_e: EnumType): void { // Empty } - protected emitEnumDeserializationAttributes(_e: EnumType) { + protected emitEnumDeserializationAttributes(_e: EnumType): void { // Empty } diff --git a/packages/quicktype-core/src/language/Pike.ts b/packages/quicktype-core/src/language/Pike.ts index fd2a8b2b9..ea7f9d3a5 100644 --- a/packages/quicktype-core/src/language/Pike.ts +++ b/packages/quicktype-core/src/language/Pike.ts @@ -6,7 +6,7 @@ import { type MultiWord, type Sourcelike, multiWord, parenIfNeeded, singleWord } import { isLetterOrUnderscoreOrDigit, legalizeCharacters, makeNameStyle, stringEscape } from "../support/Strings"; import { TargetLanguage } from "../TargetLanguage"; import { ArrayType, type ClassType, type EnumType, MapType, PrimitiveType, type Type, type UnionType } from "../Type"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; +import { type FixMeOptionsAnyType } from "../types"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; export const pikeOptions = {}; @@ -256,7 +256,7 @@ export class PikeRenderer extends ConvenienceRenderer { this.emitTable(table); } - private emitInformationComment() { + private emitInformationComment(): void { this.emitCommentLines( [ "This source has been automatically generated by quicktype.", @@ -277,11 +277,11 @@ export class PikeRenderer extends ConvenienceRenderer { ); } - private emitTopLevelTypedef(t: Type, name: Name) { + private emitTopLevelTypedef(t: Type, name: Name): void { this.emitLine("typedef ", this.sourceFor(t).source, " ", name, ";"); } - private emitTopLevelConverter(t: Type, name: Name) { + private emitTopLevelConverter(t: Type, name: Name): void { this.emitBlock([name, " ", name, "_from_JSON(mixed json)"], () => { if (t instanceof PrimitiveType) { this.emitLine(["return json;"]); @@ -302,7 +302,7 @@ export class PikeRenderer extends ConvenienceRenderer { }); } - private emitEncodingFunction(c: ClassType) { + private emitEncodingFunction(c: ClassType): void { this.emitBlock(["string encode_json()"], () => { this.emitMappingBlock(["mapping(string:mixed) json = "], () => { this.forEachClassProperty(c, "none", (name, jsonName) => { @@ -314,7 +314,7 @@ export class PikeRenderer extends ConvenienceRenderer { }); } - private emitDecodingFunction(className: Name, c: ClassType) { + private emitDecodingFunction(className: Name, c: ClassType): void { this.emitBlock([className, " ", className, "_from_JSON(mixed json)"], () => { this.emitLine([className, " retval = ", className, "();"]); this.ensureBlankLine(); diff --git a/packages/quicktype-core/src/language/Python.ts b/packages/quicktype-core/src/language/Python.ts index 37e5106b4..c58dbd852 100644 --- a/packages/quicktype-core/src/language/Python.ts +++ b/packages/quicktype-core/src/language/Python.ts @@ -14,6 +14,7 @@ import { type RenderContext } from "../Renderer"; import { BooleanOption, EnumOption, type Option, type OptionValues, getOptionValues } from "../RendererOptions"; import { type MultiWord, type Sourcelike, modifySource, multiWord, parenIfNeeded, singleWord } from "../Source"; import { + type WordStyle, allLowerWordStyle, allUpperWordStyle, combineWords, @@ -223,7 +224,7 @@ function classNameStyle(original: string): string { ); } -function getWordStyle(uppercase: boolean, forceSnakeNameStyle: boolean) { +function getWordStyle(uppercase: boolean, forceSnakeNameStyle: boolean): WordStyle { if (!forceSnakeNameStyle) { return originalWord; } @@ -1016,7 +1017,7 @@ export class JSONPythonRenderer extends PythonRenderer { } protected transformer(inputTransformer: ValueOrLambda, xfer: Transformer, targetType: Type): ValueOrLambda { - const consume = (consumer: Transformer | undefined, vol: ValueOrLambda) => { + const consume = (consumer: Transformer | undefined, vol: ValueOrLambda): ValueOrLambda => { if (consumer === undefined) { return vol; } diff --git a/packages/quicktype-core/src/language/Rust.ts b/packages/quicktype-core/src/language/Rust.ts index ca36ca6d8..8dcf5b93a 100644 --- a/packages/quicktype-core/src/language/Rust.ts +++ b/packages/quicktype-core/src/language/Rust.ts @@ -360,7 +360,7 @@ export class RustRenderer extends ConvenienceRenderer { jsonName: string, defaultNamingStyle: string, preferedNamingStyle: string - ) { + ): void { const escapedName = rustStringEscape(jsonName); const name = namingStyles[defaultNamingStyle].fromParts(this.sourcelikeToString(propName).split(" ")); const styledName = nameToNamingStyle(name, preferedNamingStyle); @@ -370,7 +370,7 @@ export class RustRenderer extends ConvenienceRenderer { } } - private emitSkipSerializeNone(t: Type) { + private emitSkipSerializeNone(t: Type): void { if (t instanceof UnionType) { const nullable = nullableFromUnion(t); if (nullable !== null) this.emitLine('#[serde(skip_serializing_if = "Option::is_none")]'); @@ -411,7 +411,7 @@ export class RustRenderer extends ConvenienceRenderer { } const blankLines = this._options.density === Density.Dense ? "none" : "interposing"; - const structBody = () => + const structBody = (): void => this.forEachClassProperty(c, blankLines, (name, jsonName, prop) => { this.emitDescription(this.descriptionForClassProperty(c, jsonName)); this.emitRenameAttribute(name, jsonName, defaultStyle, preferedNamingStyle); diff --git a/packages/quicktype-core/src/language/Scala3.ts b/packages/quicktype-core/src/language/Scala3.ts index 69dc3c9fd..cc3ec1b9a 100644 --- a/packages/quicktype-core/src/language/Scala3.ts +++ b/packages/quicktype-core/src/language/Scala3.ts @@ -348,7 +348,7 @@ export class Scala3Renderer extends ConvenienceRenderer { return; } - const scalaType = (p: ClassProperty) => { + const scalaType = (p: ClassProperty): Sourcelike => { if (p.isOptional) { return ["Option[", this.scalaType(p.type, true, true), "]"]; } else { @@ -402,7 +402,7 @@ export class Scala3Renderer extends ConvenienceRenderer { this.emitClassDefinitionMethods(); } - protected emitClassDefinitionMethods() { + protected emitClassDefinitionMethods(): void { this.emitLine(")"); } @@ -489,7 +489,7 @@ export class Scala3Renderer extends ConvenienceRenderer { } export class UpickleRenderer extends Scala3Renderer { - protected emitClassDefinitionMethods() { + protected emitClassDefinitionMethods(): void { this.emitLine(") derives ReadWriter "); } @@ -596,7 +596,7 @@ export class CirceRenderer extends Scala3Renderer { return [wrapOption("Json", optional)]; } - protected emitClassDefinitionMethods() { + protected emitClassDefinitionMethods(): void { this.emitLine(") derives Encoder.AsObject, Decoder"); } diff --git a/packages/quicktype-core/src/language/Smithy4s.ts b/packages/quicktype-core/src/language/Smithy4s.ts index 2abe6f27f..163b33073 100644 --- a/packages/quicktype-core/src/language/Smithy4s.ts +++ b/packages/quicktype-core/src/language/Smithy4s.ts @@ -314,7 +314,7 @@ export class Smithy4sRenderer extends ConvenienceRenderer { return; } - const scalaType = (p: ClassProperty) => { + const scalaType = (p: ClassProperty): Sourcelike => { if (p.isOptional) { return [this.scalaType(p.type, true, true)]; } else { @@ -375,7 +375,7 @@ export class Smithy4sRenderer extends ConvenienceRenderer { this.emitClassDefinitionMethods(emitLater); } - protected emitClassDefinitionMethods(arrayTypes: ClassProperty[]) { + protected emitClassDefinitionMethods(arrayTypes: ClassProperty[]): void { this.emitLine("}"); arrayTypes.forEach(p => { function ignore(_: T): void { diff --git a/packages/quicktype-core/src/language/Swift.ts b/packages/quicktype-core/src/language/Swift.ts index d46f56780..3991d7f7c 100644 --- a/packages/quicktype-core/src/language/Swift.ts +++ b/packages/quicktype-core/src/language/Swift.ts @@ -402,7 +402,7 @@ export class SwiftRenderer extends ConvenienceRenderer { else return notJustTypes; } - private get lowerNamingFunction() { + private get lowerNamingFunction(): Namer { return funPrefixNamer("lower", s => swiftNameStyle("", false, s, acronymStyle(this._options.acronymStyle))); } @@ -601,7 +601,7 @@ export class SwiftRenderer extends ConvenienceRenderer { return protocols.length > 0 ? ": " + protocols.join(", ") : ""; } - private getEnumPropertyGroups(c: ClassType) { + private getEnumPropertyGroups(c: ClassType): typeof groups { type PropertyGroup = Array<{ label?: string; name: Name }>; let groups: PropertyGroup[] = []; @@ -699,7 +699,7 @@ export class SwiftRenderer extends ConvenienceRenderer { let lastProperty: ClassProperty | undefined = undefined; let lastNames: Name[] = []; - const emitLastProperty = () => { + const emitLastProperty = (): void => { if (lastProperty === undefined) return; const useMutableProperties = this._options.mutableProperties; @@ -1400,7 +1400,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); this.endFile(); }; - private emitConvenienceMutator(c: ClassType, className: Name) { + private emitConvenienceMutator(c: ClassType, className: Name): void { this.emitLine("func with("); this.indent(() => { this.forEachClassProperty(c, "none", (name, _, p, position) => { @@ -1431,7 +1431,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); }); } - protected emitMark(line: Sourcelike, horizontalLine = false) { + protected emitMark(line: Sourcelike, horizontalLine = false): void { this.emitLine("// MARK:", horizontalLine ? " - " : " ", line); } @@ -1452,7 +1452,7 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); } } - private emitAlamofireExtension() { + private emitAlamofireExtension(): void { this.ensureBlankLine(); this.emitBlockWithAccess("extension DataRequest", () => { this diff --git a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts index 470a79efb..63b35e5db 100644 --- a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts +++ b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts @@ -76,7 +76,7 @@ export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { legalizeName, upper ? firstUpperWordStyle : allLowerWordStyle, firstUpperWordStyle, - upper ? s => capitalize(acronyms(s)) : allLowerWordStyle, + upper ? (s): string => capitalize(acronyms(s)) : allLowerWordStyle, acronyms, "", isLetterOrUnderscore @@ -153,7 +153,7 @@ export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { return match; } - private emitObject(name: Name, t: ObjectType) { + private emitObject(name: Name, t: ObjectType): void { this.emittedObjects.add(name); this.ensureBlankLine(); this.emitLine("\nexport class ", name, " extends S.Class<", name, '>("', name, '")({'); @@ -181,10 +181,10 @@ export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { } } - protected walkObjectNames(objectType: ObjectType) { + protected walkObjectNames(objectType: ObjectType): Name[] { const names: Name[] = []; - const recurse = (type: Type) => { + const recurse = (type: Type): void => { if (type.kind === "object" || type.kind === "class") { names.push(this.nameForNamedType(type)); this.forEachClassProperty(type as ObjectType, "none", (_, __, prop) => { diff --git a/packages/quicktype-core/src/language/TypeScriptFlow.ts b/packages/quicktype-core/src/language/TypeScriptFlow.ts index a0f6216b3..a6cb60ad8 100644 --- a/packages/quicktype-core/src/language/TypeScriptFlow.ts +++ b/packages/quicktype-core/src/language/TypeScriptFlow.ts @@ -190,12 +190,12 @@ export abstract class TypeScriptFlowBaseRenderer extends JavaScriptRenderer { } } - private emitClass(c: ClassType, className: Name) { + private emitClass(c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); this.emitClassBlock(c, className); } - protected emitUnion(u: UnionType, unionName: Name) { + protected emitUnion(u: UnionType, unionName: Name): void { if (!this._tsFlowOptions.declareUnions) { return; } @@ -383,7 +383,7 @@ export class FlowRenderer extends TypeScriptFlowBaseRenderer { }); } - protected emitSourceStructure() { + protected emitSourceStructure(): void { this.emitLine("// @flow"); this.ensureBlankLine(); super.emitSourceStructure(); diff --git a/packages/quicktype-core/src/language/TypeScriptZod.ts b/packages/quicktype-core/src/language/TypeScriptZod.ts index 69cd77fda..ada7494a9 100644 --- a/packages/quicktype-core/src/language/TypeScriptZod.ts +++ b/packages/quicktype-core/src/language/TypeScriptZod.ts @@ -93,7 +93,7 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { legalizeName, upper ? firstUpperWordStyle : allLowerWordStyle, firstUpperWordStyle, - upper ? s => capitalize(acronyms(s)) : allLowerWordStyle, + upper ? (s): string => capitalize(acronyms(s)) : allLowerWordStyle, acronyms, "", isLetterOrUnderscore @@ -169,7 +169,7 @@ export class TypeScriptZodRenderer extends ConvenienceRenderer { return match; } - protected emitObject(name: Name, t: ObjectType) { + protected emitObject(name: Name, t: ObjectType): void { this.ensureBlankLine(); this.emitLine("\nexport const ", name, "Schema = ", "z.object({"); this.indent(() => { diff --git a/packages/quicktype-core/src/language/ruby/index.ts b/packages/quicktype-core/src/language/ruby/index.ts index feb6e7608..461a33a94 100644 --- a/packages/quicktype-core/src/language/ruby/index.ts +++ b/packages/quicktype-core/src/language/ruby/index.ts @@ -260,7 +260,7 @@ export class RubyRenderer extends ConvenienceRenderer { } private jsonSample(t: Type): Sourcelike { - function inner() { + function inner(): string { if (t instanceof ArrayType) { return "[…]"; } else if (t instanceof MapType) { @@ -401,14 +401,14 @@ export class RubyRenderer extends ConvenienceRenderer { ); } - private emitBlock(source: Sourcelike, emit: () => void) { + private emitBlock(source: Sourcelike, emit: () => void): void { this.emitLine(source); this.indent(emit); this.emitLine("end"); } - private emitModule(emit: () => void) { - const emitModuleInner = (moduleName: string) => { + private emitModule(emit: () => void): void { + const emitModuleInner = (moduleName: string): void => { const [firstModule, ...subModules] = moduleName.split("::"); if (subModules.length > 0) { this.emitBlock(["module ", firstModule], () => { @@ -426,7 +426,7 @@ export class RubyRenderer extends ConvenienceRenderer { } } - private emitClass(c: ClassType, className: Name) { + private emitClass(c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); this.emitBlock(["class ", className, " < Dry::Struct"], () => { let table: Sourcelike[][] = []; @@ -518,7 +518,7 @@ export class RubyRenderer extends ConvenienceRenderer { }); } - private emitEnum(e: EnumType, enumName: Name) { + private emitEnum(e: EnumType, enumName: Name): void { this.emitDescription(this.descriptionForType(e)); this.emitBlock(["module ", enumName], () => { const table: Sourcelike[][] = []; @@ -529,7 +529,7 @@ export class RubyRenderer extends ConvenienceRenderer { }); } - private emitUnion(u: UnionType, unionName: Name) { + private emitUnion(u: UnionType, unionName: Name): void { this.emitDescription(this.descriptionForType(u)); this.emitBlock(["class ", unionName, " < Dry::Struct"], () => { const table: Sourcelike[][] = []; @@ -601,7 +601,7 @@ export class RubyRenderer extends ConvenienceRenderer { }); } - private emitTypesModule() { + private emitTypesModule(): void { this.emitBlock(["module Types"], () => { this.emitLine("include Dry.Types(default: :nominal)"); @@ -649,7 +649,7 @@ export class RubyRenderer extends ConvenienceRenderer { }); } - protected emitSourceStructure() { + protected emitSourceStructure(): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } else if (!this._options.justTypes) { @@ -704,7 +704,7 @@ export class RubyRenderer extends ConvenienceRenderer { // it for arrays. const needsToJsonDefined = "array" === topLevel.kind; - const classDeclaration = () => { + const classDeclaration = (): void => { this.emitBlock(["class ", name], () => { this.emitBlock(["def self.from_json!(json)"], () => { if (needsToJsonDefined) { diff --git a/packages/quicktype-core/src/support/Acronyms.ts b/packages/quicktype-core/src/support/Acronyms.ts index 8c3eabcf1..d24c85e97 100644 --- a/packages/quicktype-core/src/support/Acronyms.ts +++ b/packages/quicktype-core/src/support/Acronyms.ts @@ -1108,7 +1108,7 @@ export enum AcronymStyleOptions { Pascal = "pascal" } -export const acronymOption = function (defaultOption: AcronymStyleOptions) { +export const acronymOption = function (defaultOption: AcronymStyleOptions): EnumOption { return new EnumOption( "acronym-style", "Acronym naming style", diff --git a/packages/quicktype-core/src/support/Converters.ts b/packages/quicktype-core/src/support/Converters.ts index 1e9a46250..caec348bf 100644 --- a/packages/quicktype-core/src/support/Converters.ts +++ b/packages/quicktype-core/src/support/Converters.ts @@ -5,7 +5,7 @@ export enum ConvertersOptions { TopLevel = "top-level" } -export function convertersOption() { +export function convertersOption(): EnumOption { return new EnumOption( "converters", "Which converters to generate (top-level by default)", diff --git a/src/index.ts b/src/index.ts index 5006b0bde..7efee1f87 100644 --- a/src/index.ts +++ b/src/index.ts @@ -201,7 +201,7 @@ async function samplesFromDirectory(dataDir: string, httpHeaders?: string[]): Pr } // FIXME: rewrite this to be clearer - const oneUnlessEmpty = (xs: TypeSource[]) => Math.sign(xs.length); + const oneUnlessEmpty = (xs: TypeSource[]): 0 | 1 => Math.sign(xs.length) as 0 | 1; if (oneUnlessEmpty(schemaSources) + oneUnlessEmpty(graphQLSources) > 1) { return messageError("DriverCannotMixNonJSONInputs", { dir: dir }); } @@ -629,7 +629,7 @@ function parseOptions(definitions: OptionDefinition[], argv: string[], partial: return options; } -function usage(targetLanguages: TargetLanguage[]) { +function usage(targetLanguages: TargetLanguage[]): void { const rendererSections: UsageSection[] = []; for (const language of targetLanguages) { @@ -978,7 +978,7 @@ export function writeOutput( } } -export async function main(args: string[] | Partial) { +export async function main(args: string[] | Partial): Promise { let cliOptions: CLIOptions; if (Array.isArray(args)) { cliOptions = parseCLIOptions(args); From e5edac4b8d278906aa5fc2e6d8aaf17c7a037aaa Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Fri, 12 Apr 2024 21:20:23 -0700 Subject: [PATCH 41/94] fix types errors --- .../quicktype-core/src/input/Inference.ts | 5 +- packages/quicktype-core/src/language/CJSON.ts | 47 ++++++++++++++++++- packages/quicktype-core/src/language/Swift.ts | 2 +- .../quicktype-core/src/support/Support.ts | 3 +- src/index.ts | 6 ++- 5 files changed, 57 insertions(+), 6 deletions(-) diff --git a/packages/quicktype-core/src/input/Inference.ts b/packages/quicktype-core/src/input/Inference.ts index a8dc6a772..85c544c7b 100644 --- a/packages/quicktype-core/src/input/Inference.ts +++ b/packages/quicktype-core/src/input/Inference.ts @@ -20,8 +20,9 @@ import { type CompressedJSON, Tag, type Value, valueTag } from "./CompressedJSON // This should be the recursive type // Value[] | NestedValueArray[] // but TypeScript doesn't support that. -// FIXME -export type NestedValueArray = Value[]; +// FIXME: reactor this +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type NestedValueArray = any; function forEachArrayInNestedValueArray(va: NestedValueArray, f: (va: Value[]) => void): void { if (va.length === 0) { diff --git a/packages/quicktype-core/src/language/CJSON.ts b/packages/quicktype-core/src/language/CJSON.ts index 3cfe6b976..28499a4b4 100644 --- a/packages/quicktype-core/src/language/CJSON.ts +++ b/packages/quicktype-core/src/language/CJSON.ts @@ -498,7 +498,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param fieldType: the variable type * @param fieldName: name of the variable */ - protected emitTypedefAlias(fieldType: Type, fieldName: Name) { + protected emitTypedefAlias(fieldType: Type, fieldName: Name): void { if (this._options.addTypedefAlias) { this.emitLine("typedef ", this.quicktypeTypeToCJSON(fieldType, false).cType, " ", fieldName, ";"); this.ensureBlankLine(); @@ -922,6 +922,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ); } else { this.emitLine( + // @ts-expect-error awaiting refactor cJSON.items?.cType, " * tmp", level > 0 ? level.toString() : "", @@ -936,6 +937,7 @@ export class CJSONRenderer extends ConvenienceRenderer { "* tmp", level > 0 ? level.toString() : "", " = ", + // @ts-expect-error awaiting refactor cJSON.items?.getValue, "(e", child_level.toString(), @@ -947,6 +949,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ", tmp", level > 0 ? level.toString() : "", ", sizeof(", + // @ts-expect-error awaiting refactor cJSON.items?.cType, " *));" ); @@ -1057,6 +1060,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ); } else { this.emitLine( + // @ts-expect-error awaiting refactor cJSON.items?.cType, " * tmp", level > 0 ? level.toString() : "", @@ -1071,6 +1075,7 @@ export class CJSONRenderer extends ConvenienceRenderer { "* tmp", level > 0 ? level.toString() : "", " = ", + // @ts-expect-error awaiting refactor cJSON.items?.getValue, "(e", child_level.toString(), @@ -1084,6 +1089,7 @@ export class CJSONRenderer extends ConvenienceRenderer { "->string, tmp", level > 0 ? level.toString() : "", ", sizeof(", + // @ts-expect-error awaiting refactor cJSON.items?.cType, " *));" ); @@ -1185,6 +1191,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ); this.emitBlock(["if (NULL != j", child_level.toString(), ")"], () => { this.emitLine( + // @ts-expect-error awaiting refactor cJSON.items?.cType, " * x", child_level.toString(), @@ -1229,6 +1236,7 @@ export class CJSONRenderer extends ConvenienceRenderer { "cJSON_AddItemToArray(j", child_level.toString(), ", ", + // @ts-expect-error awaiting refactor cJSON.items?.createObject, "(*x", child_level.toString(), @@ -1305,6 +1313,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ], () => { this.emitLine( + // @ts-expect-error awaiting refactor cJSON.items?.cType, " *x", child_level.toString(), @@ -1367,6 +1376,7 @@ export class CJSONRenderer extends ConvenienceRenderer { "[index", child_level.toString(), "], ", + // @ts-expect-error awaiting refactor cJSON.items?.createObject, "(*x", child_level.toString(), @@ -1450,6 +1460,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ], () => { this.emitLine( + // @ts-expect-error awaiting refactor cJSON.items?.cType, " * x", child_level.toString(), @@ -1475,6 +1486,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ["if ((void *)0xDEADBEEF != x", child_level.toString(), ")"], () => { this.emitLine( + // @ts-expect-error awaiting refactor cJSON.items?.deleteType, "(x", child_level.toString(), @@ -1484,6 +1496,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ); } else { this.emitLine( + // @ts-expect-error awaiting refactor cJSON.items?.deleteType, "(x", child_level.toString(), @@ -1551,6 +1564,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ], () => { this.emitLine( + // @ts-expect-error awaiting refactor cJSON.items?.cType, " *x", child_level.toString(), @@ -1584,6 +1598,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ], () => { this.emitLine( + // @ts-expect-error awaiting refactor cJSON.items?.deleteType, "(x", child_level.toString(), @@ -1593,6 +1608,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ); } else { this.emitLine( + // @ts-expect-error awaiting refactor cJSON.items?.deleteType, "(x", child_level.toString(), @@ -1766,6 +1782,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ", x", child_level2.toString(), ", sizeof(", + // @ts-expect-error awaiting refactor cJSON.items?.cType, " *));" ); @@ -1965,6 +1982,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ); } else { this.emitLine( + // @ts-expect-error awaiting refactor cJSON.items?.cType, " * tmp", level > 0 ? level.toString() : "", @@ -1983,6 +2001,7 @@ export class CJSONRenderer extends ConvenienceRenderer { "* tmp", level > 0 ? level.toString() : "", " = ", + // @ts-expect-error awaiting refactor cJSON.items?.getValue, "(e", child_level.toString(), @@ -1994,6 +2013,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ", tmp", level > 0 ? level.toString() : "", ", sizeof(", + // @ts-expect-error awaiting refactor cJSON.items?.cType, " *));" ); @@ -2139,6 +2159,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ); } else { this.emitLine( + // @ts-expect-error awaiting refactor cJSON.items?.cType, " * tmp", level > 0 ? level.toString() : "", @@ -2157,6 +2178,7 @@ export class CJSONRenderer extends ConvenienceRenderer { "* tmp", level > 0 ? level.toString() : "", " = ", + // @ts-expect-error awaiting refactor cJSON.items?.getValue, "(e", child_level.toString(), @@ -2170,6 +2192,7 @@ export class CJSONRenderer extends ConvenienceRenderer { "->string, tmp", level > 0 ? level.toString() : "", ", sizeof(", + // @ts-expect-error awaiting refactor cJSON.items?.cType, " *));" ); @@ -2478,6 +2501,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ); this.emitBlock(["if (NULL != j", child_level.toString(), ")"], () => { this.emitLine( + // @ts-expect-error awaiting refactor cJSON.items?.cType, " * x", child_level.toString(), @@ -2540,6 +2564,7 @@ export class CJSONRenderer extends ConvenienceRenderer { "cJSON_AddItemToArray(j", child_level.toString(), ", ", + // @ts-expect-error awaiting refactor cJSON.items?.createObject, "(*x", child_level.toString(), @@ -2626,6 +2651,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ], () => { this.emitLine( + // @ts-expect-error awaiting refactor cJSON.items?.cType, " *x", child_level.toString(), @@ -2715,6 +2741,7 @@ export class CJSONRenderer extends ConvenienceRenderer { "[index", child_level.toString(), "], ", + // @ts-expect-error awaiting refactor cJSON.items?.createObject, "(*x", child_level.toString(), @@ -3015,6 +3042,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ["if (NULL != x", level > 0 ? level.toString() : "", "->", name, ")"], () => { this.emitLine( + // @ts-expect-error awaiting refactor cJSON.items?.cType, " * x", child_level.toString(), @@ -3050,6 +3078,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ["if ((void *)0xDEADBEEF != x", child_level.toString(), ")"], () => { this.emitLine( + // @ts-expect-error awaiting refactor cJSON.items?.deleteType, "(x", child_level.toString(), @@ -3059,6 +3088,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ); } else { this.emitLine( + // @ts-expect-error awaiting refactor cJSON.items?.deleteType, "(x", child_level.toString(), @@ -3119,6 +3149,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ], () => { this.emitLine( + // @ts-expect-error awaiting refactor cJSON.items?.cType, " *x", child_level.toString(), @@ -3164,6 +3195,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ], () => { this.emitLine( + // @ts-expect-error awaiting refactor cJSON.items?.deleteType, "(x", child_level.toString(), @@ -3173,6 +3205,7 @@ export class CJSONRenderer extends ConvenienceRenderer { ); } else { this.emitLine( + // @ts-expect-error awaiting refactor cJSON.items?.deleteType, "(x", child_level.toString(), @@ -3376,6 +3409,7 @@ export class CJSONRenderer extends ConvenienceRenderer { } else { this.emitLine( "list_add_tail(x->value, ", + // @ts-expect-error awaiting refactor cJSON.items?.getValue, "(e), sizeof(", cJSON.items?.cType, @@ -3430,6 +3464,7 @@ export class CJSONRenderer extends ConvenienceRenderer { } else { this.emitLine( "hashtable_add(x->value, e->string, ", + // @ts-expect-error awaiting refactor cJSON.items?.getValue, "(e), sizeof(", cJSON.items?.cType, @@ -3479,6 +3514,7 @@ export class CJSONRenderer extends ConvenienceRenderer { this.emitBlock(["if (NULL != x->value)"], () => { this.emitLine("j = ", cJSON.createObject, "();"); this.emitBlock(["if (NULL != j)"], () => { + // @ts-expect-error awaiting refactor this.emitLine(cJSON.items?.cType, " * x1 = list_get_head(x->value);"); this.emitBlock(["while (NULL != x1)"], () => { const add = (cJSON: TypeCJSON) => { @@ -3507,6 +3543,7 @@ export class CJSONRenderer extends ConvenienceRenderer { } else { this.emitLine( "cJSON_AddItemToArray(j, ", + // @ts-expect-error awaiting refactor cJSON.items?.createObject, "(*x1));" ); @@ -3537,6 +3574,7 @@ export class CJSONRenderer extends ConvenienceRenderer { this.emitBlock(["if (NULL != keys)"], () => { this.emitBlock(["for (size_t index = 0; index < count; index++)"], () => { this.emitLine( + // @ts-expect-error awaiting refactor cJSON.items?.cType, " *x2 = hashtable_lookup(x->value, keys[index]);" ); @@ -3569,6 +3607,7 @@ export class CJSONRenderer extends ConvenienceRenderer { this.emitLine( cJSON.addToObject, "(j, keys[index], ", + // @ts-expect-error awaiting refactor cJSON.items?.createObject, "(*x2));" ); @@ -3626,13 +3665,16 @@ export class CJSONRenderer extends ConvenienceRenderer { const cJSON = this.quicktypeTypeToCJSON(type, false); if (cJSON.cjsonType === "cJSON_Array" && cJSON.items !== undefined) { this.emitBlock(["if (NULL != x->value)"], () => { + // @ts-expect-error awaiting refactor this.emitLine(cJSON.items?.cType, " * x1 = list_get_head(x->value);"); this.emitBlock(["while (NULL != x1)"], () => { if (cJSON.items?.isNullable) { this.emitBlock(["if ((void *)0xDEADBEEF != x1)"], () => { + // @ts-expect-error awaiting refactor this.emitLine(cJSON.items?.deleteType, "(x1);"); }); } else { + // @ts-expect-error awaiting refactor this.emitLine(cJSON.items?.deleteType, "(x1);"); } @@ -3646,13 +3688,16 @@ export class CJSONRenderer extends ConvenienceRenderer { this.emitLine("size_t count = hashtable_get_keys(x->value, &keys);"); this.emitBlock(["if (NULL != keys)"], () => { this.emitBlock(["for (size_t index = 0; index < count; index++)"], () => { + // @ts-expect-error awaiting refactor this.emitLine(cJSON.items?.cType, " *x2 = hashtable_lookup(x->value, keys[index]);"); this.emitBlock(["if (NULL != x2)"], () => { if (cJSON.items?.isNullable) { this.emitBlock(["if ((", cJSON.items?.cType, " *)0xDEADBEEF != x2)"], () => { + // @ts-expect-error awaiting refactor this.emitLine(cJSON.items?.deleteType, "(x2);"); }); } else { + // @ts-expect-error awaiting refactor this.emitLine(cJSON.items?.deleteType, "(x2);"); } }); diff --git a/packages/quicktype-core/src/language/Swift.ts b/packages/quicktype-core/src/language/Swift.ts index 3991d7f7c..661d6655f 100644 --- a/packages/quicktype-core/src/language/Swift.ts +++ b/packages/quicktype-core/src/language/Swift.ts @@ -730,7 +730,7 @@ export class SwiftRenderer extends ConvenienceRenderer { this.forEachClassProperty(c, "none", (name, jsonName, p) => { const description = this.descriptionForClassProperty(c, jsonName); if ( - !p.equals(lastProperty) || + (lastProperty && !p.equals(lastProperty)) || lastNames.length >= MAX_SAMELINE_PROPERTIES || description !== undefined ) { diff --git a/packages/quicktype-core/src/support/Support.ts b/packages/quicktype-core/src/support/Support.ts index 3778ed3ed..3715a7108 100644 --- a/packages/quicktype-core/src/support/Support.ts +++ b/packages/quicktype-core/src/support/Support.ts @@ -2,6 +2,7 @@ import { Base64 } from "js-base64"; import * as pako from "pako"; import * as YAML from "yaml"; +import { type JSONSchema } from "../input/JSONSchemaStore"; import { messageError } from "../Messages"; export interface StringMap { @@ -123,7 +124,7 @@ export function inflateBase64(encoded: string): string { return pako.inflate(bytes, { to: "string" }); } -export function parseJSON(text: string, description: string, address = ""): unknown { +export function parseJSON(text: string, description: string, address = ""): JSONSchema | undefined { try { // https://gist.github.com/pbakondy/f5045eff725193dad9c7 if (text.charCodeAt(0) === 0xfeff) { diff --git a/src/index.ts b/src/index.ts index 7efee1f87..fe252a087 100644 --- a/src/index.ts +++ b/src/index.ts @@ -752,7 +752,11 @@ async function makeInputData( } function stringSourceDataToStreamSourceData(src: JSONSourceData): JSONSourceData { - return { name: src.name, description: src.description, samples: src.samples.map(stringToStream) }; + return { + name: src.name, + description: src.description, + samples: src.samples.map(sample => stringToStream(sample) as Readable) + }; } export async function makeQuicktypeOptions( From 130fe313500d16a045a193b46832f6b281dff46f Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 13 Apr 2024 08:34:03 -0700 Subject: [PATCH 42/94] fix json import for test tsconfig --- test/tsconfig.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/tsconfig.json b/test/tsconfig.json index 26618760c..a042b47f7 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -4,7 +4,8 @@ "strict": true, "alwaysStrict": true, "noUnusedLocals": true, - "noUnusedParameters": true + "noUnusedParameters": true, + "resolveJsonModule": true }, "include": ["*.ts", "../dist/*.js", "../dist/*.d.ts"] } From 06002f9ed70250878e146030d5040d7ce9e96650 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sun, 14 Apr 2024 07:56:48 -0700 Subject: [PATCH 43/94] auto lint fix --- packages/quicktype-core/src/language/Swift.ts | 1 + .../quicktype-typescript-input/src/index.ts | 4 +- packages/quicktype-vscode/src/extension.ts | 82 +++++++++++-------- 3 files changed, 53 insertions(+), 34 deletions(-) diff --git a/packages/quicktype-core/src/language/Swift.ts b/packages/quicktype-core/src/language/Swift.ts index 56e4f89d4..e16ba1cb2 100644 --- a/packages/quicktype-core/src/language/Swift.ts +++ b/packages/quicktype-core/src/language/Swift.ts @@ -773,6 +773,7 @@ export class SwiftRenderer extends ConvenienceRenderer { enumDeclaration += ", "; enumDeclaration += this._options.codingKeysProtocol; } + this.emitBlock(enumDeclaration, () => { for (const group of groups) { const { name, label } = group[0]; diff --git a/packages/quicktype-typescript-input/src/index.ts b/packages/quicktype-typescript-input/src/index.ts index b8ebc7f89..3289e914b 100644 --- a/packages/quicktype-typescript-input/src/index.ts +++ b/packages/quicktype-typescript-input/src/index.ts @@ -34,13 +34,13 @@ export function schemaForTypeScriptSources(sourceFileNames: string[]): JSONSchem const schema = generateSchema(program, "*", settings); const uris: string[] = []; - let topLevelName: string = ""; + let topLevelName = ""; // if there is a type that is `export default`, swap the corresponding ref if (schema?.definitions?.default) { const defaultDefinition = schema?.definitions?.default; const matchingDefaultName = Object.entries(schema?.definitions ?? {}).find( - ([_name, definition]) => (definition as Record)["$ref"] === "#/definitions/default" + ([_name, definition]) => (definition as Record).$ref === "#/definitions/default" )?.[0]; if (matchingDefaultName) { diff --git a/packages/quicktype-vscode/src/extension.ts b/packages/quicktype-vscode/src/extension.ts index 3c62a47d2..f6c202748 100644 --- a/packages/quicktype-vscode/src/extension.ts +++ b/packages/quicktype-vscode/src/extension.ts @@ -2,22 +2,24 @@ import * as path from "path"; -import * as vscode from "vscode"; -import { Range } from "vscode"; import { - quicktype, - languageNamed, - SerializedRenderResult, - defaultTargetLanguages, - JSONSchemaInput, InputData, - TargetLanguage, + JSONSchemaInput, + defaultTargetLanguages, + inferenceFlagNames, jsonInputForTargetLanguage, - RendererOptions, - Options, - inferenceFlagNames + languageNamed, + quicktype } from "quicktype-core"; +import { + type Options, + type RendererOptions, + type SerializedRenderResult, + type TargetLanguage} from "quicktype-core"; import { schemaForTypeScriptSources } from "quicktype-typescript-input"; +import * as vscode from "vscode"; +import { Range } from "vscode"; + const configurationSection = "quicktype"; @@ -39,6 +41,7 @@ function jsonIsValid(json: string) { } catch (e) { return false; } + return true; } @@ -53,10 +56,10 @@ async function promptTopLevelName(): Promise<{ cancelled: boolean; name: string }; } -type TargetLanguagePick = { +interface TargetLanguagePick { cancelled: boolean; lang: TargetLanguage; -}; +} async function pickTargetLanguage(): Promise { const languageChoices = defaultTargetLanguages.map(l => l.displayName).sort(); @@ -65,6 +68,7 @@ async function pickTargetLanguage(): Promise { if (chosenName === undefined) { chosenName = "typescript"; } + return { cancelled, lang: languageNamed(chosenName)! }; } @@ -77,6 +81,7 @@ async function getTargetLanguage(editor: vscode.TextEditor): Promise(); + private readonly _changeSubscription: vscode.Disposable; + private readonly _onDidChangeVisibleTextEditors: vscode.Disposable; + private readonly _onDidChangeConfiguration: vscode.Disposable; private _isOpen = false; + private _timer: NodeJS.Timeout | undefined = undefined; constructor( @@ -279,6 +291,7 @@ class CodeProvider implements vscode.TextDocumentContentProvider { if (!this._isOpen && isOpen) { this.update(); } + this._isOpen = isOpen; } @@ -296,6 +309,7 @@ class CodeProvider implements vscode.TextDocumentContentProvider { if (this._timer) { clearTimeout(this._timer); } + this._timer = setTimeout(() => { this._timer = undefined; this.update(); @@ -338,14 +352,17 @@ function deduceTargetLanguage(): TargetLanguage { if (count === undefined) { count = 0; } + count += 1; counts.set(name, count); } + const sorted = Array.from(counts).sort(([_na, ca], [_nb, cb]) => cb - ca); for (const [name] of sorted) { const lang = languageNamed(name); if (lang !== undefined) return lang; } + return languageNamed("typescript")!; } @@ -382,12 +399,13 @@ async function openQuicktype( const doc = lastCodeProvider.document; originalEditor = vscode.window.visibleTextEditors.find(e => e.document === doc); } + if (originalEditor === undefined) { originalEditor = vscode.window.activeTextEditor; } let column: number; - if (originalEditor !== undefined && originalEditor.viewColumn !== undefined) { + if (originalEditor?.viewColumn !== undefined) { column = originalEditor.viewColumn + 1; } else { column = 0; @@ -422,29 +440,29 @@ export async function activate(context: vscode.ExtensionContext): Promise extensionContext = context; context.subscriptions.push( - vscode.commands.registerTextEditorCommand(Command.PasteJSONAsTypes, editor => - pasteAsTypes(editor, "json", true) + vscode.commands.registerTextEditorCommand(Command.PasteJSONAsTypes, async editor => + await pasteAsTypes(editor, "json", true) ), - vscode.commands.registerTextEditorCommand(Command.PasteJSONAsTypesAndSerialization, editor => - pasteAsTypes(editor, "json", false) + vscode.commands.registerTextEditorCommand(Command.PasteJSONAsTypesAndSerialization, async editor => + await pasteAsTypes(editor, "json", false) ), - vscode.commands.registerTextEditorCommand(Command.PasteSchemaAsTypes, editor => - pasteAsTypes(editor, "schema", true) + vscode.commands.registerTextEditorCommand(Command.PasteSchemaAsTypes, async editor => + await pasteAsTypes(editor, "schema", true) ), - vscode.commands.registerTextEditorCommand(Command.PasteSchemaAsTypesAndSerialization, editor => - pasteAsTypes(editor, "schema", false) + vscode.commands.registerTextEditorCommand(Command.PasteSchemaAsTypesAndSerialization, async editor => + await pasteAsTypes(editor, "schema", false) ), - vscode.commands.registerTextEditorCommand(Command.PasteTypeScriptAsTypesAndSerialization, editor => - pasteAsTypes(editor, "typescript", false) + vscode.commands.registerTextEditorCommand(Command.PasteTypeScriptAsTypesAndSerialization, async editor => + await pasteAsTypes(editor, "typescript", false) ), - vscode.commands.registerTextEditorCommand(Command.OpenQuicktypeForJSON, editor => - openForEditor(editor, "json") + vscode.commands.registerTextEditorCommand(Command.OpenQuicktypeForJSON, async editor => + await openForEditor(editor, "json") ), - vscode.commands.registerTextEditorCommand(Command.OpenQuicktypeForJSONSchema, editor => - openForEditor(editor, "schema") + vscode.commands.registerTextEditorCommand(Command.OpenQuicktypeForJSONSchema, async editor => + await openForEditor(editor, "schema") ), - vscode.commands.registerTextEditorCommand(Command.OpenQuicktypeForTypeScript, editor => - openForEditor(editor, "typescript") + vscode.commands.registerTextEditorCommand(Command.OpenQuicktypeForTypeScript, async editor => + await openForEditor(editor, "typescript") ), vscode.commands.registerCommand(Command.ChangeTargetLanguage, changeTargetLanguage) ); From 93ab86e0923bfde02c4f362d3d06e842f9f834be Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sun, 14 Apr 2024 08:04:54 -0700 Subject: [PATCH 44/94] fix lint errors in extension --- packages/quicktype-vscode/src/extension.ts | 133 +++++++++++---------- 1 file changed, 73 insertions(+), 60 deletions(-) diff --git a/packages/quicktype-vscode/src/extension.ts b/packages/quicktype-vscode/src/extension.ts index f6c202748..3e8083721 100644 --- a/packages/quicktype-vscode/src/extension.ts +++ b/packages/quicktype-vscode/src/extension.ts @@ -5,21 +5,19 @@ import * as path from "path"; import { InputData, JSONSchemaInput, + type Options, + type RendererOptions, + type SerializedRenderResult, + type TargetLanguage, defaultTargetLanguages, inferenceFlagNames, jsonInputForTargetLanguage, languageNamed, quicktype } from "quicktype-core"; -import { - type Options, - type RendererOptions, - type SerializedRenderResult, - type TargetLanguage} from "quicktype-core"; import { schemaForTypeScriptSources } from "quicktype-typescript-input"; +// eslint-disable-next-line import/no-unresolved import * as vscode from "vscode"; -import { Range } from "vscode"; - const configurationSection = "quicktype"; @@ -35,7 +33,7 @@ enum Command { ChangeTargetLanguage = "quicktype.changeTargetLanguage" } -function jsonIsValid(json: string) { +function jsonIsValid(json: string): boolean { try { JSON.parse(json); } catch (e) { @@ -52,6 +50,7 @@ async function promptTopLevelName(): Promise<{ cancelled: boolean; name: string return { cancelled: topLevelName === undefined, + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing name: topLevelName || "TopLevel" }; } @@ -69,7 +68,8 @@ async function pickTargetLanguage(): Promise { chosenName = "typescript"; } - return { cancelled, lang: languageNamed(chosenName)! }; + // @ts-expect-error languageNamed is not strongly typed yet + return { cancelled, lang: languageNamed(chosenName) }; } async function getTargetLanguage(editor: vscode.TextEditor): Promise { @@ -154,7 +154,7 @@ async function runQuicktype( return await quicktype(options); } -async function pasteAsTypes(editor: vscode.TextEditor, kind: InputKind, justTypes: boolean) { +async function pasteAsTypes(editor: vscode.TextEditor, kind: InputKind, justTypes: boolean): Promise { let indentation: string; if (editor.options.insertSpaces) { const tabSize = editor.options.tabSize as number; @@ -172,13 +172,11 @@ async function pasteAsTypes(editor: vscode.TextEditor, kind: InputKind, justType try { content = await vscode.env.clipboard.readText(); } catch (e) { - vscode.window.showErrorMessage("Could not get clipboard contents"); - return; + return await vscode.window.showErrorMessage("Could not get clipboard contents"); } if (kind !== "typescript" && !jsonIsValid(content)) { - vscode.window.showErrorMessage("Clipboard does not contain valid JSON."); - return; + return await vscode.window.showErrorMessage("Clipboard does not contain valid JSON."); } let topLevelName: string; @@ -196,28 +194,30 @@ async function pasteAsTypes(editor: vscode.TextEditor, kind: InputKind, justType let result: SerializedRenderResult; try { result = await runQuicktype(content, kind, language.lang, topLevelName, justTypes, indentation); - } catch (e: any) { + } catch (e) { // TODO Invalid JSON produces an uncatchable exception from quicktype // Fix this so we can catch and show an error message. - vscode.window.showErrorMessage(e); - return; + if (typeof e === "string") { + return await vscode.window.showErrorMessage(e); + } } + // @ts-expect-error FIXME: resolve this after above ^ const text = result.lines.join("\n"); const selection = editor.selection; - editor.edit(builder => { + return await editor.edit(builder => { if (selection.isEmpty) { builder.insert(selection.start, text); } else { - builder.replace(new Range(selection.start, selection.end), text); + builder.replace(new vscode.Range(selection.start, selection.end), text); } }); } class CodeProvider implements vscode.TextDocumentContentProvider { - readonly scheme: string = "quicktype"; + public readonly scheme: string = "quicktype"; - readonly uri: vscode.Uri; + public readonly uri: vscode.Uri; private _documentText: string = "{}"; @@ -235,7 +235,7 @@ class CodeProvider implements vscode.TextDocumentContentProvider { private _timer: NodeJS.Timeout | undefined = undefined; - constructor( + public constructor( private _inputKind: InputKind, private readonly _targetLanguage: TargetLanguage, private _document: vscode.TextDocument @@ -253,43 +253,43 @@ class CodeProvider implements vscode.TextDocumentContentProvider { ); } - dispose(): void { + public dispose(): void { this._onDidChange.dispose(); this._changeSubscription.dispose(); this._onDidChangeVisibleTextEditors.dispose(); this._onDidChangeConfiguration.dispose(); } - get inputKind(): InputKind { + public get inputKind(): InputKind { return this._inputKind; } - setInputKind(inputKind: InputKind): void { + public setInputKind(inputKind: InputKind): void { this._inputKind = inputKind; } - get document(): vscode.TextDocument { + public get document(): vscode.TextDocument { return this._document; } - get documentName(): string { + public get documentName(): string { const basename = path.basename(this.document.fileName); const extIndex = basename.lastIndexOf("."); return extIndex === -1 ? basename : basename.substring(0, extIndex); } - setDocument(document: vscode.TextDocument): void { + public setDocument(document: vscode.TextDocument): void { this._document = document; } - get onDidChange(): vscode.Event { + public get onDidChange(): vscode.Event { return this._onDidChange.event; } - private visibleTextEditorsDidChange(editors: vscode.TextEditor[]) { + private visibleTextEditorsDidChange(editors: vscode.TextEditor[]): void { const isOpen = editors.some(e => e.document.uri.scheme === this.scheme); if (!this._isOpen && isOpen) { - this.update(); + void this.update(); } this._isOpen = isOpen; @@ -297,7 +297,7 @@ class CodeProvider implements vscode.TextDocumentContentProvider { private configurationDidChange(ev: vscode.ConfigurationChangeEvent): void { if (ev.affectsConfiguration(configurationSection)) { - this.update(); + void this.update(); } } @@ -312,11 +312,11 @@ class CodeProvider implements vscode.TextDocumentContentProvider { this._timer = setTimeout(() => { this._timer = undefined; - this.update(); + void this.update(); }, 300); } - async update(): Promise { + public async update(): Promise { this._documentText = this._document.getText(); try { @@ -333,10 +333,15 @@ class CodeProvider implements vscode.TextDocumentContentProvider { if (!this._isOpen) return; this._onDidChange.fire(this.uri); - } catch (e) {} + } catch (e) { + // FIXME + } } - provideTextDocumentContent(_uri: vscode.Uri, _token: vscode.CancellationToken): vscode.ProviderResult { + public provideTextDocumentContent( + _uri: vscode.Uri, + _token: vscode.CancellationToken + ): vscode.ProviderResult { this._isOpen = true; return this._targetCode; @@ -363,7 +368,8 @@ function deduceTargetLanguage(): TargetLanguage { if (lang !== undefined) return lang; } - return languageNamed("typescript")!; + // @ts-expect-error languageNamed is not yet strongly typed + return languageNamed("typescript"); } const lastTargetLanguageUsedKey = "lastTargetLanguageUsed"; @@ -379,7 +385,7 @@ async function openQuicktype( inputKind: InputKind, targetLanguage: TargetLanguage, document: vscode.TextDocument -): Promise { +): Promise { let codeProvider = codeProviders.get(targetLanguage.name); if (codeProvider === undefined) { codeProvider = new CodeProvider(inputKind, targetLanguage, document); @@ -396,8 +402,8 @@ async function openQuicktype( let originalEditor: vscode.TextEditor | undefined; if (lastCodeProvider !== undefined) { - const doc = lastCodeProvider.document; - originalEditor = vscode.window.visibleTextEditors.find(e => e.document === doc); + const lastDoc = lastCodeProvider.document; + originalEditor = vscode.window.visibleTextEditors.find(e => e.document === lastDoc); } if (originalEditor === undefined) { @@ -413,14 +419,13 @@ async function openQuicktype( lastCodeProvider = codeProvider; - codeProvider.update(); + await codeProvider.update(); const doc = await vscode.workspace.openTextDocument(codeProvider.uri); - vscode.window.showTextDocument(doc, column, true); + return await vscode.window.showTextDocument(doc, column, true); } async function openForEditor(editor: vscode.TextEditor, inputKind: InputKind): Promise { - const targetLanguage = - explicitlySetTargetLanguage !== undefined ? explicitlySetTargetLanguage : deduceTargetLanguage(); + const targetLanguage = explicitlySetTargetLanguage ?? deduceTargetLanguage(); await openQuicktype(inputKind, targetLanguage, editor.document); } @@ -440,29 +445,37 @@ export async function activate(context: vscode.ExtensionContext): Promise extensionContext = context; context.subscriptions.push( - vscode.commands.registerTextEditorCommand(Command.PasteJSONAsTypes, async editor => - await pasteAsTypes(editor, "json", true) + vscode.commands.registerTextEditorCommand( + Command.PasteJSONAsTypes, + async editor => await pasteAsTypes(editor, "json", true) ), - vscode.commands.registerTextEditorCommand(Command.PasteJSONAsTypesAndSerialization, async editor => - await pasteAsTypes(editor, "json", false) + vscode.commands.registerTextEditorCommand( + Command.PasteJSONAsTypesAndSerialization, + async editor => await pasteAsTypes(editor, "json", false) ), - vscode.commands.registerTextEditorCommand(Command.PasteSchemaAsTypes, async editor => - await pasteAsTypes(editor, "schema", true) + vscode.commands.registerTextEditorCommand( + Command.PasteSchemaAsTypes, + async editor => await pasteAsTypes(editor, "schema", true) ), - vscode.commands.registerTextEditorCommand(Command.PasteSchemaAsTypesAndSerialization, async editor => - await pasteAsTypes(editor, "schema", false) + vscode.commands.registerTextEditorCommand( + Command.PasteSchemaAsTypesAndSerialization, + async editor => await pasteAsTypes(editor, "schema", false) ), - vscode.commands.registerTextEditorCommand(Command.PasteTypeScriptAsTypesAndSerialization, async editor => - await pasteAsTypes(editor, "typescript", false) + vscode.commands.registerTextEditorCommand( + Command.PasteTypeScriptAsTypesAndSerialization, + async editor => await pasteAsTypes(editor, "typescript", false) ), - vscode.commands.registerTextEditorCommand(Command.OpenQuicktypeForJSON, async editor => - await openForEditor(editor, "json") + vscode.commands.registerTextEditorCommand( + Command.OpenQuicktypeForJSON, + async editor => await openForEditor(editor, "json") ), - vscode.commands.registerTextEditorCommand(Command.OpenQuicktypeForJSONSchema, async editor => - await openForEditor(editor, "schema") + vscode.commands.registerTextEditorCommand( + Command.OpenQuicktypeForJSONSchema, + async editor => await openForEditor(editor, "schema") ), - vscode.commands.registerTextEditorCommand(Command.OpenQuicktypeForTypeScript, async editor => - await openForEditor(editor, "typescript") + vscode.commands.registerTextEditorCommand( + Command.OpenQuicktypeForTypeScript, + async editor => await openForEditor(editor, "typescript") ), vscode.commands.registerCommand(Command.ChangeTargetLanguage, changeTargetLanguage) ); From 1ec5933c783db7f7e57286bb2a1bac41bf231c73 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sun, 14 Apr 2024 08:25:03 -0700 Subject: [PATCH 45/94] fix lint errors in Elixir --- .../quicktype-core/src/language/Elixir.ts | 83 +++++++++++-------- 1 file changed, 50 insertions(+), 33 deletions(-) diff --git a/packages/quicktype-core/src/language/Elixir.ts b/packages/quicktype-core/src/language/Elixir.ts index ddbbcdaa7..f864e2a93 100644 --- a/packages/quicktype-core/src/language/Elixir.ts +++ b/packages/quicktype-core/src/language/Elixir.ts @@ -1,27 +1,27 @@ import unicode from "unicode-properties"; -import { Sourcelike } from "../Source"; -import { Namer, Name } from "../Naming"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { TargetLanguage } from "../TargetLanguage"; -import { Option, BooleanOption, OptionValues, getOptionValues, StringOption } from "../RendererOptions"; -import { Type, EnumType, ClassType, UnionType, ArrayType, MapType, PrimitiveType } from "../Type"; -import { matchType, nullableFromUnion } from "../TypeUtils"; - +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; +import { type Name, Namer } from "../Naming"; +import { type RenderContext } from "../Renderer"; +import { BooleanOption, type Option, type OptionValues, StringOption, getOptionValues } from "../RendererOptions"; +import { type Sourcelike } from "../Source"; import { - legalizeCharacters, - splitIntoWords, - combineWords, - firstUpperWordStyle, - allUpperWordStyle, allLowerWordStyle, - utf32ConcatMap, - isPrintable, + allUpperWordStyle, + combineWords, escapeNonPrintableMapper, + firstUpperWordStyle, intToHex, - isLetterOrUnderscore + isLetterOrUnderscore, + isPrintable, + legalizeCharacters, + splitIntoWords, + utf32ConcatMap } from "../support/Strings"; -import { RenderContext } from "../Renderer"; +import { TargetLanguage } from "../TargetLanguage"; +import { ArrayType, ClassType, EnumType, MapType, PrimitiveType, type Type, UnionType } from "../Type"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; +import { matchType, nullableFromUnion } from "../TypeUtils"; const forbiddenModuleNames = [ "Access", @@ -128,17 +128,17 @@ function unicodeEscape(codePoint: number): string { return `\\u{${intToHex(codePoint, 0)}}`; } -function capitalizeFirstLetter(str: string) { +function capitalizeFirstLetter(str: string): string { return str.charAt(0).toUpperCase() + str.slice(1); } const stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, unicodeEscape)); -function escapeDoubleQuotes(str: string) { +function escapeDoubleQuotes(str: string): string { return str.replace(/"/g, '\\"'); } -function escapeNewLines(str: string) { +function escapeNewLines(str: string): string { return str.replace(/\n/g, "\\n"); } @@ -148,15 +148,15 @@ export const elixirOptions = { }; export class ElixirTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super("Elixir", ["elixir"], "ex"); } - protected getOptions(): Option[] { + protected getOptions(): Array> { return [elixirOptions.justTypes, elixirOptions.namespace]; } - get supportsOptionalClassProperties(): boolean { + public get supportsOptionalClassProperties(): boolean { return true; } @@ -164,7 +164,7 @@ export class ElixirTargetLanguage extends TargetLanguage { return " "; } - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): ElixirRenderer { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): ElixirRenderer { return new ElixirRenderer(this, renderContext, getOptionValues(elixirOptions, untypedOptionValues)); } } @@ -173,7 +173,7 @@ const isStartCharacter = isLetterOrUnderscore; function isPartCharacter(utf16Unit: number): boolean { const category: string = unicode.getCategory(utf16Unit); - return ["Nd", "Pc", "Mn", "Mc"].indexOf(category) >= 0 || isStartCharacter(utf16Unit); + return ["Nd", "Pc", "Mn", "Mc"].includes(category) || isStartCharacter(utf16Unit); } const legalizeName = legalizeCharacters(isPartCharacter); @@ -182,6 +182,7 @@ function simpleNameStyle(original: string, uppercase: boolean): string { if (/^[0-9]+$/.test(original)) { original = `${original}N`; } + const words = splitIntoWords(original); return combineWords( words, @@ -210,7 +211,7 @@ function memberNameStyle(original: string): string { } export class ElixirRenderer extends ConvenienceRenderer { - constructor( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues @@ -285,7 +286,7 @@ export class ElixirRenderer extends ConvenienceRenderer { mapType => ["%{String.t() => ", this.elixirType(mapType.values), "}", optional], enumType => [this.nameForNamedTypeWithNamespace(enumType), ".t()", optional], unionType => { - const children = [...unionType.getChildren()].map(t => this.elixirType(t)); + const children = [...unionType.getChildren()].map(ut => this.elixirType(ut)); return [ children.flatMap((element, index) => (index === children.length - 1 ? element : [element, " | "])), optional @@ -422,7 +423,13 @@ export class ElixirRenderer extends ConvenienceRenderer { }); } - private emitPatternMatches(types: Type[], name: Sourcelike, parentName: Sourcelike, suffix = "", optional = false) { + private emitPatternMatches( + types: Type[], + name: Sourcelike, + parentName: Sourcelike, + suffix = "", + optional = false + ): void { this.ensureBlankLine(); let typesToMatch = this.sortAndFilterPatternMatchTypes(types); @@ -482,6 +489,7 @@ export class ElixirRenderer extends ConvenienceRenderer { if (encode) { mode = "encode"; } + return matchType( t, _anyType => [], @@ -574,6 +582,7 @@ export class ElixirRenderer extends ConvenienceRenderer { "(value)} end)" ]; } + return [primitive]; } }, @@ -604,8 +613,10 @@ export class ElixirRenderer extends ConvenienceRenderer { if (nullableTypes.length < 2) { return this.fromDynamic(nullable, jsonName, name, true); } + return ['m["', jsonName, '"] && decode_', name, '(m["', jsonName, '"])']; } + return ["decode_", name, '(m["', jsonName, '"])']; } ); @@ -626,6 +637,7 @@ export class ElixirRenderer extends ConvenienceRenderer { if (arrayElement instanceof ArrayType) { return expression; } + if (arrayElement.isPrimitive()) { return expression; } else if (arrayElement instanceof MapType) { @@ -689,6 +701,7 @@ export class ElixirRenderer extends ConvenienceRenderer { "(value)} end)" ]; } + return [expression]; } }, @@ -721,12 +734,13 @@ export class ElixirRenderer extends ConvenienceRenderer { return ["struct.", e, " && encode_", e, "(struct.", e, ")"]; } + return ["encode_", e, "(struct.", e, ")"]; } ); } - private emitBlock(source: Sourcelike, emit: () => void) { + private emitBlock(source: Sourcelike, emit: () => void): void { this.emitLine(source); this.indent(emit); this.emitLine("end"); @@ -740,7 +754,7 @@ export class ElixirRenderer extends ConvenienceRenderer { }); } - private emitModule(c: ClassType, moduleName: Name) { + private emitModule(c: ClassType, moduleName: Name): void { this.emitBlock(["defmodule ", this.nameWithNamespace(moduleName), " do"], () => { const structDescription = this.descriptionForType(c) ?? []; const attributeDescriptions: Sourcelike[][] = []; @@ -754,6 +768,7 @@ export class ElixirRenderer extends ConvenienceRenderer { this.emitDescription([...structDescription, ...attributeDescriptions]); this.ensureBlankLine(); } + const requiredAttributes: Sourcelike[] = []; this.forEachClassProperty(c, "none", (name, _jsonName, p) => { if (!p.isOptional) { @@ -767,6 +782,7 @@ export class ElixirRenderer extends ConvenienceRenderer { if (requiredAttributes.length) { this.emitLine(["@enforce_keys [", requiredAttributes, "]"]); } + const attributeNames: Sourcelike[] = []; this.forEachClassProperty(c, "none", (name, _jsonName, _p) => { if (attributeNames.length === 0) { @@ -794,6 +810,7 @@ export class ElixirRenderer extends ConvenienceRenderer { if (this._options.justTypes) { return; } + this.forEachClassProperty(c, "none", (name, _jsonName, p) => { if (p.type.kind === "union") { const unionTypes = [...p.type.getChildren()]; @@ -925,7 +942,7 @@ export class ElixirRenderer extends ConvenienceRenderer { return true; } - private emitEnum(e: EnumType, enumName: Name) { + private emitEnum(e: EnumType, enumName: Name): void { this.emitBlock(["defmodule ", this.nameWithNamespace(enumName), " do"], () => { this.emitDescription(this.descriptionForType(e)); this.emitLine("@valid_enum_members ["); @@ -984,11 +1001,11 @@ end`); }); } - private emitUnion(_u: UnionType, _unionName: Name) { + private emitUnion(_u: UnionType, _unionName: Name): void { return; } - protected emitSourceStructure() { + protected emitSourceStructure(): void { if (this.leadingComments !== undefined) { this.emitComments(this.leadingComments); } else if (!this._options.justTypes) { From 4620ba55663f423307f9820198e45eb776ca16e4 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sun, 14 Apr 2024 09:16:05 -0700 Subject: [PATCH 46/94] make ref.pushElement public --- packages/quicktype-core/src/input/JSONSchemaInput.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/quicktype-core/src/input/JSONSchemaInput.ts b/packages/quicktype-core/src/input/JSONSchemaInput.ts index a88e78157..ccd68d231 100644 --- a/packages/quicktype-core/src/input/JSONSchemaInput.ts +++ b/packages/quicktype-core/src/input/JSONSchemaInput.ts @@ -201,7 +201,7 @@ export class Ref { return this.path.length === 1 && this.path[0].kind === PathElementKind.Root; } - private pushElement(pe: PathElement): Ref { + public pushElement(pe: PathElement): Ref { const newPath = Array.from(this.path); newPath.push(pe); return new Ref(this.addressURI, newPath); From 4fe1649b5022aa23530b767fefeda9697beb85aa Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sun, 14 Apr 2024 09:42:16 -0700 Subject: [PATCH 47/94] fix misc --- packages/quicktype-core/src/Naming.ts | 6 ++++-- packages/quicktype-core/src/input/Inputs.ts | 2 +- packages/quicktype-core/src/input/JSONSchemaInput.ts | 5 +++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/quicktype-core/src/Naming.ts b/packages/quicktype-core/src/Naming.ts index 94c6ca452..6b2b2b825 100644 --- a/packages/quicktype-core/src/Naming.ts +++ b/packages/quicktype-core/src/Naming.ts @@ -403,7 +403,9 @@ export function assignNames(rootNamespaces: Iterable): ReadonlyMap ctx.areForbiddensFullyNamed(ns)); - const readyNamespace = iterableFind(unfinishedNamespaces, ns => iterableSome(ns.members, ctx.isReadyToBeNamed)); + const readyNamespace = iterableFind(unfinishedNamespaces, ns => + iterableSome(ns.members, member => ctx.isReadyToBeNamed(member)) + ); if (readyNamespace === undefined) { // FIXME: Check for cycles? @@ -418,7 +420,7 @@ export function assignNames(rootNamespaces: Iterable): ReadonlyMap ctx.isReadyToBeNamed(member)); const minOrderName = iterableMinBy(allReadyNames, n => n.order); if (minOrderName === undefined) break; const minOrder = minOrderName.order; diff --git a/packages/quicktype-core/src/input/Inputs.ts b/packages/quicktype-core/src/input/Inputs.ts index be10e48d2..96d78756a 100644 --- a/packages/quicktype-core/src/input/Inputs.ts +++ b/packages/quicktype-core/src/input/Inputs.ts @@ -169,7 +169,7 @@ export class InputData { // eslint-disable-next-line @typescript-eslint/no-explicit-any private _inputs: Set> = new Set(); - protected addInput(input: Input): void { + public addInput(input: Input): void { this._inputs = this._inputs.add(input); } diff --git a/packages/quicktype-core/src/input/JSONSchemaInput.ts b/packages/quicktype-core/src/input/JSONSchemaInput.ts index ccd68d231..e000f7f40 100644 --- a/packages/quicktype-core/src/input/JSONSchemaInput.ts +++ b/packages/quicktype-core/src/input/JSONSchemaInput.ts @@ -201,14 +201,15 @@ export class Ref { return this.path.length === 1 && this.path[0].kind === PathElementKind.Root; } - public pushElement(pe: PathElement): Ref { + private pushElement(pe: PathElement): Ref { const newPath = Array.from(this.path); newPath.push(pe); return new Ref(this.addressURI, newPath); } public push(...keys: string[]): Ref { - let ref: Ref = { ...this }; + // eslint-disable-next-line @typescript-eslint/no-this-alias + let ref: Ref = this; for (const key of keys) { ref = ref.pushElement({ kind: PathElementKind.KeyOrIndex, key }); } From eed53c66164bd32724f614c7db64516d5b19877c Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sun, 14 Apr 2024 09:52:09 -0700 Subject: [PATCH 48/94] fix accidental public in CSharp raw text get --- packages/quicktype-core/src/language/CSharp.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/quicktype-core/src/language/CSharp.ts b/packages/quicktype-core/src/language/CSharp.ts index 159dab900..331345d66 100644 --- a/packages/quicktype-core/src/language/CSharp.ts +++ b/packages/quicktype-core/src/language/CSharp.ts @@ -2433,19 +2433,19 @@ internal class IsoDateTimeOffsetConverter : JsonConverter public DateTimeStyles DateTimeStyles { -public get => _dateTimeStyles; + get => _dateTimeStyles; set => _dateTimeStyles = value; } public string? DateTimeFormat { -public get => _dateTimeFormat ?? string.Empty; + get => _dateTimeFormat ?? string.Empty; set => _dateTimeFormat = (string.IsNullOrEmpty(value)) ? null : value; } public CultureInfo Culture { -public get => _culture ?? CultureInfo.CurrentCulture; + get => _culture ?? CultureInfo.CurrentCulture; set => _culture = value; } From 15fd4521d68c77ab53fc1ecbdf307c328c7a0f21 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Tue, 16 Apr 2024 08:17:42 -0700 Subject: [PATCH 49/94] use full generics for all languages to all extensibility --- packages/quicktype-core/src/language/CJSON.ts | 14 ++++++-- .../quicktype-core/src/language/CPlusPlus.ts | 14 ++++++-- .../quicktype-core/src/language/CSharp.ts | 14 ++++++-- .../quicktype-core/src/language/Crystal.ts | 14 ++++++-- packages/quicktype-core/src/language/Dart.ts | 18 ++++++++--- packages/quicktype-core/src/language/Elm.ts | 14 ++++++-- .../quicktype-core/src/language/Golang.ts | 14 ++++++-- .../quicktype-core/src/language/Haskell.ts | 14 ++++++-- .../quicktype-core/src/language/JSONSchema.ts | 14 ++++++-- packages/quicktype-core/src/language/Java.ts | 14 ++++++-- .../src/language/JavaScriptPropTypes.ts | 18 +++++++---- .../quicktype-core/src/language/Kotlin.ts | 14 ++++++-- .../src/language/Objective-C.ts | 18 +++++++---- packages/quicktype-core/src/language/Php.ts | 14 ++++++-- packages/quicktype-core/src/language/Pike.ts | 14 ++++++-- .../quicktype-core/src/language/Python.ts | 14 ++++++-- packages/quicktype-core/src/language/Rust.ts | 14 ++++++-- .../quicktype-core/src/language/Scala3.ts | 22 +++++++++---- .../quicktype-core/src/language/Smithy4s.ts | 22 +++++++++---- packages/quicktype-core/src/language/Swift.ts | 14 ++++++-- .../src/language/TypeScriptEffectSchema.ts | 18 +++++++---- .../src/language/TypeScriptFlow.ts | 32 +++++++++++++------ .../src/language/TypeScriptZod.ts | 14 ++++++-- .../quicktype-core/src/language/ruby/index.ts | 14 ++++++-- 24 files changed, 285 insertions(+), 101 deletions(-) diff --git a/packages/quicktype-core/src/language/CJSON.ts b/packages/quicktype-core/src/language/CJSON.ts index 53cf67fdb..19c322ca1 100644 --- a/packages/quicktype-core/src/language/CJSON.ts +++ b/packages/quicktype-core/src/language/CJSON.ts @@ -128,9 +128,17 @@ export const cJSONOptions = { }; /* cJSON generator target language */ -export class CJSONTargetLanguage extends TargetLanguage<"C (cJSON)", ["cjson", "cJSON"], "h"> { - constructor() { - super("C (cJSON)", ["cjson", "cJSON"], "h"); +export class CJSONTargetLanguage< + const DisplayName extends string = "C (cJSON)", + const Names extends readonly string[] = readonly ["cjson", "cJSON"], + const Extension extends string = "h" +> extends TargetLanguage { + constructor( + displayName = "C (cJSON)" as DisplayName, + names = ["cjson", "cJSON"] as unknown as Names, + extension = "h" as Extension + ) { + super(displayName, names, extension); } /** diff --git a/packages/quicktype-core/src/language/CPlusPlus.ts b/packages/quicktype-core/src/language/CPlusPlus.ts index c6b68b93b..029d85806 100644 --- a/packages/quicktype-core/src/language/CPlusPlus.ts +++ b/packages/quicktype-core/src/language/CPlusPlus.ts @@ -118,9 +118,17 @@ export const cPlusPlusOptions = { hideNullOptional: new BooleanOption("hide-null-optional", "Hide null value for optional field", false) }; -export class CPlusPlusTargetLanguage extends TargetLanguage<"C++", ["c++", "cpp", "cplusplus"], "cpp"> { - constructor() { - super("C++", ["c++", "cpp", "cplusplus"], "cpp"); +export class CPlusPlusTargetLanguage< + const DisplayName extends string = "C++", + const Names extends readonly string[] = readonly ["c++", "cpp", "cplusplus"], + const Extension extends string = "cpp" +> extends TargetLanguage { + constructor( + displayName = "C++" as DisplayName, + names = ["c++", "cpp", "cplusplus"] as unknown as Names, + extension = "cpp" as Extension + ) { + super(displayName, names, extension); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/CSharp.ts b/packages/quicktype-core/src/language/CSharp.ts index c0272e4b0..f81b22885 100644 --- a/packages/quicktype-core/src/language/CSharp.ts +++ b/packages/quicktype-core/src/language/CSharp.ts @@ -194,9 +194,17 @@ export const cSharpOptions = { keepPropertyName: new BooleanOption("keep-property-name", "Keep original field name generate", false) }; -export class CSharpTargetLanguage extends TargetLanguage<"C#", ["cs", "csharp"], "cs"> { - constructor() { - super("C#", ["cs", "csharp"], "cs"); +export class CSharpTargetLanguage< + const DisplayName extends string = "C#", + const Names extends readonly string[] = readonly ["cs", "csharp"], + const Extension extends string = "cs" +> extends TargetLanguage { + constructor( + displayName = "C#" as DisplayName, + names = ["cs", "csharp"] as unknown as Names, + extension = "cs" as Extension + ) { + super(displayName, names, extension); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/Crystal.ts b/packages/quicktype-core/src/language/Crystal.ts index a6d0e5ef1..52d1c6089 100644 --- a/packages/quicktype-core/src/language/Crystal.ts +++ b/packages/quicktype-core/src/language/Crystal.ts @@ -22,9 +22,17 @@ import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; import { Option } from "../RendererOptions"; import { RenderContext } from "../Renderer"; -export class CrystalTargetLanguage extends TargetLanguage<"Crystal", ["crystal", "cr", "crystallang"], "cr"> { - constructor() { - super("Crystal", ["crystal", "cr", "crystallang"], "cr"); +export class CrystalTargetLanguage< + const DisplayName extends string = "Crystal", + const Names extends readonly string[] = readonly ["crystal", "cr", "crystallang"], + const Extension extends string = "cr" +> extends TargetLanguage { + constructor( + displayName = "Crystal" as DisplayName, + names = ["crystal", "cr", "crystallang"] as unknown as Names, + extension = "cr" as Extension + ) { + super(displayName, names, extension); } protected makeRenderer(renderContext: RenderContext): CrystalRenderer { diff --git a/packages/quicktype-core/src/language/Dart.ts b/packages/quicktype-core/src/language/Dart.ts index 9fbd5807f..3e9fd687f 100644 --- a/packages/quicktype-core/src/language/Dart.ts +++ b/packages/quicktype-core/src/language/Dart.ts @@ -61,9 +61,17 @@ export const dartOptions = { partName: new StringOption("part-name", "Use this name in `part` directive", "NAME", "", "secondary") }; -export class DartTargetLanguage extends TargetLanguage<"Dart", ["dart"], "dart"> { - constructor() { - super("Dart", ["dart"], "dart"); +export class DartTargetLanguage< + const DisplayName extends string = "Dart", + const Names extends readonly string[] = readonly ["dart"], + const Extension extends string = "dart" +> extends TargetLanguage { + constructor( + displayName = "Dart" as DisplayName, + names = ["dart"] as unknown as Names, + extension = "dart" as Extension + ) { + super(displayName, names, extension); } protected getOptions(): Option[] { @@ -200,8 +208,8 @@ function dartNameStyle(startWithUpper: boolean, upperUnderscore: boolean, origin const firstWordStyle = upperUnderscore ? allUpperWordStyle : startWithUpper - ? firstUpperWordStyle - : allLowerWordStyle; + ? firstUpperWordStyle + : allLowerWordStyle; const restWordStyle = upperUnderscore ? allUpperWordStyle : firstUpperWordStyle; return combineWords( words, diff --git a/packages/quicktype-core/src/language/Elm.ts b/packages/quicktype-core/src/language/Elm.ts index 0a7c77f9d..cba6216ec 100644 --- a/packages/quicktype-core/src/language/Elm.ts +++ b/packages/quicktype-core/src/language/Elm.ts @@ -34,9 +34,17 @@ export const elmOptions = { moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType") }; -export class ElmTargetLanguage extends TargetLanguage<"Elm", ["elm"], "elm"> { - constructor() { - super("Elm", ["elm"], "elm"); +export class ElmTargetLanguage< + const DisplayName extends string = "Elm", + const Names extends readonly string[] = readonly ["elm"], + const Extension extends string = "elm" +> extends TargetLanguage { + constructor( + displayName = "Elm" as DisplayName, + names = ["elm"] as unknown as Names, + extension = "elm" as Extension + ) { + super(displayName, names, extension); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/Golang.ts b/packages/quicktype-core/src/language/Golang.ts index b0f375de9..b3fbc9a48 100644 --- a/packages/quicktype-core/src/language/Golang.ts +++ b/packages/quicktype-core/src/language/Golang.ts @@ -34,9 +34,17 @@ export const goOptions = { ) }; -export class GoTargetLanguage extends TargetLanguage<"Go", ["go", "golang"], "go"> { - constructor() { - super("Go", ["go", "golang"], "go"); +export class GoTargetLanguage< + const DisplayName extends string = "Go", + const Names extends readonly string[] = readonly ["go", "golang"], + const Extension extends string = "go" +> extends TargetLanguage { + constructor( + displayName = "Go" as DisplayName, + names = ["go", "golang"] as unknown as Names, + extension = "go" as Extension + ) { + super(displayName, names, extension); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/Haskell.ts b/packages/quicktype-core/src/language/Haskell.ts index 5856f32cb..2980e4e2e 100644 --- a/packages/quicktype-core/src/language/Haskell.ts +++ b/packages/quicktype-core/src/language/Haskell.ts @@ -29,9 +29,17 @@ export const haskellOptions = { moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType") }; -export class HaskellTargetLanguage extends TargetLanguage<"Haskell", ["haskell"], "haskell"> { - constructor() { - super("Haskell", ["haskell"], "haskell"); +export class HaskellTargetLanguage< + const DisplayName extends string = "Haskell", + const Names extends readonly string[] = readonly ["haskell"], + const Extension extends string = "haskell" +> extends TargetLanguage { + constructor( + displayName = "Haskell" as DisplayName, + names = ["haskell"] as unknown as Names, + extension = "haskell" as Extension + ) { + super(displayName, names, extension); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/JSONSchema.ts b/packages/quicktype-core/src/language/JSONSchema.ts index 7249b212f..a82135f3c 100644 --- a/packages/quicktype-core/src/language/JSONSchema.ts +++ b/packages/quicktype-core/src/language/JSONSchema.ts @@ -18,9 +18,17 @@ import { addDescriptionToSchema } from "../attributes/Description"; import { Option } from "../RendererOptions"; import { RenderContext } from "../Renderer"; -export class JSONSchemaTargetLanguage extends TargetLanguage<"JSON Schema", ["schema", "json-schema"], "schema"> { - constructor() { - super("JSON Schema", ["schema", "json-schema"], "schema"); +export class JSONSchemaTargetLanguage< + const DisplayName extends string = "JSON Schema", + const Names extends readonly string[] = readonly ["schema", "json-schema"], + const Extension extends string = "schema" +> extends TargetLanguage { + constructor( + displayName = "JSON Schema" as DisplayName, + names = ["schema", "json-schema"] as unknown as Names, + extension = "schema" as Extension + ) { + super(displayName, names, extension); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/Java.ts b/packages/quicktype-core/src/language/Java.ts index 64b3c6c2f..d1b91671e 100644 --- a/packages/quicktype-core/src/language/Java.ts +++ b/packages/quicktype-core/src/language/Java.ts @@ -53,9 +53,17 @@ export const javaOptions = { lombokCopyAnnotations: new BooleanOption("lombok-copy-annotations", "Copy accessor annotations", true, "secondary") }; -export class JavaTargetLanguage extends TargetLanguage<"Java", ["java"], "java"> { - constructor() { - super("Java", ["java"], "java"); +export class JavaTargetLanguage< + const DisplayName extends string = "Java", + const Names extends readonly string[] = readonly ["java"], + const Extension extends string = "java" +> extends TargetLanguage { + constructor( + displayName = "Java" as DisplayName, + names = ["java"] as unknown as Names, + extension = "java" as Extension + ) { + super(displayName, names, extension); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts index 4e8369db2..78b92049c 100644 --- a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts +++ b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts @@ -39,13 +39,17 @@ export const javaScriptPropTypesOptions = { ) }; -export class JavaScriptPropTypesTargetLanguage extends TargetLanguage< - "JavaScript PropTypes", - ["javascript-prop-types"], - "js" -> { - constructor() { - super("JavaScript PropTypes", ["javascript-prop-types"], "js"); +export class JavaScriptPropTypesTargetLanguage< + const DisplayName extends string = "JavaScript PropTypes", + const Names extends readonly string[] = readonly ["javascript-prop-types"], + const Extension extends string = "js" +> extends TargetLanguage { + constructor( + displayName = "JavaScript PropTypes" as DisplayName, + names = ["javascript-prop-types"] as unknown as Names, + extension = "js" as Extension + ) { + super(displayName, names, extension); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/Kotlin.ts b/packages/quicktype-core/src/language/Kotlin.ts index e3e09469d..b5a7cc8f0 100644 --- a/packages/quicktype-core/src/language/Kotlin.ts +++ b/packages/quicktype-core/src/language/Kotlin.ts @@ -61,9 +61,17 @@ export const kotlinOptions = { packageName: new StringOption("package", "Package", "PACKAGE", "quicktype") }; -export class KotlinTargetLanguage extends TargetLanguage<"Kotlin", ["kotlin"], "kt"> { - constructor() { - super("Kotlin", ["kotlin"], "kt"); +export class KotlinTargetLanguage< + const DisplayName extends string = "Kotlin", + const Names extends readonly string[] = readonly ["kotlin"], + const Extension extends string = "kt" +> extends TargetLanguage { + constructor( + displayName = "Kotlin" as DisplayName, + names = ["kotlin"] as unknown as Names, + extension = "kt" as Extension + ) { + super(displayName, names, extension); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/Objective-C.ts b/packages/quicktype-core/src/language/Objective-C.ts index 91f368a4b..8a8aefeac 100644 --- a/packages/quicktype-core/src/language/Objective-C.ts +++ b/packages/quicktype-core/src/language/Objective-C.ts @@ -43,13 +43,17 @@ export const objcOptions = { extraComments: new BooleanOption("extra-comments", "Extra comments", false) }; -export class ObjectiveCTargetLanguage extends TargetLanguage< - "Objective-C", - ["objc", "objective-c", "objectivec"], - "m" -> { - constructor() { - super("Objective-C", ["objc", "objective-c", "objectivec"], "m"); +export class ObjectiveCTargetLanguage< + const DisplayName extends string = "Objective-C", + const Names extends readonly string[] = readonly ["objc", "objective-c", "objectivec"], + const Extension extends string = "m" +> extends TargetLanguage { + constructor( + displayName = "Objective-C" as DisplayName, + names = ["objc", "objective-c", "objectivec"] as unknown as Names, + extension = "m" as Extension + ) { + super(displayName, names, extension); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/Php.ts b/packages/quicktype-core/src/language/Php.ts index 4933d86d0..e7ecf7b28 100644 --- a/packages/quicktype-core/src/language/Php.ts +++ b/packages/quicktype-core/src/language/Php.ts @@ -34,9 +34,17 @@ export const phpOptions = { acronymStyle: acronymOption(AcronymStyleOptions.Pascal) }; -export class PhpTargetLanguage extends TargetLanguage<"PHP", ["php"], "php"> { - constructor() { - super("PHP", ["php"], "php"); +export class PhpTargetLanguage< + const DisplayName extends string = "PHP", + const Names extends readonly string[] = readonly ["php"], + const Extension extends string = "php" +> extends TargetLanguage { + constructor( + displayName = "PHP" as DisplayName, + names = ["php"] as unknown as Names, + extension = "php" as Extension + ) { + super(displayName, names, extension); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/Pike.ts b/packages/quicktype-core/src/language/Pike.ts index 2e87f5d5a..2ac61e105 100644 --- a/packages/quicktype-core/src/language/Pike.ts +++ b/packages/quicktype-core/src/language/Pike.ts @@ -70,9 +70,17 @@ const enumNamingFunction = funPrefixNamer("enumNamer", makeNameStyle("upper-unde const namingFunction = funPrefixNamer("genericNamer", makeNameStyle("underscore", legalizeName)); const namedTypeNamingFunction = funPrefixNamer("typeNamer", makeNameStyle("pascal", legalizeName)); -export class PikeTargetLanguage extends TargetLanguage<"Pike", ["pike", "pikelang"], "pmod"> { - constructor() { - super("Pike", ["pike", "pikelang"], "pmod"); +export class PikeTargetLanguage< + const DisplayName extends string = "Pike", + const Names extends readonly string[] = readonly ["pike", "pikelang"], + const Extension extends string = "pmod" +> extends TargetLanguage { + constructor( + displayName = "Pike" as DisplayName, + names = ["pike", "pikelang"] as unknown as Names, + extension = "pmod" as Extension + ) { + super(displayName, names, extension); } protected getOptions(): Option[] { return []; diff --git a/packages/quicktype-core/src/language/Python.ts b/packages/quicktype-core/src/language/Python.ts index 1c89a0960..8808f3922 100644 --- a/packages/quicktype-core/src/language/Python.ts +++ b/packages/quicktype-core/src/language/Python.ts @@ -129,9 +129,17 @@ export const pythonOptions = { nicePropertyNames: new BooleanOption("nice-property-names", "Transform property names to be Pythonic", true) }; -export class PythonTargetLanguage extends TargetLanguage<"Python", ["python", "py"], "py"> { - constructor() { - super("Python", ["python", "py"], "py"); +export class PythonTargetLanguage< + const DisplayName extends string = "Python", + const Names extends readonly string[] = readonly ["python", "py"], + const Extension extends string = "py" +> extends TargetLanguage { + constructor( + displayName = "Python" as DisplayName, + names = ["python", "py"] as unknown as Names, + extension = "py" as Extension + ) { + super(displayName, names, extension); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/Rust.ts b/packages/quicktype-core/src/language/Rust.ts index 82feb3032..cf79a1bba 100644 --- a/packages/quicktype-core/src/language/Rust.ts +++ b/packages/quicktype-core/src/language/Rust.ts @@ -111,9 +111,17 @@ const namingStyles: Record = { } }; -export class RustTargetLanguage extends TargetLanguage<"Rust", ["rust", "rs", "rustlang"], "rs"> { - constructor() { - super("Rust", ["rust", "rs", "rustlang"], "rs"); +export class RustTargetLanguage< + const DisplayName extends string = "Rust", + const Names extends readonly string[] = readonly ["rust", "rs", "rustlang"], + const Extension extends string = "rs" +> extends TargetLanguage { + constructor( + displayName = "Rust" as DisplayName, + names = ["rust", "rs", "rustlang"] as unknown as Names, + extension = "rs" as Extension + ) { + super(displayName, names, extension); } protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): RustRenderer { diff --git a/packages/quicktype-core/src/language/Scala3.ts b/packages/quicktype-core/src/language/Scala3.ts index 31d2f3e90..3e8588580 100644 --- a/packages/quicktype-core/src/language/Scala3.ts +++ b/packages/quicktype-core/src/language/Scala3.ts @@ -245,10 +245,10 @@ export class Scala3Renderer extends ConvenienceRenderer { delimiter === "curly" ? ["{", "}"] : delimiter === "paren" - ? ["(", ")"] - : delimiter === "none" - ? ["", ""] - : ["{", "})"]; + ? ["(", ")"] + : delimiter === "none" + ? ["", ""] + : ["{", "})"]; this.emitLine(line, " ", open); this.indent(f); this.emitLine(close); @@ -670,9 +670,17 @@ export class CirceRenderer extends Scala3Renderer { } } -export class Scala3TargetLanguage extends TargetLanguage<"Scala3", ["scala3"], "scala"> { - constructor() { - super("Scala3", ["scala3"], "scala"); +export class Scala3TargetLanguage< + const DisplayName extends string = "Scala3", + const Names extends readonly string[] = readonly ["scala3"], + const Extension extends string = "scala" +> extends TargetLanguage { + constructor( + displayName = "Scala3" as DisplayName, + names = ["scala3"] as unknown as Names, + extension = "scala" as Extension + ) { + super(displayName, names, extension); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/Smithy4s.ts b/packages/quicktype-core/src/language/Smithy4s.ts index 203c3b277..c233c272d 100644 --- a/packages/quicktype-core/src/language/Smithy4s.ts +++ b/packages/quicktype-core/src/language/Smithy4s.ts @@ -205,10 +205,10 @@ export class Smithy4sRenderer extends ConvenienceRenderer { delimiter === "curly" ? ["{", "}"] : delimiter === "paren" - ? ["(", ")"] - : delimiter === "none" - ? ["", ""] - : ["{", "})"]; + ? ["(", ")"] + : delimiter === "none" + ? ["", ""] + : ["{", "})"]; this.emitLine(line, " ", open); this.indent(f); this.emitLine(close); @@ -510,9 +510,17 @@ export class Smithy4sRenderer extends ConvenienceRenderer { } } -export class SmithyTargetLanguage extends TargetLanguage<"Smithy", ["Smithy"], "smithy"> { - constructor() { - super("Smithy", ["Smithy"], "smithy"); +export class SmithyTargetLanguage< + const DisplayName extends string = "Smithy", + const Names extends readonly string[] = readonly ["Smithy"], + const Extension extends string = "smithy" +> extends TargetLanguage { + constructor( + displayName = "Smithy" as DisplayName, + names = ["Smithy"] as unknown as Names, + extension = "smithy" as Extension + ) { + super(displayName, names, extension); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/Swift.ts b/packages/quicktype-core/src/language/Swift.ts index e2415fb83..b8c30603a 100644 --- a/packages/quicktype-core/src/language/Swift.ts +++ b/packages/quicktype-core/src/language/Swift.ts @@ -137,9 +137,17 @@ export interface SwiftProperty { position: ForEachPosition; } -export class SwiftTargetLanguage extends TargetLanguage<"Swift", ["swift", "swift4"], "swift"> { - constructor() { - super("Swift", ["swift", "swift4"], "swift"); +export class SwiftTargetLanguage< + const DisplayName extends string = "Swift", + const Names extends readonly string[] = readonly ["swift", "swift4"], + const Extension extends string = "swift" +> extends TargetLanguage { + constructor( + displayName = "Swift" as DisplayName, + names = ["swift", "swift4"] as unknown as Names, + extension = "swift" as Extension + ) { + super(displayName, names, extension); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts index a3f766cd7..c6ed19bf7 100644 --- a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts +++ b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts @@ -25,13 +25,17 @@ export const typeScriptEffectSchemaOptions = { justSchema: new BooleanOption("just-schema", "Schema only", false) }; -export class TypeScriptEffectSchemaTargetLanguage extends TargetLanguage< - "TypeScript Effect Schema", - ["typescript-effect-schema"], - "ts" -> { - constructor() { - super("TypeScript Effect Schema", ["typescript-effect-schema"], "ts"); +export class TypeScriptEffectSchemaTargetLanguage< + const DisplayName extends string = "TypeScript Effect Schema", + const Names extends readonly string[] = readonly ["typescript-effect-schema"], + const Extension extends string = "ts" +> extends TargetLanguage { + constructor( + displayName = "TypeScript Effect Schema" as DisplayName, + names = ["typescript-effect-schema"] as unknown as Names, + extension = "ts" as Extension + ) { + super(displayName, names, extension); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/TypeScriptFlow.ts b/packages/quicktype-core/src/language/TypeScriptFlow.ts index 664ff92d2..97e9143c7 100644 --- a/packages/quicktype-core/src/language/TypeScriptFlow.ts +++ b/packages/quicktype-core/src/language/TypeScriptFlow.ts @@ -76,13 +76,17 @@ export abstract class TypeScriptFlowBaseTargetLanguage< ): JavaScriptRenderer; } -export class TypeScriptTargetLanguage extends TypeScriptFlowBaseTargetLanguage< - "TypeScript", - ["typescript", "ts", "tsx"], - "ts" -> { - constructor() { - super("TypeScript", ["typescript", "ts", "tsx"], "ts"); +export class TypeScriptTargetLanguage< + const DisplayName extends string = "TypeScript", + const Names extends readonly string[] = readonly ["typescript", "ts", "tsx"], + const Extension extends string = "ts" +> extends TypeScriptFlowBaseTargetLanguage { + constructor( + displayName = "TypeScript" as DisplayName, + names = ["typescript", "ts", "tsx"] as unknown as Names, + extension = "ts" as Extension + ) { + super(displayName, names, extension); } protected makeRenderer( @@ -351,9 +355,17 @@ export class TypeScriptRenderer extends TypeScriptFlowBaseRenderer { } } -export class FlowTargetLanguage extends TypeScriptFlowBaseTargetLanguage<"Flow", ["flow"], "js"> { - constructor() { - super("Flow", ["flow"], "js"); +export class FlowTargetLanguage< + const DisplayName extends string = "Flow", + const Names extends readonly string[] = readonly ["flow"], + const Extension extends string = "js" +> extends TypeScriptFlowBaseTargetLanguage { + constructor( + displayName = "Flow" as DisplayName, + names = ["flow"] as unknown as Names, + extension = "js" as Extension + ) { + super(displayName, names, extension); } protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): FlowRenderer { diff --git a/packages/quicktype-core/src/language/TypeScriptZod.ts b/packages/quicktype-core/src/language/TypeScriptZod.ts index 77d0ea9c1..319a99fb0 100644 --- a/packages/quicktype-core/src/language/TypeScriptZod.ts +++ b/packages/quicktype-core/src/language/TypeScriptZod.ts @@ -37,9 +37,17 @@ export const typeScriptZodOptions = { justSchema: new BooleanOption("just-schema", "Schema only", false) }; -export class TypeScriptZodTargetLanguage extends TargetLanguage<"TypeScript Zod", ["typescript-zod"], "ts"> { - constructor() { - super("TypeScript Zod", ["typescript-zod"], "ts"); +export class TypeScriptZodTargetLanguage< + const DisplayName extends string = "TypeScript Zod", + const Names extends readonly string[] = readonly ["typescript-zod"], + const Extension extends string = "ts" +> extends TargetLanguage { + constructor( + displayName = "TypeScript Zod" as DisplayName, + names = ["typescript-zod"] as unknown as Names, + extension = "ts" as Extension + ) { + super(displayName, names, extension); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/ruby/index.ts b/packages/quicktype-core/src/language/ruby/index.ts index eb2774103..252f3da0b 100644 --- a/packages/quicktype-core/src/language/ruby/index.ts +++ b/packages/quicktype-core/src/language/ruby/index.ts @@ -51,9 +51,17 @@ export const rubyOptions = { namespace: new StringOption("namespace", "Specify a wrapping Namespace", "NAME", "", "secondary") }; -export class RubyTargetLanguage extends TargetLanguage<"Ruby", ["ruby"], "rb"> { - constructor() { - super("Ruby", ["ruby"], "rb"); +export class RubyTargetLanguage< + const DisplayName extends string = "Ruby", + const Names extends readonly string[] = readonly ["ruby"], + const Extension extends string = "rb" +> extends TargetLanguage { + constructor( + displayName = "Ruby" as DisplayName, + names = ["ruby"] as unknown as Names, + extension = "rb" as Extension + ) { + super(displayName, names, extension); } protected getOptions(): Option[] { From 6fd903ce8ea13d620e6fdf56a58b722393402586 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Tue, 16 Apr 2024 08:19:54 -0700 Subject: [PATCH 50/94] add generics for elixir --- packages/quicktype-core/src/language/Elixir.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/quicktype-core/src/language/Elixir.ts b/packages/quicktype-core/src/language/Elixir.ts index 9efb257a5..5055aad29 100644 --- a/packages/quicktype-core/src/language/Elixir.ts +++ b/packages/quicktype-core/src/language/Elixir.ts @@ -147,11 +147,18 @@ export const elixirOptions = { namespace: new StringOption("namespace", "Specify a module namespace", "NAME", "") }; -export class ElixirTargetLanguage extends TargetLanguage { - constructor() { - super("Elixir", ["elixir"], "ex"); +export class ElixirTargetLanguage< + const DisplayName extends string = "Elixir", + const Names extends readonly string[] = readonly ["elixir"], + const Extension extends string = "ex" +> extends TargetLanguage { + constructor( + displayName = "Elixir" as DisplayName, + names = ["elixir"] as unknown as Names, + extension = "ex" as Extension + ) { + super(displayName, names, extension); } - protected getOptions(): Option[] { return [elixirOptions.justTypes, elixirOptions.namespace]; } From 719a02832de4b34e5e04547b6349bfccb5b3e8ab Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Tue, 16 Apr 2024 08:25:47 -0700 Subject: [PATCH 51/94] typescript 4.9 doesn't support const generics yet --- packages/quicktype-core/src/language/CJSON.ts | 6 +++--- packages/quicktype-core/src/language/CPlusPlus.ts | 6 +++--- packages/quicktype-core/src/language/CSharp.ts | 6 +++--- packages/quicktype-core/src/language/Crystal.ts | 6 +++--- packages/quicktype-core/src/language/Dart.ts | 6 +++--- packages/quicktype-core/src/language/Elixir.ts | 6 +++--- packages/quicktype-core/src/language/Elm.ts | 6 +++--- packages/quicktype-core/src/language/Golang.ts | 6 +++--- packages/quicktype-core/src/language/Haskell.ts | 6 +++--- packages/quicktype-core/src/language/JSONSchema.ts | 6 +++--- packages/quicktype-core/src/language/Java.ts | 6 +++--- .../src/language/JavaScriptPropTypes.ts | 6 +++--- packages/quicktype-core/src/language/Kotlin.ts | 6 +++--- packages/quicktype-core/src/language/Objective-C.ts | 6 +++--- packages/quicktype-core/src/language/Php.ts | 6 +++--- packages/quicktype-core/src/language/Pike.ts | 6 +++--- packages/quicktype-core/src/language/Python.ts | 6 +++--- packages/quicktype-core/src/language/Rust.ts | 6 +++--- packages/quicktype-core/src/language/Scala3.ts | 6 +++--- packages/quicktype-core/src/language/Smithy4s.ts | 6 +++--- packages/quicktype-core/src/language/Swift.ts | 6 +++--- .../src/language/TypeScriptEffectSchema.ts | 6 +++--- .../quicktype-core/src/language/TypeScriptFlow.ts | 12 ++++++------ .../quicktype-core/src/language/TypeScriptZod.ts | 6 +++--- packages/quicktype-core/src/language/ruby/index.ts | 6 +++--- 25 files changed, 78 insertions(+), 78 deletions(-) diff --git a/packages/quicktype-core/src/language/CJSON.ts b/packages/quicktype-core/src/language/CJSON.ts index 19c322ca1..a4f9e6046 100644 --- a/packages/quicktype-core/src/language/CJSON.ts +++ b/packages/quicktype-core/src/language/CJSON.ts @@ -129,9 +129,9 @@ export const cJSONOptions = { /* cJSON generator target language */ export class CJSONTargetLanguage< - const DisplayName extends string = "C (cJSON)", - const Names extends readonly string[] = readonly ["cjson", "cJSON"], - const Extension extends string = "h" + DisplayName extends string = "C (cJSON)", + Names extends readonly string[] = readonly ["cjson", "cJSON"], + Extension extends string = "h" > extends TargetLanguage { constructor( displayName = "C (cJSON)" as DisplayName, diff --git a/packages/quicktype-core/src/language/CPlusPlus.ts b/packages/quicktype-core/src/language/CPlusPlus.ts index 029d85806..ecbd80fb6 100644 --- a/packages/quicktype-core/src/language/CPlusPlus.ts +++ b/packages/quicktype-core/src/language/CPlusPlus.ts @@ -119,9 +119,9 @@ export const cPlusPlusOptions = { }; export class CPlusPlusTargetLanguage< - const DisplayName extends string = "C++", - const Names extends readonly string[] = readonly ["c++", "cpp", "cplusplus"], - const Extension extends string = "cpp" + DisplayName extends string = "C++", + Names extends readonly string[] = readonly ["c++", "cpp", "cplusplus"], + Extension extends string = "cpp" > extends TargetLanguage { constructor( displayName = "C++" as DisplayName, diff --git a/packages/quicktype-core/src/language/CSharp.ts b/packages/quicktype-core/src/language/CSharp.ts index f81b22885..d2dfd2a7c 100644 --- a/packages/quicktype-core/src/language/CSharp.ts +++ b/packages/quicktype-core/src/language/CSharp.ts @@ -195,9 +195,9 @@ export const cSharpOptions = { }; export class CSharpTargetLanguage< - const DisplayName extends string = "C#", - const Names extends readonly string[] = readonly ["cs", "csharp"], - const Extension extends string = "cs" + DisplayName extends string = "C#", + Names extends readonly string[] = readonly ["cs", "csharp"], + Extension extends string = "cs" > extends TargetLanguage { constructor( displayName = "C#" as DisplayName, diff --git a/packages/quicktype-core/src/language/Crystal.ts b/packages/quicktype-core/src/language/Crystal.ts index 52d1c6089..54a4b2f4a 100644 --- a/packages/quicktype-core/src/language/Crystal.ts +++ b/packages/quicktype-core/src/language/Crystal.ts @@ -23,9 +23,9 @@ import { Option } from "../RendererOptions"; import { RenderContext } from "../Renderer"; export class CrystalTargetLanguage< - const DisplayName extends string = "Crystal", - const Names extends readonly string[] = readonly ["crystal", "cr", "crystallang"], - const Extension extends string = "cr" + DisplayName extends string = "Crystal", + Names extends readonly string[] = readonly ["crystal", "cr", "crystallang"], + Extension extends string = "cr" > extends TargetLanguage { constructor( displayName = "Crystal" as DisplayName, diff --git a/packages/quicktype-core/src/language/Dart.ts b/packages/quicktype-core/src/language/Dart.ts index 3e9fd687f..416241f29 100644 --- a/packages/quicktype-core/src/language/Dart.ts +++ b/packages/quicktype-core/src/language/Dart.ts @@ -62,9 +62,9 @@ export const dartOptions = { }; export class DartTargetLanguage< - const DisplayName extends string = "Dart", - const Names extends readonly string[] = readonly ["dart"], - const Extension extends string = "dart" + DisplayName extends string = "Dart", + Names extends readonly string[] = readonly ["dart"], + Extension extends string = "dart" > extends TargetLanguage { constructor( displayName = "Dart" as DisplayName, diff --git a/packages/quicktype-core/src/language/Elixir.ts b/packages/quicktype-core/src/language/Elixir.ts index 5055aad29..f16ae1138 100644 --- a/packages/quicktype-core/src/language/Elixir.ts +++ b/packages/quicktype-core/src/language/Elixir.ts @@ -148,9 +148,9 @@ export const elixirOptions = { }; export class ElixirTargetLanguage< - const DisplayName extends string = "Elixir", - const Names extends readonly string[] = readonly ["elixir"], - const Extension extends string = "ex" + DisplayName extends string = "Elixir", + Names extends readonly string[] = readonly ["elixir"], + Extension extends string = "ex" > extends TargetLanguage { constructor( displayName = "Elixir" as DisplayName, diff --git a/packages/quicktype-core/src/language/Elm.ts b/packages/quicktype-core/src/language/Elm.ts index cba6216ec..34061f318 100644 --- a/packages/quicktype-core/src/language/Elm.ts +++ b/packages/quicktype-core/src/language/Elm.ts @@ -35,9 +35,9 @@ export const elmOptions = { }; export class ElmTargetLanguage< - const DisplayName extends string = "Elm", - const Names extends readonly string[] = readonly ["elm"], - const Extension extends string = "elm" + DisplayName extends string = "Elm", + Names extends readonly string[] = readonly ["elm"], + Extension extends string = "elm" > extends TargetLanguage { constructor( displayName = "Elm" as DisplayName, diff --git a/packages/quicktype-core/src/language/Golang.ts b/packages/quicktype-core/src/language/Golang.ts index b3fbc9a48..71c46820f 100644 --- a/packages/quicktype-core/src/language/Golang.ts +++ b/packages/quicktype-core/src/language/Golang.ts @@ -35,9 +35,9 @@ export const goOptions = { }; export class GoTargetLanguage< - const DisplayName extends string = "Go", - const Names extends readonly string[] = readonly ["go", "golang"], - const Extension extends string = "go" + DisplayName extends string = "Go", + Names extends readonly string[] = readonly ["go", "golang"], + Extension extends string = "go" > extends TargetLanguage { constructor( displayName = "Go" as DisplayName, diff --git a/packages/quicktype-core/src/language/Haskell.ts b/packages/quicktype-core/src/language/Haskell.ts index 2980e4e2e..214f34c6c 100644 --- a/packages/quicktype-core/src/language/Haskell.ts +++ b/packages/quicktype-core/src/language/Haskell.ts @@ -30,9 +30,9 @@ export const haskellOptions = { }; export class HaskellTargetLanguage< - const DisplayName extends string = "Haskell", - const Names extends readonly string[] = readonly ["haskell"], - const Extension extends string = "haskell" + DisplayName extends string = "Haskell", + Names extends readonly string[] = readonly ["haskell"], + Extension extends string = "haskell" > extends TargetLanguage { constructor( displayName = "Haskell" as DisplayName, diff --git a/packages/quicktype-core/src/language/JSONSchema.ts b/packages/quicktype-core/src/language/JSONSchema.ts index a82135f3c..1d079e00a 100644 --- a/packages/quicktype-core/src/language/JSONSchema.ts +++ b/packages/quicktype-core/src/language/JSONSchema.ts @@ -19,9 +19,9 @@ import { Option } from "../RendererOptions"; import { RenderContext } from "../Renderer"; export class JSONSchemaTargetLanguage< - const DisplayName extends string = "JSON Schema", - const Names extends readonly string[] = readonly ["schema", "json-schema"], - const Extension extends string = "schema" + DisplayName extends string = "JSON Schema", + Names extends readonly string[] = readonly ["schema", "json-schema"], + Extension extends string = "schema" > extends TargetLanguage { constructor( displayName = "JSON Schema" as DisplayName, diff --git a/packages/quicktype-core/src/language/Java.ts b/packages/quicktype-core/src/language/Java.ts index d1b91671e..7ec11f332 100644 --- a/packages/quicktype-core/src/language/Java.ts +++ b/packages/quicktype-core/src/language/Java.ts @@ -54,9 +54,9 @@ export const javaOptions = { }; export class JavaTargetLanguage< - const DisplayName extends string = "Java", - const Names extends readonly string[] = readonly ["java"], - const Extension extends string = "java" + DisplayName extends string = "Java", + Names extends readonly string[] = readonly ["java"], + Extension extends string = "java" > extends TargetLanguage { constructor( displayName = "Java" as DisplayName, diff --git a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts index 78b92049c..0921ddfe0 100644 --- a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts +++ b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts @@ -40,9 +40,9 @@ export const javaScriptPropTypesOptions = { }; export class JavaScriptPropTypesTargetLanguage< - const DisplayName extends string = "JavaScript PropTypes", - const Names extends readonly string[] = readonly ["javascript-prop-types"], - const Extension extends string = "js" + DisplayName extends string = "JavaScript PropTypes", + Names extends readonly string[] = readonly ["javascript-prop-types"], + Extension extends string = "js" > extends TargetLanguage { constructor( displayName = "JavaScript PropTypes" as DisplayName, diff --git a/packages/quicktype-core/src/language/Kotlin.ts b/packages/quicktype-core/src/language/Kotlin.ts index b5a7cc8f0..4581ab961 100644 --- a/packages/quicktype-core/src/language/Kotlin.ts +++ b/packages/quicktype-core/src/language/Kotlin.ts @@ -62,9 +62,9 @@ export const kotlinOptions = { }; export class KotlinTargetLanguage< - const DisplayName extends string = "Kotlin", - const Names extends readonly string[] = readonly ["kotlin"], - const Extension extends string = "kt" + DisplayName extends string = "Kotlin", + Names extends readonly string[] = readonly ["kotlin"], + Extension extends string = "kt" > extends TargetLanguage { constructor( displayName = "Kotlin" as DisplayName, diff --git a/packages/quicktype-core/src/language/Objective-C.ts b/packages/quicktype-core/src/language/Objective-C.ts index 8a8aefeac..3d02a574a 100644 --- a/packages/quicktype-core/src/language/Objective-C.ts +++ b/packages/quicktype-core/src/language/Objective-C.ts @@ -44,9 +44,9 @@ export const objcOptions = { }; export class ObjectiveCTargetLanguage< - const DisplayName extends string = "Objective-C", - const Names extends readonly string[] = readonly ["objc", "objective-c", "objectivec"], - const Extension extends string = "m" + DisplayName extends string = "Objective-C", + Names extends readonly string[] = readonly ["objc", "objective-c", "objectivec"], + Extension extends string = "m" > extends TargetLanguage { constructor( displayName = "Objective-C" as DisplayName, diff --git a/packages/quicktype-core/src/language/Php.ts b/packages/quicktype-core/src/language/Php.ts index e7ecf7b28..f5d12a7d9 100644 --- a/packages/quicktype-core/src/language/Php.ts +++ b/packages/quicktype-core/src/language/Php.ts @@ -35,9 +35,9 @@ export const phpOptions = { }; export class PhpTargetLanguage< - const DisplayName extends string = "PHP", - const Names extends readonly string[] = readonly ["php"], - const Extension extends string = "php" + DisplayName extends string = "PHP", + Names extends readonly string[] = readonly ["php"], + Extension extends string = "php" > extends TargetLanguage { constructor( displayName = "PHP" as DisplayName, diff --git a/packages/quicktype-core/src/language/Pike.ts b/packages/quicktype-core/src/language/Pike.ts index 2ac61e105..afc510c8c 100644 --- a/packages/quicktype-core/src/language/Pike.ts +++ b/packages/quicktype-core/src/language/Pike.ts @@ -71,9 +71,9 @@ const namingFunction = funPrefixNamer("genericNamer", makeNameStyle("underscore" const namedTypeNamingFunction = funPrefixNamer("typeNamer", makeNameStyle("pascal", legalizeName)); export class PikeTargetLanguage< - const DisplayName extends string = "Pike", - const Names extends readonly string[] = readonly ["pike", "pikelang"], - const Extension extends string = "pmod" + DisplayName extends string = "Pike", + Names extends readonly string[] = readonly ["pike", "pikelang"], + Extension extends string = "pmod" > extends TargetLanguage { constructor( displayName = "Pike" as DisplayName, diff --git a/packages/quicktype-core/src/language/Python.ts b/packages/quicktype-core/src/language/Python.ts index 8808f3922..0e91e8f79 100644 --- a/packages/quicktype-core/src/language/Python.ts +++ b/packages/quicktype-core/src/language/Python.ts @@ -130,9 +130,9 @@ export const pythonOptions = { }; export class PythonTargetLanguage< - const DisplayName extends string = "Python", - const Names extends readonly string[] = readonly ["python", "py"], - const Extension extends string = "py" + DisplayName extends string = "Python", + Names extends readonly string[] = readonly ["python", "py"], + Extension extends string = "py" > extends TargetLanguage { constructor( displayName = "Python" as DisplayName, diff --git a/packages/quicktype-core/src/language/Rust.ts b/packages/quicktype-core/src/language/Rust.ts index cf79a1bba..79b3d4bb9 100644 --- a/packages/quicktype-core/src/language/Rust.ts +++ b/packages/quicktype-core/src/language/Rust.ts @@ -112,9 +112,9 @@ const namingStyles: Record = { }; export class RustTargetLanguage< - const DisplayName extends string = "Rust", - const Names extends readonly string[] = readonly ["rust", "rs", "rustlang"], - const Extension extends string = "rs" + DisplayName extends string = "Rust", + Names extends readonly string[] = readonly ["rust", "rs", "rustlang"], + Extension extends string = "rs" > extends TargetLanguage { constructor( displayName = "Rust" as DisplayName, diff --git a/packages/quicktype-core/src/language/Scala3.ts b/packages/quicktype-core/src/language/Scala3.ts index 3e8588580..fc2053b00 100644 --- a/packages/quicktype-core/src/language/Scala3.ts +++ b/packages/quicktype-core/src/language/Scala3.ts @@ -671,9 +671,9 @@ export class CirceRenderer extends Scala3Renderer { } export class Scala3TargetLanguage< - const DisplayName extends string = "Scala3", - const Names extends readonly string[] = readonly ["scala3"], - const Extension extends string = "scala" + DisplayName extends string = "Scala3", + Names extends readonly string[] = readonly ["scala3"], + Extension extends string = "scala" > extends TargetLanguage { constructor( displayName = "Scala3" as DisplayName, diff --git a/packages/quicktype-core/src/language/Smithy4s.ts b/packages/quicktype-core/src/language/Smithy4s.ts index c233c272d..70ba91158 100644 --- a/packages/quicktype-core/src/language/Smithy4s.ts +++ b/packages/quicktype-core/src/language/Smithy4s.ts @@ -511,9 +511,9 @@ export class Smithy4sRenderer extends ConvenienceRenderer { } export class SmithyTargetLanguage< - const DisplayName extends string = "Smithy", - const Names extends readonly string[] = readonly ["Smithy"], - const Extension extends string = "smithy" + DisplayName extends string = "Smithy", + Names extends readonly string[] = readonly ["Smithy"], + Extension extends string = "smithy" > extends TargetLanguage { constructor( displayName = "Smithy" as DisplayName, diff --git a/packages/quicktype-core/src/language/Swift.ts b/packages/quicktype-core/src/language/Swift.ts index b8c30603a..673892c52 100644 --- a/packages/quicktype-core/src/language/Swift.ts +++ b/packages/quicktype-core/src/language/Swift.ts @@ -138,9 +138,9 @@ export interface SwiftProperty { } export class SwiftTargetLanguage< - const DisplayName extends string = "Swift", - const Names extends readonly string[] = readonly ["swift", "swift4"], - const Extension extends string = "swift" + DisplayName extends string = "Swift", + Names extends readonly string[] = readonly ["swift", "swift4"], + Extension extends string = "swift" > extends TargetLanguage { constructor( displayName = "Swift" as DisplayName, diff --git a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts index c6ed19bf7..b9dacd95c 100644 --- a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts +++ b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts @@ -26,9 +26,9 @@ export const typeScriptEffectSchemaOptions = { }; export class TypeScriptEffectSchemaTargetLanguage< - const DisplayName extends string = "TypeScript Effect Schema", - const Names extends readonly string[] = readonly ["typescript-effect-schema"], - const Extension extends string = "ts" + DisplayName extends string = "TypeScript Effect Schema", + Names extends readonly string[] = readonly ["typescript-effect-schema"], + Extension extends string = "ts" > extends TargetLanguage { constructor( displayName = "TypeScript Effect Schema" as DisplayName, diff --git a/packages/quicktype-core/src/language/TypeScriptFlow.ts b/packages/quicktype-core/src/language/TypeScriptFlow.ts index 97e9143c7..03d63d197 100644 --- a/packages/quicktype-core/src/language/TypeScriptFlow.ts +++ b/packages/quicktype-core/src/language/TypeScriptFlow.ts @@ -77,9 +77,9 @@ export abstract class TypeScriptFlowBaseTargetLanguage< } export class TypeScriptTargetLanguage< - const DisplayName extends string = "TypeScript", - const Names extends readonly string[] = readonly ["typescript", "ts", "tsx"], - const Extension extends string = "ts" + DisplayName extends string = "TypeScript", + Names extends readonly string[] = readonly ["typescript", "ts", "tsx"], + Extension extends string = "ts" > extends TypeScriptFlowBaseTargetLanguage { constructor( displayName = "TypeScript" as DisplayName, @@ -356,9 +356,9 @@ export class TypeScriptRenderer extends TypeScriptFlowBaseRenderer { } export class FlowTargetLanguage< - const DisplayName extends string = "Flow", - const Names extends readonly string[] = readonly ["flow"], - const Extension extends string = "js" + DisplayName extends string = "Flow", + Names extends readonly string[] = readonly ["flow"], + Extension extends string = "js" > extends TypeScriptFlowBaseTargetLanguage { constructor( displayName = "Flow" as DisplayName, diff --git a/packages/quicktype-core/src/language/TypeScriptZod.ts b/packages/quicktype-core/src/language/TypeScriptZod.ts index 319a99fb0..3c73fed5e 100644 --- a/packages/quicktype-core/src/language/TypeScriptZod.ts +++ b/packages/quicktype-core/src/language/TypeScriptZod.ts @@ -38,9 +38,9 @@ export const typeScriptZodOptions = { }; export class TypeScriptZodTargetLanguage< - const DisplayName extends string = "TypeScript Zod", - const Names extends readonly string[] = readonly ["typescript-zod"], - const Extension extends string = "ts" + DisplayName extends string = "TypeScript Zod", + Names extends readonly string[] = readonly ["typescript-zod"], + Extension extends string = "ts" > extends TargetLanguage { constructor( displayName = "TypeScript Zod" as DisplayName, diff --git a/packages/quicktype-core/src/language/ruby/index.ts b/packages/quicktype-core/src/language/ruby/index.ts index 252f3da0b..9e4fab636 100644 --- a/packages/quicktype-core/src/language/ruby/index.ts +++ b/packages/quicktype-core/src/language/ruby/index.ts @@ -52,9 +52,9 @@ export const rubyOptions = { }; export class RubyTargetLanguage< - const DisplayName extends string = "Ruby", - const Names extends readonly string[] = readonly ["ruby"], - const Extension extends string = "rb" + DisplayName extends string = "Ruby", + Names extends readonly string[] = readonly ["ruby"], + Extension extends string = "rb" > extends TargetLanguage { constructor( displayName = "Ruby" as DisplayName, From a0e399a369d8c1e6645bb7d99aeb0d210e5fbd95 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Tue, 16 Apr 2024 08:36:46 -0700 Subject: [PATCH 52/94] export LanguageName type and predicates --- packages/quicktype-core/src/index.ts | 3 ++- packages/quicktype-core/src/language/All.ts | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/quicktype-core/src/index.ts b/packages/quicktype-core/src/index.ts index 67711c93d..6cd63c08b 100644 --- a/packages/quicktype-core/src/index.ts +++ b/packages/quicktype-core/src/index.ts @@ -21,7 +21,7 @@ export { Ref, JSONSchemaType, JSONSchemaAttributes } from "./input/JSONSchemaInp export { RenderContext } from "./Renderer"; export { Option, OptionDefinition, getOptionValues, OptionValues } from "./RendererOptions"; export { TargetLanguage, MultiFileRenderResult } from "./TargetLanguage"; -export { all as defaultTargetLanguages, languageNamed } from "./language/All"; +export { all as defaultTargetLanguages, languageNamed, isLanguageName } from "./language/All"; export { MultiWord, Sourcelike, @@ -81,6 +81,7 @@ export { StringTypes } from "./attributes/StringTypes"; export { removeNullFromUnion, matchType, nullableFromUnion } from "./TypeUtils"; export { ConvenienceRenderer } from "./ConvenienceRenderer"; export { uriTypeAttributeKind } from "./attributes/URIAttributes"; +export { type LanguageName, type LanguageDisplayName } from "./types"; export { CJSONTargetLanguage, CJSONRenderer, cJSONOptions } from "./language/CJSON"; export { CPlusPlusTargetLanguage, CPlusPlusRenderer, cPlusPlusOptions } from "./language/CPlusPlus"; diff --git a/packages/quicktype-core/src/language/All.ts b/packages/quicktype-core/src/language/All.ts index 9068d5d08..d15e3f55d 100644 --- a/packages/quicktype-core/src/language/All.ts +++ b/packages/quicktype-core/src/language/All.ts @@ -27,7 +27,7 @@ import { PhpTargetLanguage } from "./Php"; import { TypeScriptEffectSchemaTargetLanguage } from "./TypeScriptEffectSchema"; import { ElixirTargetLanguage } from "./Elixir"; -import type { LanguageName, LanguageNameMap } from "../types"; +import type { LanguageDisplayName, LanguageName, LanguageNameMap } from "../types"; export const all = [ new CJSONTargetLanguage(), @@ -72,3 +72,16 @@ export function languageNamed( return foundLanguage as LanguageNameMap[Name]; } + +export function isLanguageName(maybeName: string): maybeName is LanguageName { + if (all.some(lang => (lang.names as readonly string[]).includes(maybeName))) { + return true; + } + return false; +} +export function isLanguageDisplayName(maybeName: string): maybeName is LanguageDisplayName { + if (all.some(lang => lang.displayName === maybeName)) { + return true; + } + return false; +} From 45c06ce0f01dbbe23ddc4bd4ee23de9f3a037a4f Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Tue, 16 Apr 2024 08:36:53 -0700 Subject: [PATCH 53/94] fix type safety for extension --- packages/quicktype-vscode/src/extension.ts | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/packages/quicktype-vscode/src/extension.ts b/packages/quicktype-vscode/src/extension.ts index 3c62a47d2..888692525 100644 --- a/packages/quicktype-vscode/src/extension.ts +++ b/packages/quicktype-vscode/src/extension.ts @@ -15,7 +15,8 @@ import { jsonInputForTargetLanguage, RendererOptions, Options, - inferenceFlagNames + inferenceFlagNames, + isLanguageName } from "quicktype-core"; import { schemaForTypeScriptSources } from "quicktype-typescript-input"; @@ -62,15 +63,16 @@ async function pickTargetLanguage(): Promise { const languageChoices = defaultTargetLanguages.map(l => l.displayName).sort(); let chosenName = await vscode.window.showQuickPick(languageChoices); const cancelled = chosenName === undefined; - if (chosenName === undefined) { - chosenName = "typescript"; + if (chosenName === undefined || !isLanguageName(chosenName)) { + return { cancelled, lang: languageNamed("typescript") }; } - return { cancelled, lang: languageNamed(chosenName)! }; + return { cancelled, lang: languageNamed(chosenName) }; } async function getTargetLanguage(editor: vscode.TextEditor): Promise { const documentLanguage = editor.document.languageId; - const currentLanguage = languageNamed(documentLanguage); + const languageName = isLanguageName(documentLanguage) ? documentLanguage : "typescript"; + const currentLanguage = languageNamed(languageName); if (currentLanguage !== undefined) { return { cancelled: false, @@ -343,8 +345,9 @@ function deduceTargetLanguage(): TargetLanguage { } const sorted = Array.from(counts).sort(([_na, ca], [_nb, cb]) => cb - ca); for (const [name] of sorted) { - const lang = languageNamed(name); - if (lang !== undefined) return lang; + if (isLanguageName(name)) { + return languageNamed(name); + } } return languageNamed("typescript")!; } @@ -450,7 +453,7 @@ export async function activate(context: vscode.ExtensionContext): Promise ); const maybeName = extensionContext.workspaceState.get(lastTargetLanguageUsedKey); - if (typeof maybeName === "string") { + if (typeof maybeName === "string" && isLanguageName(maybeName)) { explicitlySetTargetLanguage = languageNamed(maybeName); } } From beddba2765a3864fb3bd55bd10fe6e596f148974 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Tue, 16 Apr 2024 08:42:58 -0700 Subject: [PATCH 54/94] fix type safety for cli --- src/index.ts | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/index.ts b/src/index.ts index 943abdfb9..fa1b5c87f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -37,7 +37,8 @@ import { getStream, readableFromFileOrURL, readFromFileOrURL, - FetchingJSONSchemaStore + FetchingJSONSchemaStore, + isLanguageName } from "quicktype-core"; import { schemaForTypeScriptSources } from "quicktype-typescript-input"; import { GraphQLInput } from "quicktype-graphql-input"; @@ -264,11 +265,12 @@ function inferCLIOptions(opts: Partial, targetLanguage: TargetLangua language = targetLanguage; } else { const languageName = opts.lang !== undefined ? opts.lang : inferLang(opts, defaultDefaultTargetLanguageName); - const maybeLanguage = languageNamed(languageName); - if (maybeLanguage === undefined) { + + if (isLanguageName(languageName)) { + language = languageNamed(languageName); + } else { return messageError("DriverUnknownOutputLanguage", { lang: languageName }); } - language = maybeLanguage; } /* tslint:disable:strict-boolean-expressions */ @@ -303,7 +305,7 @@ function inferCLIOptions(opts: Partial, targetLanguage: TargetLangua return options; } -function makeLangTypeLabel(targetLanguages: TargetLanguage[]): string { +function makeLangTypeLabel(targetLanguages: readonly TargetLanguage[]): string { assert(targetLanguages.length > 0, "Must have at least one target language"); return targetLanguages.map(r => _.minBy(r.names, s => s.length)).join("|"); } @@ -322,7 +324,7 @@ function dashedFromCamelCase(name: string): string { .join("-"); } -function makeOptionDefinitions(targetLanguages: TargetLanguage[]): OptionDefinition[] { +function makeOptionDefinitions(targetLanguages: readonly TargetLanguage[]): OptionDefinition[] { const beforeLang: OptionDefinition[] = [ { name: "out", @@ -504,7 +506,7 @@ const tableOptionsForOptions: TableOptions = { ] }; -function makeSectionsBeforeRenderers(targetLanguages: TargetLanguage[]): UsageSection[] { +function makeSectionsBeforeRenderers(targetLanguages: readonly TargetLanguage[]): UsageSection[] { const langDisplayNames = targetLanguages.map(r => r.displayName).join(", "); return [ @@ -574,7 +576,8 @@ export function parseCLIOptions(argv: string[], targetLanguage?: TargetLanguage) // twice. This is the first parse to get the renderer: const incompleteOptions = inferCLIOptions(parseOptions(optionDefinitions, argv, true), targetLanguage); if (targetLanguage === undefined) { - targetLanguage = getTargetLanguage(incompleteOptions.lang); + const languageName = isLanguageName(incompleteOptions.lang) ? incompleteOptions.lang : "typescript"; + targetLanguage = getTargetLanguage(languageName); } const rendererOptionDefinitions = targetLanguage.cliOptionDefinitions.actual; // Use the global options as well as the renderer options from now on: @@ -615,7 +618,7 @@ function parseOptions(definitions: OptionDefinition[], argv: string[], partial: return options; } -function usage(targetLanguages: TargetLanguage[]) { +function usage(targetLanguages: readonly TargetLanguage[]) { const rendererSections: UsageSection[] = []; for (const language of targetLanguages) { @@ -696,7 +699,8 @@ export function jsonInputForTargetLanguage( handleJSONRefs = false ): JSONInput { if (typeof targetLanguage === "string") { - targetLanguage = defined(languageNamed(targetLanguage, languages)); + const languageName = isLanguageName(targetLanguage) ? targetLanguage : "typescript"; + targetLanguage = defined(languageNamed(languageName, languages)); } const compressedJSON = new CompressedJSONFromStream(targetLanguage.dateTimeRecognizer, handleJSONRefs); return new JSONInput(compressedJSON); @@ -870,10 +874,10 @@ export async function makeQuicktypeOptions( } } - const lang = languageNamed(options.lang, targetLanguages); - if (lang === undefined) { + if (!isLanguageName(options.lang)) { return messageError("DriverUnknownOutputLanguage", { lang: options.lang }); } + const lang = languageNamed(options.lang, targetLanguages); const quicktypeOptions: Partial = { lang, From fb25f797340b9bda06cc25481c709a1e8b4b6dd1 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Thu, 18 Apr 2024 23:06:42 -0700 Subject: [PATCH 55/94] reduce target language generic to singular config object --- packages/quicktype-core/src/TargetLanguage.ts | 28 +++++++++++-------- .../quicktype-core/src/language/Golang.ts | 22 +++++++-------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/packages/quicktype-core/src/TargetLanguage.ts b/packages/quicktype-core/src/TargetLanguage.ts index 229fa09bb..bdd0952bf 100644 --- a/packages/quicktype-core/src/TargetLanguage.ts +++ b/packages/quicktype-core/src/TargetLanguage.ts @@ -13,16 +13,22 @@ import { type Comment } from "./support/Comments"; export type MultiFileRenderResult = ReadonlyMap; -export abstract class TargetLanguage< - DisplayName extends string = string, - Names extends readonly string[] = readonly string[], - Extension extends string = string -> { - constructor( - readonly displayName: DisplayName, - readonly names: Names, - readonly extension: Extension - ) {} +export type LanguageConfig = { + readonly displayName: string; + readonly names: readonly string[]; + readonly extension: string; +}; + +export abstract class TargetLanguage { + displayName: Config["displayName"]; + names: Config["names"]; + extension: Config["extension"]; + + constructor({ displayName, names, extension }: Config) { + this.displayName = displayName; + this.names = names; + this.extension = extension; + } protected abstract getOptions(): Option[]; @@ -40,7 +46,7 @@ export abstract class TargetLanguage< return { actual, display }; } - get name(): Names[0] { + get name(): (typeof this.names)[0] { return defined(this.names[0]); } diff --git a/packages/quicktype-core/src/language/Golang.ts b/packages/quicktype-core/src/language/Golang.ts index 71c46820f..3b379b829 100644 --- a/packages/quicktype-core/src/language/Golang.ts +++ b/packages/quicktype-core/src/language/Golang.ts @@ -34,17 +34,15 @@ export const goOptions = { ) }; -export class GoTargetLanguage< - DisplayName extends string = "Go", - Names extends readonly string[] = readonly ["go", "golang"], - Extension extends string = "go" -> extends TargetLanguage { - constructor( - displayName = "Go" as DisplayName, - names = ["go", "golang"] as unknown as Names, - extension = "go" as Extension - ) { - super(displayName, names, extension); +const golangLanguageConfig = { + displayName: "Go", + names: ["go", "golang"], + extension: "go" +} as const; + +export class GoTargetLanguage extends TargetLanguage { + constructor() { + super(golangLanguageConfig); } protected getOptions(): Option[] { @@ -119,7 +117,7 @@ export class GoRenderer extends ConvenienceRenderer { private _currentFilename: string | undefined; constructor( - targetLanguage: TargetLanguage, + targetLanguage: GoTargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { From 050d6d03abb97bdd5b3b0a36f516e450466d87eb Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 20 Apr 2024 03:08:26 -0700 Subject: [PATCH 56/94] strongly type Renderer Options with map for enums --- .../quicktype-core/src/RendererOptions.ts | 106 +++++++++--------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/packages/quicktype-core/src/RendererOptions.ts b/packages/quicktype-core/src/RendererOptions.ts index 9ef964b42..bcefa98a9 100644 --- a/packages/quicktype-core/src/RendererOptions.ts +++ b/packages/quicktype-core/src/RendererOptions.ts @@ -8,71 +8,76 @@ import { hasOwnProperty } from "collection-utils"; */ export type OptionKind = "primary" | "secondary"; -export interface OptionDefinition { - name: string; +export interface OptionDefinition { + name: Name; + description: string; type: StringConstructor | BooleanConstructor; kind?: OptionKind; renderer?: boolean; alias?: string; multiple?: boolean; defaultOption?: boolean; - defaultValue?: any; + defaultValue?: T; typeLabel?: string; - description: string; - legalValues?: string[]; } /** * The superclass for target language options. You probably want to use one of its * subclasses, `BooleanOption`, `EnumOption`, or `StringOption`. */ -export abstract class Option { - readonly definition: OptionDefinition; +export abstract class Option { + readonly definition: OptionDefinition; - constructor(definition: OptionDefinition) { + constructor(definition: OptionDefinition) { definition.renderer = true; this.definition = definition; assert(definition.kind !== undefined, "Renderer option kind must be defined"); } - getValue(values: { [name: string]: any }): T { - const value = values[this.definition.name]; - if (value === undefined) { - return this.definition.defaultValue; - } - return value; + getValue(values: Record): T { + return (values[this.name] ?? this.definition.defaultValue) as T; + } + + get name(): Name { + return this.definition.name; } - get cliDefinitions(): { display: OptionDefinition[]; actual: OptionDefinition[] } { + get cliDefinitions(): { display: OptionDefinition[]; actual: OptionDefinition[] } { return { actual: [this.definition], display: [this.definition] }; } } -export type OptionValueType = O extends Option ? T : never; +export type OptionValueType = O extends Option ? T : never; export type OptionValues = { [P in keyof T]: OptionValueType }; -export function getOptionValues }>( - options: T, +export function getOptionValues>>( + options: Options, untypedOptionValues: { [name: string]: any } -): OptionValues { +): OptionValues { const optionValues: { [name: string]: any } = {}; for (const name of Object.getOwnPropertyNames(options)) { - optionValues[name] = options[name].getValue(untypedOptionValues); + const option = options[name]; + const value = option.getValue(untypedOptionValues); + if (option instanceof EnumOption) { + optionValues[name] = option.getEnumValue(value); + } else { + optionValues[name] = value; + } } - return optionValues as OptionValues; + return optionValues as OptionValues; } /** * A target language option that allows setting a boolean flag. */ -export class BooleanOption extends Option { +export class BooleanOption extends Option { /** * @param name The shorthand name. * @param description Short-ish description of the option. * @param defaultValue The default value. * @param kind Whether it's a primary or secondary option. */ - constructor(name: string, description: string, defaultValue: boolean, kind: OptionKind = "primary") { + constructor(name: Name, description: string, defaultValue: boolean, kind: OptionKind = "primary") { super({ name, kind, @@ -82,13 +87,13 @@ export class BooleanOption extends Option { }); } - get cliDefinitions(): { display: OptionDefinition[]; actual: OptionDefinition[] } { + get cliDefinitions(): { display: OptionDefinition[]; actual: OptionDefinition[] } { const negated = Object.assign({}, this.definition, { - name: `no-${this.definition.name}`, + name: `no-${this.name}`, defaultValue: !this.definition.defaultValue }); const display = Object.assign({}, this.definition, { - name: `[no-]${this.definition.name}`, + name: `[no-]${this.name}`, description: `${this.definition.description} (${this.definition.defaultValue ? "on" : "off"} by default)` }); return { @@ -97,13 +102,13 @@ export class BooleanOption extends Option { }; } - getValue(values: { [name: string]: any }): boolean { - let value = values[this.definition.name]; + getValue(values: Record): boolean { + let value = values[this.name]; if (value === undefined) { value = this.definition.defaultValue; } - let negated = values[`no-${this.definition.name}`]; + let negated = values[`no-${this.name}`]; if (negated === undefined) { negated = !this.definition.defaultValue; } @@ -115,16 +120,16 @@ export class BooleanOption extends Option { } if (this.definition.defaultValue) { - return value && !negated; + return (value && !negated) as boolean; } else { - return value || !negated; + return (value || !negated) as boolean; } } } -export class StringOption extends Option { +export class StringOption extends Option { constructor( - name: string, + name: Name, description: string, typeLabel: string, defaultValue: string, @@ -142,43 +147,38 @@ export class StringOption extends Option { } } -export class EnumOption extends Option { - private readonly _values: { [name: string]: T }; +type NoInfer = [T][T extends any ? 0 : never]; + +export class EnumOption< + Name extends string, + EnumMap extends Record, + EnumKey = keyof EnumMap +> extends Option { + private readonly _values: EnumMap; constructor( - name: string, + name: Name, description: string, - values: [string, T][], - defaultValue: string | undefined = undefined, + values: EnumMap, + defaultValue: NoInfer, kind: OptionKind = "primary" ) { - if (defaultValue === undefined) { - defaultValue = values[0][0]; - } const definition = { name, kind, type: String, description, - typeLabel: values.map(([n, _]) => n).join("|"), - legalValues: values.map(([n, _]) => n), + typeLabel: Object.keys(values).join("|"), defaultValue }; super(definition); - this._values = {}; - for (const [n, v] of values) { - this._values[n] = v; - } + this._values = values; } - getValue(values: { [name: string]: any }): T { - let name: string = values[this.definition.name]; - if (name === undefined) { - name = this.definition.defaultValue; - } + getEnumValue(name: Key): EnumMap[Key] { if (!hasOwnProperty(this._values, name)) { - return messageError("RendererUnknownOptionValue", { value: name, name: this.definition.name }); + return messageError("RendererUnknownOptionValue", { value: name, name: this.name }); } return this._values[name]; } From afdb99ad1bead4b2f0130d4b1b4cc95f968b88f5 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 20 Apr 2024 03:15:03 -0700 Subject: [PATCH 57/94] support existing tuple params --- .../quicktype-core/src/RendererOptions.ts | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/quicktype-core/src/RendererOptions.ts b/packages/quicktype-core/src/RendererOptions.ts index bcefa98a9..459012167 100644 --- a/packages/quicktype-core/src/RendererOptions.ts +++ b/packages/quicktype-core/src/RendererOptions.ts @@ -149,17 +149,22 @@ export class StringOption extends Option { type NoInfer = [T][T extends any ? 0 : never]; +// FIXME: remove tuples and use map export class EnumOption< Name extends string, - EnumMap extends Record, - EnumKey = keyof EnumMap + // EnumMap extends Record, + // EnumKey = keyof EnumMap + EnumTuples extends [string, unknown][], + EnumKey = EnumTuples[number][0], + EnumMap = { [Key in EnumTuples[number][0]]: Extract[1] } > extends Option { private readonly _values: EnumMap; constructor( name: Name, description: string, - values: EnumMap, + // values: EnumMap, + values: EnumTuples, defaultValue: NoInfer, kind: OptionKind = "primary" ) { @@ -168,15 +173,18 @@ export class EnumOption< kind, type: String, description, - typeLabel: Object.keys(values).join("|"), + // typeLabel: Object.keys(values).join("|"), + typeLabel: values.map(([key, _]) => key).join("|"), defaultValue }; super(definition); - this._values = values; + // this._values = values; + this._values = values.reduce((acc, [key, val]) => ({ ...acc, [key]: val }), {} as Partial) as EnumMap; } - getEnumValue(name: Key): EnumMap[Key] { + // getEnumValue(name: Key): EnumMap[Key] { + getEnumValue(name: Key): EnumMap[Key] { if (!hasOwnProperty(this._values, name)) { return messageError("RendererUnknownOptionValue", { value: name, name: this.name }); } From d0b8c15874aa377cfb1f1c72a4830fdc50b3a85b Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 20 Apr 2024 11:51:08 -0700 Subject: [PATCH 58/94] update all non-inherited target languages to have external language config --- packages/quicktype-core/src/language/CJSON.ts | 22 +++++++------- .../quicktype-core/src/language/CPlusPlus.ts | 22 +++++++------- .../quicktype-core/src/language/CSharp.ts | 22 +++++--------- .../quicktype-core/src/language/Crystal.ts | 22 +++++++------- packages/quicktype-core/src/language/Dart.ts | 22 +++++--------- .../quicktype-core/src/language/Elixir.ts | 22 +++++++------- packages/quicktype-core/src/language/Elm.ts | 22 +++++++------- .../quicktype-core/src/language/Haskell.ts | 22 +++++++------- .../quicktype-core/src/language/JSONSchema.ts | 20 ++++++------- packages/quicktype-core/src/language/Java.ts | 24 +++++++-------- .../quicktype-core/src/language/JavaScript.ts | 22 +++++++------- .../src/language/JavaScriptPropTypes.ts | 22 +++++++------- .../quicktype-core/src/language/Kotlin.ts | 28 ++++++++--------- .../src/language/Objective-C.ts | 22 +++++++------- packages/quicktype-core/src/language/Php.ts | 22 +++++++------- packages/quicktype-core/src/language/Pike.ts | 20 ++++++------- .../quicktype-core/src/language/Python.ts | 18 ++++------- packages/quicktype-core/src/language/Rust.ts | 22 +++++++------- .../quicktype-core/src/language/Scala3.ts | 30 +++++++++---------- .../quicktype-core/src/language/Smithy4s.ts | 30 +++++++++---------- packages/quicktype-core/src/language/Swift.ts | 22 +++++++------- .../src/language/TypeScriptEffectSchema.ts | 22 +++++++------- .../src/language/TypeScriptZod.ts | 22 +++++++------- .../quicktype-core/src/language/ruby/index.ts | 22 +++++++------- 24 files changed, 242 insertions(+), 302 deletions(-) diff --git a/packages/quicktype-core/src/language/CJSON.ts b/packages/quicktype-core/src/language/CJSON.ts index a4f9e6046..6e69e9ed1 100644 --- a/packages/quicktype-core/src/language/CJSON.ts +++ b/packages/quicktype-core/src/language/CJSON.ts @@ -128,17 +128,15 @@ export const cJSONOptions = { }; /* cJSON generator target language */ -export class CJSONTargetLanguage< - DisplayName extends string = "C (cJSON)", - Names extends readonly string[] = readonly ["cjson", "cJSON"], - Extension extends string = "h" -> extends TargetLanguage { - constructor( - displayName = "C (cJSON)" as DisplayName, - names = ["cjson", "cJSON"] as unknown as Names, - extension = "h" as Extension - ) { - super(displayName, names, extension); +export const cJSONLanguageConfig = { + displayName: "C (cJSON)", + names: ["cjson", "cJSON"], + extension: "h" +} as const; + +export class CJSONTargetLanguage extends TargetLanguage { + constructor() { + super(cJSONLanguageConfig); } /** @@ -379,7 +377,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param _options: renderer options */ constructor( - targetLanguage: TargetLanguage, + targetLanguage: CJSONTargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/CPlusPlus.ts b/packages/quicktype-core/src/language/CPlusPlus.ts index ecbd80fb6..96914a57d 100644 --- a/packages/quicktype-core/src/language/CPlusPlus.ts +++ b/packages/quicktype-core/src/language/CPlusPlus.ts @@ -118,17 +118,15 @@ export const cPlusPlusOptions = { hideNullOptional: new BooleanOption("hide-null-optional", "Hide null value for optional field", false) }; -export class CPlusPlusTargetLanguage< - DisplayName extends string = "C++", - Names extends readonly string[] = readonly ["c++", "cpp", "cplusplus"], - Extension extends string = "cpp" -> extends TargetLanguage { - constructor( - displayName = "C++" as DisplayName, - names = ["c++", "cpp", "cplusplus"] as unknown as Names, - extension = "cpp" as Extension - ) { - super(displayName, names, extension); +export const cPlusPlusLanguageConfig = { + displayName: "C++", + names: ["c++", "cpp", "cplusplus"], + extension: "cpp" +} as const; + +export class CPlusPlusTargetLanguage extends TargetLanguage { + constructor() { + super(cPlusPlusLanguageConfig); } protected getOptions(): Option[] { @@ -485,7 +483,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { protected readonly enumeratorNamingStyle: NamingStyle; constructor( - targetLanguage: TargetLanguage, + targetLanguage: CPlusPlusTargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/CSharp.ts b/packages/quicktype-core/src/language/CSharp.ts index d2dfd2a7c..e180ec705 100644 --- a/packages/quicktype-core/src/language/CSharp.ts +++ b/packages/quicktype-core/src/language/CSharp.ts @@ -194,17 +194,11 @@ export const cSharpOptions = { keepPropertyName: new BooleanOption("keep-property-name", "Keep original field name generate", false) }; -export class CSharpTargetLanguage< - DisplayName extends string = "C#", - Names extends readonly string[] = readonly ["cs", "csharp"], - Extension extends string = "cs" -> extends TargetLanguage { - constructor( - displayName = "C#" as DisplayName, - names = ["cs", "csharp"] as unknown as Names, - extension = "cs" as Extension - ) { - super(displayName, names, extension); +export const cSharpLanguageConfig = { displayName: "C#", names: ["cs", "csharp"], extension: "cs" } as const; + +export class CSharpTargetLanguage extends TargetLanguage { + constructor() { + super(cSharpLanguageConfig); } protected getOptions(): Option[] { @@ -424,7 +418,7 @@ function isValueType(t: Type): boolean { export class CSharpRenderer extends ConvenienceRenderer { constructor( - targetLanguage: TargetLanguage, + targetLanguage: CSharpTargetLanguage, renderContext: RenderContext, private readonly _csOptions: OptionValues ) { @@ -793,7 +787,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { private readonly _needNamespaces: boolean; constructor( - targetLanguage: TargetLanguage, + targetLanguage: CSharpTargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { @@ -1520,7 +1514,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { private readonly _needNamespaces: boolean; constructor( - targetLanguage: TargetLanguage, + targetLanguage: CSharpTargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/Crystal.ts b/packages/quicktype-core/src/language/Crystal.ts index 54a4b2f4a..9b10b1de1 100644 --- a/packages/quicktype-core/src/language/Crystal.ts +++ b/packages/quicktype-core/src/language/Crystal.ts @@ -22,17 +22,15 @@ import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; import { Option } from "../RendererOptions"; import { RenderContext } from "../Renderer"; -export class CrystalTargetLanguage< - DisplayName extends string = "Crystal", - Names extends readonly string[] = readonly ["crystal", "cr", "crystallang"], - Extension extends string = "cr" -> extends TargetLanguage { - constructor( - displayName = "Crystal" as DisplayName, - names = ["crystal", "cr", "crystallang"] as unknown as Names, - extension = "cr" as Extension - ) { - super(displayName, names, extension); +export const crystalLanguageConfig = { + displayName: "Crystal", + names: ["crystal", "cr", "crystallang"], + extension: "cr" +} as const; + +export class CrystalTargetLanguage extends TargetLanguage { + constructor() { + super(crystalLanguageConfig); } protected makeRenderer(renderContext: RenderContext): CrystalRenderer { @@ -236,7 +234,7 @@ function standardUnicodeCrystalEscape(codePoint: number): string { const crystalStringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, standardUnicodeCrystalEscape)); export class CrystalRenderer extends ConvenienceRenderer { - constructor(targetLanguage: TargetLanguage, renderContext: RenderContext) { + constructor(targetLanguage: CrystalTargetLanguage, renderContext: RenderContext) { super(targetLanguage, renderContext); } diff --git a/packages/quicktype-core/src/language/Dart.ts b/packages/quicktype-core/src/language/Dart.ts index 416241f29..23a86ca90 100644 --- a/packages/quicktype-core/src/language/Dart.ts +++ b/packages/quicktype-core/src/language/Dart.ts @@ -61,17 +61,11 @@ export const dartOptions = { partName: new StringOption("part-name", "Use this name in `part` directive", "NAME", "", "secondary") }; -export class DartTargetLanguage< - DisplayName extends string = "Dart", - Names extends readonly string[] = readonly ["dart"], - Extension extends string = "dart" -> extends TargetLanguage { - constructor( - displayName = "Dart" as DisplayName, - names = ["dart"] as unknown as Names, - extension = "dart" as Extension - ) { - super(displayName, names, extension); +export const dartLanguageConfig = { displayName: "Dart", names: ["dart"], extension: "dart" } as const; + +export class DartTargetLanguage extends TargetLanguage { + constructor() { + super(dartLanguageConfig); } protected getOptions(): Option[] { @@ -208,8 +202,8 @@ function dartNameStyle(startWithUpper: boolean, upperUnderscore: boolean, origin const firstWordStyle = upperUnderscore ? allUpperWordStyle : startWithUpper - ? firstUpperWordStyle - : allLowerWordStyle; + ? firstUpperWordStyle + : allLowerWordStyle; const restWordStyle = upperUnderscore ? allUpperWordStyle : firstUpperWordStyle; return combineWords( words, @@ -237,7 +231,7 @@ export class DartRenderer extends ConvenienceRenderer { private readonly _enumValues = new Map(); constructor( - targetLanguage: TargetLanguage, + targetLanguage: DartTargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/Elixir.ts b/packages/quicktype-core/src/language/Elixir.ts index f16ae1138..2d9dd6012 100644 --- a/packages/quicktype-core/src/language/Elixir.ts +++ b/packages/quicktype-core/src/language/Elixir.ts @@ -147,17 +147,15 @@ export const elixirOptions = { namespace: new StringOption("namespace", "Specify a module namespace", "NAME", "") }; -export class ElixirTargetLanguage< - DisplayName extends string = "Elixir", - Names extends readonly string[] = readonly ["elixir"], - Extension extends string = "ex" -> extends TargetLanguage { - constructor( - displayName = "Elixir" as DisplayName, - names = ["elixir"] as unknown as Names, - extension = "ex" as Extension - ) { - super(displayName, names, extension); +export const elixirLanguageConfig = { + displayName: "Elixir", + names: ["elixir"], + extension: "ex" +} as const; + +export class ElixirTargetLanguage extends TargetLanguage { + constructor() { + super(elixirLanguageConfig); } protected getOptions(): Option[] { return [elixirOptions.justTypes, elixirOptions.namespace]; @@ -218,7 +216,7 @@ function memberNameStyle(original: string): string { export class ElixirRenderer extends ConvenienceRenderer { constructor( - targetLanguage: TargetLanguage, + targetLanguage: ElixirTargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/Elm.ts b/packages/quicktype-core/src/language/Elm.ts index 34061f318..232e0028d 100644 --- a/packages/quicktype-core/src/language/Elm.ts +++ b/packages/quicktype-core/src/language/Elm.ts @@ -34,17 +34,15 @@ export const elmOptions = { moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType") }; -export class ElmTargetLanguage< - DisplayName extends string = "Elm", - Names extends readonly string[] = readonly ["elm"], - Extension extends string = "elm" -> extends TargetLanguage { - constructor( - displayName = "Elm" as DisplayName, - names = ["elm"] as unknown as Names, - extension = "elm" as Extension - ) { - super(displayName, names, extension); +export const elmLanguageConfig = { + displayName: "Elm", + names: ["elm"], + extension: "elm" +} as const; + +export class ElmTargetLanguage extends TargetLanguage { + constructor() { + super(elmLanguageConfig); } protected getOptions(): Option[] { @@ -158,7 +156,7 @@ export class ElmRenderer extends ConvenienceRenderer { private readonly _namedTypeDependents = new Map(); constructor( - targetLanguage: TargetLanguage, + targetLanguage: ElmTargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/Haskell.ts b/packages/quicktype-core/src/language/Haskell.ts index 214f34c6c..e05ec8cff 100644 --- a/packages/quicktype-core/src/language/Haskell.ts +++ b/packages/quicktype-core/src/language/Haskell.ts @@ -29,17 +29,15 @@ export const haskellOptions = { moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType") }; -export class HaskellTargetLanguage< - DisplayName extends string = "Haskell", - Names extends readonly string[] = readonly ["haskell"], - Extension extends string = "haskell" -> extends TargetLanguage { - constructor( - displayName = "Haskell" as DisplayName, - names = ["haskell"] as unknown as Names, - extension = "haskell" as Extension - ) { - super(displayName, names, extension); +export const haskellLanguageConfig = { + displayName: "Haskell", + names: ["haskell"], + extension: "haskell" +} as const; + +export class HaskellTargetLanguage extends TargetLanguage { + constructor() { + super(haskellLanguageConfig); } protected getOptions(): Option[] { @@ -138,7 +136,7 @@ const lowerNamingFunction = funPrefixNamer("lower", n => haskellNameStyle(n, fal export class HaskellRenderer extends ConvenienceRenderer { constructor( - targetLanguage: TargetLanguage, + targetLanguage: HaskellTargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/JSONSchema.ts b/packages/quicktype-core/src/language/JSONSchema.ts index 1d079e00a..2e87ead8d 100644 --- a/packages/quicktype-core/src/language/JSONSchema.ts +++ b/packages/quicktype-core/src/language/JSONSchema.ts @@ -18,17 +18,15 @@ import { addDescriptionToSchema } from "../attributes/Description"; import { Option } from "../RendererOptions"; import { RenderContext } from "../Renderer"; -export class JSONSchemaTargetLanguage< - DisplayName extends string = "JSON Schema", - Names extends readonly string[] = readonly ["schema", "json-schema"], - Extension extends string = "schema" -> extends TargetLanguage { - constructor( - displayName = "JSON Schema" as DisplayName, - names = ["schema", "json-schema"] as unknown as Names, - extension = "schema" as Extension - ) { - super(displayName, names, extension); +export const JSONSchemaLanguageConfig = { + displayName: "JSON Schema", + names: ["schema", "json-schema"], + extension: "schema" +} as const; + +export class JSONSchemaTargetLanguage extends TargetLanguage { + constructor() { + super(JSONSchemaLanguageConfig); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/Java.ts b/packages/quicktype-core/src/language/Java.ts index 7ec11f332..cb3d9efbc 100644 --- a/packages/quicktype-core/src/language/Java.ts +++ b/packages/quicktype-core/src/language/Java.ts @@ -53,17 +53,15 @@ export const javaOptions = { lombokCopyAnnotations: new BooleanOption("lombok-copy-annotations", "Copy accessor annotations", true, "secondary") }; -export class JavaTargetLanguage< - DisplayName extends string = "Java", - Names extends readonly string[] = readonly ["java"], - Extension extends string = "java" -> extends TargetLanguage { - constructor( - displayName = "Java" as DisplayName, - names = ["java"] as unknown as Names, - extension = "java" as Extension - ) { - super(displayName, names, extension); +export const javaLanguageConfig = { + displayName: "Java", + names: ["java"], + extension: "java" +} as const; + +export class JavaTargetLanguage extends TargetLanguage { + constructor() { + super(javaLanguageConfig); } protected getOptions(): Option[] { @@ -443,7 +441,7 @@ export class JavaRenderer extends ConvenienceRenderer { protected readonly _converterKeywords: string[] = []; constructor( - targetLanguage: TargetLanguage, + targetLanguage: JavaTargetLanguage, renderContext: RenderContext, protected readonly _options: OptionValues ) { @@ -912,7 +910,7 @@ export class JavaRenderer extends ConvenienceRenderer { export class JacksonRenderer extends JavaRenderer { constructor( - targetLanguage: TargetLanguage, + targetLanguage: JavaTargetLanguage, renderContext: RenderContext, options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/JavaScript.ts b/packages/quicktype-core/src/language/JavaScript.ts index 304a6c775..7c7bf08f3 100644 --- a/packages/quicktype-core/src/language/JavaScript.ts +++ b/packages/quicktype-core/src/language/JavaScript.ts @@ -65,17 +65,15 @@ export type JavaScriptTypeAnnotations = { never: string; }; -export class JavaScriptTargetLanguage< - DisplayName extends string = "JavaScript", - Names extends readonly string[] = readonly ["javascript", "js", "jsx"], - Extension extends string = "js" -> extends TargetLanguage { - constructor( - displayName = "JavaScript" as DisplayName, - names = ["javascript", "js", "jsx"] as unknown as Names, - extension = "js" as Extension - ) { - super(displayName, names, extension); +export const javaScriptLanguageConfig = { + displayName: "JavaScript", + names: ["javascript", "js", "jsx"], + extension: "js" +} as const; + +export class JavaScriptTargetLanguage extends TargetLanguage { + constructor() { + super(javaScriptLanguageConfig); } protected getOptions(): Option[] { @@ -118,7 +116,7 @@ const identityNamingFunction = funPrefixNamer("properties", s => s); export class JavaScriptRenderer extends ConvenienceRenderer { constructor( - targetLanguage: TargetLanguage, + targetLanguage: JavaScriptTargetLanguage, renderContext: RenderContext, private readonly _jsOptions: OptionValues ) { diff --git a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts index 0921ddfe0..c16688b12 100644 --- a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts +++ b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts @@ -39,17 +39,15 @@ export const javaScriptPropTypesOptions = { ) }; -export class JavaScriptPropTypesTargetLanguage< - DisplayName extends string = "JavaScript PropTypes", - Names extends readonly string[] = readonly ["javascript-prop-types"], - Extension extends string = "js" -> extends TargetLanguage { - constructor( - displayName = "JavaScript PropTypes" as DisplayName, - names = ["javascript-prop-types"] as unknown as Names, - extension = "js" as Extension - ) { - super(displayName, names, extension); +export const javaScriptPropTypesLanguageConfig = { + displayName: "JavaScript PropTypes", + names: ["javascript-prop-types"], + extension: "js" +} as const; + +export class JavaScriptPropTypesTargetLanguage extends TargetLanguage { + constructor() { + super(javaScriptPropTypesLanguageConfig); } protected getOptions(): Option[] { @@ -72,7 +70,7 @@ const identityNamingFunction = funPrefixNamer("properties", s => s); export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { constructor( - targetLanguage: TargetLanguage, + targetLanguage: JavaScriptPropTypesTargetLanguage, renderContext: RenderContext, private readonly _jsOptions: OptionValues ) { diff --git a/packages/quicktype-core/src/language/Kotlin.ts b/packages/quicktype-core/src/language/Kotlin.ts index 4581ab961..45995146f 100644 --- a/packages/quicktype-core/src/language/Kotlin.ts +++ b/packages/quicktype-core/src/language/Kotlin.ts @@ -61,17 +61,15 @@ export const kotlinOptions = { packageName: new StringOption("package", "Package", "PACKAGE", "quicktype") }; -export class KotlinTargetLanguage< - DisplayName extends string = "Kotlin", - Names extends readonly string[] = readonly ["kotlin"], - Extension extends string = "kt" -> extends TargetLanguage { - constructor( - displayName = "Kotlin" as DisplayName, - names = ["kotlin"] as unknown as Names, - extension = "kt" as Extension - ) { - super(displayName, names, extension); +export const kotlinLanguageConfig = { + displayName: "Kotlin", + names: ["kotlin"], + extension: "kt" +} as const; + +export class KotlinTargetLanguage extends TargetLanguage { + constructor() { + super(kotlinLanguageConfig); } protected getOptions(): Option[] { @@ -200,7 +198,7 @@ function stringEscape(s: string): string { export class KotlinRenderer extends ConvenienceRenderer { constructor( - targetLanguage: TargetLanguage, + targetLanguage: KotlinTargetLanguage, renderContext: RenderContext, protected readonly _kotlinOptions: OptionValues ) { @@ -468,7 +466,7 @@ export class KotlinRenderer extends ConvenienceRenderer { export class KotlinKlaxonRenderer extends KotlinRenderer { constructor( - targetLanguage: TargetLanguage, + targetLanguage: KotlinTargetLanguage, renderContext: RenderContext, _kotlinOptions: OptionValues ) { @@ -746,7 +744,7 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { export class KotlinJacksonRenderer extends KotlinRenderer { constructor( - targetLanguage: TargetLanguage, + targetLanguage: KotlinTargetLanguage, renderContext: RenderContext, _kotlinOptions: OptionValues ) { @@ -1016,7 +1014,7 @@ private fun ObjectMapper.convert(k: kotlin.reflect.KClass<*>, fromJson: (Jso */ export class KotlinXRenderer extends KotlinRenderer { constructor( - targetLanguage: TargetLanguage, + targetLanguage: KotlinTargetLanguage, renderContext: RenderContext, _kotlinOptions: OptionValues ) { diff --git a/packages/quicktype-core/src/language/Objective-C.ts b/packages/quicktype-core/src/language/Objective-C.ts index 3d02a574a..35709a08a 100644 --- a/packages/quicktype-core/src/language/Objective-C.ts +++ b/packages/quicktype-core/src/language/Objective-C.ts @@ -43,17 +43,15 @@ export const objcOptions = { extraComments: new BooleanOption("extra-comments", "Extra comments", false) }; -export class ObjectiveCTargetLanguage< - DisplayName extends string = "Objective-C", - Names extends readonly string[] = readonly ["objc", "objective-c", "objectivec"], - Extension extends string = "m" -> extends TargetLanguage { - constructor( - displayName = "Objective-C" as DisplayName, - names = ["objc", "objective-c", "objectivec"] as unknown as Names, - extension = "m" as Extension - ) { - super(displayName, names, extension); +export const objectiveCLanguageConfig = { + displayName: "Objective-C", + names: ["objc", "objective-c", "objectivec"], + extension: "m" +} as const; + +export class ObjectiveCTargetLanguage extends TargetLanguage { + constructor() { + super(objectiveCLanguageConfig); } protected getOptions(): Option[] { @@ -233,7 +231,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { private readonly _classPrefix: string; constructor( - targetLanguage: TargetLanguage, + targetLanguage: ObjectiveCTargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/Php.ts b/packages/quicktype-core/src/language/Php.ts index f5d12a7d9..25f0e05b9 100644 --- a/packages/quicktype-core/src/language/Php.ts +++ b/packages/quicktype-core/src/language/Php.ts @@ -34,17 +34,15 @@ export const phpOptions = { acronymStyle: acronymOption(AcronymStyleOptions.Pascal) }; -export class PhpTargetLanguage< - DisplayName extends string = "PHP", - Names extends readonly string[] = readonly ["php"], - Extension extends string = "php" -> extends TargetLanguage { - constructor( - displayName = "PHP" as DisplayName, - names = ["php"] as unknown as Names, - extension = "php" as Extension - ) { - super(displayName, names, extension); +export const phpLanguageConfig = { + displayName: "PHP", + names: ["php"], + extension: "php" +} as const; + +export class PhpTargetLanguage extends TargetLanguage { + constructor() { + super(phpLanguageConfig); } protected getOptions(): Option[] { @@ -118,7 +116,7 @@ export class PhpRenderer extends ConvenienceRenderer { protected readonly _converterKeywords: string[] = []; constructor( - targetLanguage: TargetLanguage, + targetLanguage: PhpTargetLanguage, renderContext: RenderContext, protected readonly _options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/Pike.ts b/packages/quicktype-core/src/language/Pike.ts index afc510c8c..abea9368d 100644 --- a/packages/quicktype-core/src/language/Pike.ts +++ b/packages/quicktype-core/src/language/Pike.ts @@ -70,17 +70,15 @@ const enumNamingFunction = funPrefixNamer("enumNamer", makeNameStyle("upper-unde const namingFunction = funPrefixNamer("genericNamer", makeNameStyle("underscore", legalizeName)); const namedTypeNamingFunction = funPrefixNamer("typeNamer", makeNameStyle("pascal", legalizeName)); -export class PikeTargetLanguage< - DisplayName extends string = "Pike", - Names extends readonly string[] = readonly ["pike", "pikelang"], - Extension extends string = "pmod" -> extends TargetLanguage { - constructor( - displayName = "Pike" as DisplayName, - names = ["pike", "pikelang"] as unknown as Names, - extension = "pmod" as Extension - ) { - super(displayName, names, extension); +export const pikeLanguageConfig = { + displayName: "Pike", + names: ["pike", "pikelang"], + extension: "pmod" +} as const; + +export class PikeTargetLanguage extends TargetLanguage { + constructor() { + super(pikeLanguageConfig); } protected getOptions(): Option[] { return []; diff --git a/packages/quicktype-core/src/language/Python.ts b/packages/quicktype-core/src/language/Python.ts index 0e91e8f79..618992df8 100644 --- a/packages/quicktype-core/src/language/Python.ts +++ b/packages/quicktype-core/src/language/Python.ts @@ -129,17 +129,11 @@ export const pythonOptions = { nicePropertyNames: new BooleanOption("nice-property-names", "Transform property names to be Pythonic", true) }; -export class PythonTargetLanguage< - DisplayName extends string = "Python", - Names extends readonly string[] = readonly ["python", "py"], - Extension extends string = "py" -> extends TargetLanguage { - constructor( - displayName = "Python" as DisplayName, - names = ["python", "py"] as unknown as Names, - extension = "py" as Extension - ) { - super(displayName, names, extension); +export const pythonLanguageConfig = { displayName: "Python", names: ["python", "py"], extension: "py" } as const; + +export class PythonTargetLanguage extends TargetLanguage { + constructor() { + super(pythonLanguageConfig); } protected getOptions(): Option[] { @@ -250,7 +244,7 @@ export class PythonRenderer extends ConvenienceRenderer { private readonly declaredTypes: Set = new Set(); constructor( - targetLanguage: TargetLanguage, + targetLanguage: PythonTargetLanguage, renderContext: RenderContext, protected readonly pyOptions: OptionValues ) { diff --git a/packages/quicktype-core/src/language/Rust.ts b/packages/quicktype-core/src/language/Rust.ts index 79b3d4bb9..e44fa26cb 100644 --- a/packages/quicktype-core/src/language/Rust.ts +++ b/packages/quicktype-core/src/language/Rust.ts @@ -111,17 +111,15 @@ const namingStyles: Record = { } }; -export class RustTargetLanguage< - DisplayName extends string = "Rust", - Names extends readonly string[] = readonly ["rust", "rs", "rustlang"], - Extension extends string = "rs" -> extends TargetLanguage { - constructor( - displayName = "Rust" as DisplayName, - names = ["rust", "rs", "rustlang"] as unknown as Names, - extension = "rs" as Extension - ) { - super(displayName, names, extension); +export const rustLanguageConfig = { + displayName: "Rust", + names: ["rust", "rs", "rustlang"], + extension: "rs" +} as const; + +export class RustTargetLanguage extends TargetLanguage { + constructor() { + super(rustLanguageConfig); } protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): RustRenderer { @@ -271,7 +269,7 @@ const rustStringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, st export class RustRenderer extends ConvenienceRenderer { constructor( - targetLanguage: TargetLanguage, + targetLanguage: RustTargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/Scala3.ts b/packages/quicktype-core/src/language/Scala3.ts index fc2053b00..48b5602be 100644 --- a/packages/quicktype-core/src/language/Scala3.ts +++ b/packages/quicktype-core/src/language/Scala3.ts @@ -189,7 +189,7 @@ const lowerNamingFunction = funPrefixNamer("lower", s => scalaNameStyle(false, s export class Scala3Renderer extends ConvenienceRenderer { constructor( - targetLanguage: TargetLanguage, + targetLanguage: Scala3TargetLanguage, renderContext: RenderContext, protected readonly _scalaOptions: OptionValues ) { @@ -245,10 +245,10 @@ export class Scala3Renderer extends ConvenienceRenderer { delimiter === "curly" ? ["{", "}"] : delimiter === "paren" - ? ["(", ")"] - : delimiter === "none" - ? ["", ""] - : ["{", "})"]; + ? ["(", ")"] + : delimiter === "none" + ? ["", ""] + : ["{", "})"]; this.emitLine(line, " ", open); this.indent(f); this.emitLine(close); @@ -670,17 +670,15 @@ export class CirceRenderer extends Scala3Renderer { } } -export class Scala3TargetLanguage< - DisplayName extends string = "Scala3", - Names extends readonly string[] = readonly ["scala3"], - Extension extends string = "scala" -> extends TargetLanguage { - constructor( - displayName = "Scala3" as DisplayName, - names = ["scala3"] as unknown as Names, - extension = "scala" as Extension - ) { - super(displayName, names, extension); +export const scala3LanguageConfig = { + displayName: "Scala3", + names: ["scala3"], + extension: "scala" +} as const; + +export class Scala3TargetLanguage extends TargetLanguage { + constructor() { + super(scala3LanguageConfig); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/Smithy4s.ts b/packages/quicktype-core/src/language/Smithy4s.ts index 70ba91158..d2f38da13 100644 --- a/packages/quicktype-core/src/language/Smithy4s.ts +++ b/packages/quicktype-core/src/language/Smithy4s.ts @@ -149,7 +149,7 @@ const lowerNamingFunction = funPrefixNamer("lower", s => scalaNameStyle(false, s export class Smithy4sRenderer extends ConvenienceRenderer { constructor( - targetLanguage: TargetLanguage, + targetLanguage: SmithyTargetLanguage, renderContext: RenderContext, protected readonly _scalaOptions: OptionValues ) { @@ -205,10 +205,10 @@ export class Smithy4sRenderer extends ConvenienceRenderer { delimiter === "curly" ? ["{", "}"] : delimiter === "paren" - ? ["(", ")"] - : delimiter === "none" - ? ["", ""] - : ["{", "})"]; + ? ["(", ")"] + : delimiter === "none" + ? ["", ""] + : ["{", "})"]; this.emitLine(line, " ", open); this.indent(f); this.emitLine(close); @@ -510,17 +510,15 @@ export class Smithy4sRenderer extends ConvenienceRenderer { } } -export class SmithyTargetLanguage< - DisplayName extends string = "Smithy", - Names extends readonly string[] = readonly ["Smithy"], - Extension extends string = "smithy" -> extends TargetLanguage { - constructor( - displayName = "Smithy" as DisplayName, - names = ["Smithy"] as unknown as Names, - extension = "smithy" as Extension - ) { - super(displayName, names, extension); +export const smithyLanguageConfig = { + displayName: "Smithy", + names: ["Smithy"], + extension: "smithy" +} as const; + +export class SmithyTargetLanguage extends TargetLanguage { + constructor() { + super(smithyLanguageConfig); } protected getOptions(): Option[] { diff --git a/packages/quicktype-core/src/language/Swift.ts b/packages/quicktype-core/src/language/Swift.ts index 673892c52..e8800feb5 100644 --- a/packages/quicktype-core/src/language/Swift.ts +++ b/packages/quicktype-core/src/language/Swift.ts @@ -137,17 +137,15 @@ export interface SwiftProperty { position: ForEachPosition; } -export class SwiftTargetLanguage< - DisplayName extends string = "Swift", - Names extends readonly string[] = readonly ["swift", "swift4"], - Extension extends string = "swift" -> extends TargetLanguage { - constructor( - displayName = "Swift" as DisplayName, - names = ["swift", "swift4"] as unknown as Names, - extension = "swift" as Extension - ) { - super(displayName, names, extension); +export const swiftLanguageConfig = { + displayName: "Swift", + names: ["swift", "swift4"], + extension: "swift" +} as const; + +export class SwiftTargetLanguage extends TargetLanguage { + constructor() { + super(swiftLanguageConfig); } protected getOptions(): Option[] { @@ -340,7 +338,7 @@ export class SwiftRenderer extends ConvenienceRenderer { private _needNull = false; constructor( - targetLanguage: TargetLanguage, + targetLanguage: SwiftTargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts index b9dacd95c..8a6e7feac 100644 --- a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts +++ b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts @@ -25,17 +25,15 @@ export const typeScriptEffectSchemaOptions = { justSchema: new BooleanOption("just-schema", "Schema only", false) }; -export class TypeScriptEffectSchemaTargetLanguage< - DisplayName extends string = "TypeScript Effect Schema", - Names extends readonly string[] = readonly ["typescript-effect-schema"], - Extension extends string = "ts" -> extends TargetLanguage { - constructor( - displayName = "TypeScript Effect Schema" as DisplayName, - names = ["typescript-effect-schema"] as unknown as Names, - extension = "ts" as Extension - ) { - super(displayName, names, extension); +export const typeScriptEffectSchemaLanguageConfig = { + displayName: "TypeScript Effect Schema", + names: ["typescript-effect-schema"], + extension: "ts" +} as const; + +export class TypeScriptEffectSchemaTargetLanguage extends TargetLanguage { + constructor() { + super(typeScriptEffectSchemaLanguageConfig); } protected getOptions(): Option[] { @@ -56,7 +54,7 @@ export class TypeScriptEffectSchemaTargetLanguage< export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { constructor( - targetLanguage: TargetLanguage, + targetLanguage: TypeScriptEffectSchemaTargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/TypeScriptZod.ts b/packages/quicktype-core/src/language/TypeScriptZod.ts index 3c73fed5e..44841c73a 100644 --- a/packages/quicktype-core/src/language/TypeScriptZod.ts +++ b/packages/quicktype-core/src/language/TypeScriptZod.ts @@ -37,17 +37,15 @@ export const typeScriptZodOptions = { justSchema: new BooleanOption("just-schema", "Schema only", false) }; -export class TypeScriptZodTargetLanguage< - DisplayName extends string = "TypeScript Zod", - Names extends readonly string[] = readonly ["typescript-zod"], - Extension extends string = "ts" -> extends TargetLanguage { - constructor( - displayName = "TypeScript Zod" as DisplayName, - names = ["typescript-zod"] as unknown as Names, - extension = "ts" as Extension - ) { - super(displayName, names, extension); +export const typeScriptZodLanguageConfig = { + displayName: "TypeScript Zod", + names: ["typescript-zod"], + extension: "ts" +} as const; + +export class TypeScriptZodTargetLanguage extends TargetLanguage { + constructor() { + super(typeScriptZodLanguageConfig); } protected getOptions(): Option[] { @@ -79,7 +77,7 @@ export class TypeScriptZodTargetLanguage< export class TypeScriptZodRenderer extends ConvenienceRenderer { constructor( - targetLanguage: TargetLanguage, + targetLanguage: TypeScriptZodTargetLanguage, renderContext: RenderContext, protected readonly _options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/ruby/index.ts b/packages/quicktype-core/src/language/ruby/index.ts index 9e4fab636..57ac5d8c3 100644 --- a/packages/quicktype-core/src/language/ruby/index.ts +++ b/packages/quicktype-core/src/language/ruby/index.ts @@ -51,17 +51,15 @@ export const rubyOptions = { namespace: new StringOption("namespace", "Specify a wrapping Namespace", "NAME", "", "secondary") }; -export class RubyTargetLanguage< - DisplayName extends string = "Ruby", - Names extends readonly string[] = readonly ["ruby"], - Extension extends string = "rb" -> extends TargetLanguage { - constructor( - displayName = "Ruby" as DisplayName, - names = ["ruby"] as unknown as Names, - extension = "rb" as Extension - ) { - super(displayName, names, extension); +export const rubyLanguageConfig = { + displayName: "Ruby", + names: ["ruby"], + extension: "rb" +} as const; + +export class RubyTargetLanguage extends TargetLanguage { + constructor() { + super(rubyLanguageConfig); } protected getOptions(): Option[] { @@ -123,7 +121,7 @@ function memberNameStyle(original: string): string { export class RubyRenderer extends ConvenienceRenderer { constructor( - targetLanguage: TargetLanguage, + targetLanguage: RubyTargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { From 410ed42ae68ae60e5de5590222460aef4880f564 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 20 Apr 2024 16:42:31 -0700 Subject: [PATCH 59/94] flatten all languages to extend from TargetLanguage --- packages/quicktype-core/src/TargetLanguage.ts | 2 +- packages/quicktype-core/src/language/CJSON.ts | 2 +- .../quicktype-core/src/language/CPlusPlus.ts | 2 +- .../quicktype-core/src/language/CSharp.ts | 6 +- .../quicktype-core/src/language/Crystal.ts | 2 +- packages/quicktype-core/src/language/Dart.ts | 2 +- .../quicktype-core/src/language/Elixir.ts | 2 +- packages/quicktype-core/src/language/Elm.ts | 2 +- .../quicktype-core/src/language/Golang.ts | 2 +- .../quicktype-core/src/language/Haskell.ts | 2 +- packages/quicktype-core/src/language/Java.ts | 4 +- .../quicktype-core/src/language/JavaScript.ts | 2 +- .../src/language/JavaScriptPropTypes.ts | 2 +- .../quicktype-core/src/language/Kotlin.ts | 8 +- .../src/language/Objective-C.ts | 2 +- packages/quicktype-core/src/language/Php.ts | 2 +- .../quicktype-core/src/language/Python.ts | 2 +- packages/quicktype-core/src/language/Rust.ts | 2 +- .../quicktype-core/src/language/Scala3.ts | 2 +- .../quicktype-core/src/language/Smithy4s.ts | 2 +- packages/quicktype-core/src/language/Swift.ts | 2 +- .../src/language/TypeScriptEffectSchema.ts | 2 +- .../src/language/TypeScriptFlow.ts | 115 +++++++++++------- .../src/language/TypeScriptZod.ts | 2 +- .../quicktype-core/src/language/ruby/index.ts | 2 +- 25 files changed, 102 insertions(+), 73 deletions(-) diff --git a/packages/quicktype-core/src/TargetLanguage.ts b/packages/quicktype-core/src/TargetLanguage.ts index bdd0952bf..3a5c9a9fa 100644 --- a/packages/quicktype-core/src/TargetLanguage.ts +++ b/packages/quicktype-core/src/TargetLanguage.ts @@ -19,7 +19,7 @@ export type LanguageConfig = { readonly extension: string; }; -export abstract class TargetLanguage { +export abstract class TargetLanguage { displayName: Config["displayName"]; names: Config["names"]; extension: Config["extension"]; diff --git a/packages/quicktype-core/src/language/CJSON.ts b/packages/quicktype-core/src/language/CJSON.ts index 6e69e9ed1..3addcc592 100644 --- a/packages/quicktype-core/src/language/CJSON.ts +++ b/packages/quicktype-core/src/language/CJSON.ts @@ -377,7 +377,7 @@ export class CJSONRenderer extends ConvenienceRenderer { * @param _options: renderer options */ constructor( - targetLanguage: CJSONTargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/CPlusPlus.ts b/packages/quicktype-core/src/language/CPlusPlus.ts index 96914a57d..879994a67 100644 --- a/packages/quicktype-core/src/language/CPlusPlus.ts +++ b/packages/quicktype-core/src/language/CPlusPlus.ts @@ -483,7 +483,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { protected readonly enumeratorNamingStyle: NamingStyle; constructor( - targetLanguage: CPlusPlusTargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/CSharp.ts b/packages/quicktype-core/src/language/CSharp.ts index e180ec705..2ffed5eea 100644 --- a/packages/quicktype-core/src/language/CSharp.ts +++ b/packages/quicktype-core/src/language/CSharp.ts @@ -418,7 +418,7 @@ function isValueType(t: Type): boolean { export class CSharpRenderer extends ConvenienceRenderer { constructor( - targetLanguage: CSharpTargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, private readonly _csOptions: OptionValues ) { @@ -787,7 +787,7 @@ export class NewtonsoftCSharpRenderer extends CSharpRenderer { private readonly _needNamespaces: boolean; constructor( - targetLanguage: CSharpTargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { @@ -1514,7 +1514,7 @@ export class SystemTextJsonCSharpRenderer extends CSharpRenderer { private readonly _needNamespaces: boolean; constructor( - targetLanguage: CSharpTargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/Crystal.ts b/packages/quicktype-core/src/language/Crystal.ts index 9b10b1de1..8e06f566d 100644 --- a/packages/quicktype-core/src/language/Crystal.ts +++ b/packages/quicktype-core/src/language/Crystal.ts @@ -234,7 +234,7 @@ function standardUnicodeCrystalEscape(codePoint: number): string { const crystalStringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, standardUnicodeCrystalEscape)); export class CrystalRenderer extends ConvenienceRenderer { - constructor(targetLanguage: CrystalTargetLanguage, renderContext: RenderContext) { + constructor(targetLanguage: TargetLanguage, renderContext: RenderContext) { super(targetLanguage, renderContext); } diff --git a/packages/quicktype-core/src/language/Dart.ts b/packages/quicktype-core/src/language/Dart.ts index 23a86ca90..1cf37c731 100644 --- a/packages/quicktype-core/src/language/Dart.ts +++ b/packages/quicktype-core/src/language/Dart.ts @@ -231,7 +231,7 @@ export class DartRenderer extends ConvenienceRenderer { private readonly _enumValues = new Map(); constructor( - targetLanguage: DartTargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/Elixir.ts b/packages/quicktype-core/src/language/Elixir.ts index 2d9dd6012..05c0f4ea3 100644 --- a/packages/quicktype-core/src/language/Elixir.ts +++ b/packages/quicktype-core/src/language/Elixir.ts @@ -216,7 +216,7 @@ function memberNameStyle(original: string): string { export class ElixirRenderer extends ConvenienceRenderer { constructor( - targetLanguage: ElixirTargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/Elm.ts b/packages/quicktype-core/src/language/Elm.ts index 232e0028d..c67facf04 100644 --- a/packages/quicktype-core/src/language/Elm.ts +++ b/packages/quicktype-core/src/language/Elm.ts @@ -156,7 +156,7 @@ export class ElmRenderer extends ConvenienceRenderer { private readonly _namedTypeDependents = new Map(); constructor( - targetLanguage: ElmTargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/Golang.ts b/packages/quicktype-core/src/language/Golang.ts index 3b379b829..0dd7f4213 100644 --- a/packages/quicktype-core/src/language/Golang.ts +++ b/packages/quicktype-core/src/language/Golang.ts @@ -117,7 +117,7 @@ export class GoRenderer extends ConvenienceRenderer { private _currentFilename: string | undefined; constructor( - targetLanguage: GoTargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/Haskell.ts b/packages/quicktype-core/src/language/Haskell.ts index e05ec8cff..3f18039bc 100644 --- a/packages/quicktype-core/src/language/Haskell.ts +++ b/packages/quicktype-core/src/language/Haskell.ts @@ -136,7 +136,7 @@ const lowerNamingFunction = funPrefixNamer("lower", n => haskellNameStyle(n, fal export class HaskellRenderer extends ConvenienceRenderer { constructor( - targetLanguage: HaskellTargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/Java.ts b/packages/quicktype-core/src/language/Java.ts index cb3d9efbc..8ce7b3fd3 100644 --- a/packages/quicktype-core/src/language/Java.ts +++ b/packages/quicktype-core/src/language/Java.ts @@ -441,7 +441,7 @@ export class JavaRenderer extends ConvenienceRenderer { protected readonly _converterKeywords: string[] = []; constructor( - targetLanguage: JavaTargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, protected readonly _options: OptionValues ) { @@ -910,7 +910,7 @@ export class JavaRenderer extends ConvenienceRenderer { export class JacksonRenderer extends JavaRenderer { constructor( - targetLanguage: JavaTargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/JavaScript.ts b/packages/quicktype-core/src/language/JavaScript.ts index 7c7bf08f3..176eddc0e 100644 --- a/packages/quicktype-core/src/language/JavaScript.ts +++ b/packages/quicktype-core/src/language/JavaScript.ts @@ -116,7 +116,7 @@ const identityNamingFunction = funPrefixNamer("properties", s => s); export class JavaScriptRenderer extends ConvenienceRenderer { constructor( - targetLanguage: JavaScriptTargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, private readonly _jsOptions: OptionValues ) { diff --git a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts index c16688b12..30a7efca2 100644 --- a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts +++ b/packages/quicktype-core/src/language/JavaScriptPropTypes.ts @@ -70,7 +70,7 @@ const identityNamingFunction = funPrefixNamer("properties", s => s); export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { constructor( - targetLanguage: JavaScriptPropTypesTargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, private readonly _jsOptions: OptionValues ) { diff --git a/packages/quicktype-core/src/language/Kotlin.ts b/packages/quicktype-core/src/language/Kotlin.ts index 45995146f..d2557280c 100644 --- a/packages/quicktype-core/src/language/Kotlin.ts +++ b/packages/quicktype-core/src/language/Kotlin.ts @@ -198,7 +198,7 @@ function stringEscape(s: string): string { export class KotlinRenderer extends ConvenienceRenderer { constructor( - targetLanguage: KotlinTargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, protected readonly _kotlinOptions: OptionValues ) { @@ -466,7 +466,7 @@ export class KotlinRenderer extends ConvenienceRenderer { export class KotlinKlaxonRenderer extends KotlinRenderer { constructor( - targetLanguage: KotlinTargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, _kotlinOptions: OptionValues ) { @@ -744,7 +744,7 @@ export class KotlinKlaxonRenderer extends KotlinRenderer { export class KotlinJacksonRenderer extends KotlinRenderer { constructor( - targetLanguage: KotlinTargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, _kotlinOptions: OptionValues ) { @@ -1014,7 +1014,7 @@ private fun ObjectMapper.convert(k: kotlin.reflect.KClass<*>, fromJson: (Jso */ export class KotlinXRenderer extends KotlinRenderer { constructor( - targetLanguage: KotlinTargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, _kotlinOptions: OptionValues ) { diff --git a/packages/quicktype-core/src/language/Objective-C.ts b/packages/quicktype-core/src/language/Objective-C.ts index 35709a08a..da948ad3a 100644 --- a/packages/quicktype-core/src/language/Objective-C.ts +++ b/packages/quicktype-core/src/language/Objective-C.ts @@ -231,7 +231,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { private readonly _classPrefix: string; constructor( - targetLanguage: ObjectiveCTargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/Php.ts b/packages/quicktype-core/src/language/Php.ts index 25f0e05b9..f1b7b885d 100644 --- a/packages/quicktype-core/src/language/Php.ts +++ b/packages/quicktype-core/src/language/Php.ts @@ -116,7 +116,7 @@ export class PhpRenderer extends ConvenienceRenderer { protected readonly _converterKeywords: string[] = []; constructor( - targetLanguage: PhpTargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, protected readonly _options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/Python.ts b/packages/quicktype-core/src/language/Python.ts index 618992df8..67796ce93 100644 --- a/packages/quicktype-core/src/language/Python.ts +++ b/packages/quicktype-core/src/language/Python.ts @@ -244,7 +244,7 @@ export class PythonRenderer extends ConvenienceRenderer { private readonly declaredTypes: Set = new Set(); constructor( - targetLanguage: PythonTargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, protected readonly pyOptions: OptionValues ) { diff --git a/packages/quicktype-core/src/language/Rust.ts b/packages/quicktype-core/src/language/Rust.ts index e44fa26cb..d0c0a7162 100644 --- a/packages/quicktype-core/src/language/Rust.ts +++ b/packages/quicktype-core/src/language/Rust.ts @@ -269,7 +269,7 @@ const rustStringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, st export class RustRenderer extends ConvenienceRenderer { constructor( - targetLanguage: RustTargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/Scala3.ts b/packages/quicktype-core/src/language/Scala3.ts index 48b5602be..a7ac41697 100644 --- a/packages/quicktype-core/src/language/Scala3.ts +++ b/packages/quicktype-core/src/language/Scala3.ts @@ -189,7 +189,7 @@ const lowerNamingFunction = funPrefixNamer("lower", s => scalaNameStyle(false, s export class Scala3Renderer extends ConvenienceRenderer { constructor( - targetLanguage: Scala3TargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, protected readonly _scalaOptions: OptionValues ) { diff --git a/packages/quicktype-core/src/language/Smithy4s.ts b/packages/quicktype-core/src/language/Smithy4s.ts index d2f38da13..5dc62674b 100644 --- a/packages/quicktype-core/src/language/Smithy4s.ts +++ b/packages/quicktype-core/src/language/Smithy4s.ts @@ -149,7 +149,7 @@ const lowerNamingFunction = funPrefixNamer("lower", s => scalaNameStyle(false, s export class Smithy4sRenderer extends ConvenienceRenderer { constructor( - targetLanguage: SmithyTargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, protected readonly _scalaOptions: OptionValues ) { diff --git a/packages/quicktype-core/src/language/Swift.ts b/packages/quicktype-core/src/language/Swift.ts index e8800feb5..bed8b3fad 100644 --- a/packages/quicktype-core/src/language/Swift.ts +++ b/packages/quicktype-core/src/language/Swift.ts @@ -338,7 +338,7 @@ export class SwiftRenderer extends ConvenienceRenderer { private _needNull = false; constructor( - targetLanguage: SwiftTargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { diff --git a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts index 8a6e7feac..d8ca6789e 100644 --- a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts +++ b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts @@ -54,7 +54,7 @@ export class TypeScriptEffectSchemaTargetLanguage extends TargetLanguage ) { diff --git a/packages/quicktype-core/src/language/TypeScriptFlow.ts b/packages/quicktype-core/src/language/TypeScriptFlow.ts index 03d63d197..92f7a4e7a 100644 --- a/packages/quicktype-core/src/language/TypeScriptFlow.ts +++ b/packages/quicktype-core/src/language/TypeScriptFlow.ts @@ -1,21 +1,24 @@ -import { Type, ArrayType, UnionType, ClassType, EnumType } from "../Type"; +import { + Type, + ArrayType, + UnionType, + ClassType, + EnumType, + PrimitiveStringTypeKind, + TransformedStringTypeKind +} from "../Type"; import { matchType, nullableFromUnion, isNamedType } from "../TypeUtils"; import { utf16StringEscape, camelCase } from "../support/Strings"; import { Sourcelike, modifySource, MultiWord, singleWord, parenIfNeeded, multiWord } from "../Source"; import { Name, Namer, funPrefixNamer } from "../Naming"; import { BooleanOption, Option, OptionValues, getOptionValues } from "../RendererOptions"; -import { - javaScriptOptions, - JavaScriptTargetLanguage, - JavaScriptRenderer, - JavaScriptTypeAnnotations, - legalizeName -} from "./JavaScript"; +import { javaScriptOptions, JavaScriptRenderer, JavaScriptTypeAnnotations, legalizeName } from "./JavaScript"; import { defined, panic } from "../support/Support"; import { TargetLanguage } from "../TargetLanguage"; import { RenderContext } from "../Renderer"; import { isES3IdentifierStart } from "./JavaScriptUnicodeMaps"; +import { StringTypeMapping } from "../TypeBuilder"; export const tsFlowOptions = Object.assign({}, javaScriptOptions, { justTypes: new BooleanOption("just-types", "Interfaces only", false), @@ -40,13 +43,15 @@ const tsFlowTypeAnnotations = { boolean: ": boolean" }; -export abstract class TypeScriptFlowBaseTargetLanguage< - DisplayName extends string, - Names extends readonly string[], - Extension extends string -> extends JavaScriptTargetLanguage { - protected constructor(displayName: DisplayName, names: Names, extension: Extension) { - super(displayName, names, extension); +export const typeScriptLanguageConfig = { + displayName: "TypeScript", + names: ["typescript", "ts", "tsx"], + extension: "ts" +} as const; + +export class TypeScriptTargetLanguage extends TargetLanguage { + constructor() { + super(typeScriptLanguageConfig); } protected getOptions(): Option[] { @@ -66,27 +71,20 @@ export abstract class TypeScriptFlowBaseTargetLanguage< ]; } + get stringTypeMapping(): StringTypeMapping { + const mapping: Map = new Map(); + const dateTimeType = "date-time"; + mapping.set("date", dateTimeType); + mapping.set("date-time", dateTimeType); + return mapping; + } + get supportsOptionalClassProperties(): boolean { return true; } - protected abstract makeRenderer( - renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } - ): JavaScriptRenderer; -} - -export class TypeScriptTargetLanguage< - DisplayName extends string = "TypeScript", - Names extends readonly string[] = readonly ["typescript", "ts", "tsx"], - Extension extends string = "ts" -> extends TypeScriptFlowBaseTargetLanguage { - constructor( - displayName = "TypeScript" as DisplayName, - names = ["typescript", "ts", "tsx"] as unknown as Names, - extension = "ts" as Extension - ) { - super(displayName, names, extension); + get supportsFullObjectType(): boolean { + return true; } protected makeRenderer( @@ -355,17 +353,48 @@ export class TypeScriptRenderer extends TypeScriptFlowBaseRenderer { } } -export class FlowTargetLanguage< - DisplayName extends string = "Flow", - Names extends readonly string[] = readonly ["flow"], - Extension extends string = "js" -> extends TypeScriptFlowBaseTargetLanguage { - constructor( - displayName = "Flow" as DisplayName, - names = ["flow"] as unknown as Names, - extension = "js" as Extension - ) { - super(displayName, names, extension); +export const flowLanguageConfig = { + displayName: "Flow", + names: ["flow"], + extension: "js" +} as const; + +export class FlowTargetLanguage extends TargetLanguage { + constructor() { + super(flowLanguageConfig); + } + + protected getOptions(): Option[] { + return [ + tsFlowOptions.justTypes, + tsFlowOptions.nicePropertyNames, + tsFlowOptions.declareUnions, + tsFlowOptions.runtimeTypecheck, + tsFlowOptions.runtimeTypecheckIgnoreUnknownProperties, + tsFlowOptions.acronymStyle, + tsFlowOptions.converters, + tsFlowOptions.rawType, + tsFlowOptions.preferUnions, + tsFlowOptions.preferTypes, + tsFlowOptions.preferConstValues, + tsFlowOptions.readonly + ]; + } + + get stringTypeMapping(): StringTypeMapping { + const mapping: Map = new Map(); + const dateTimeType = "date-time"; + mapping.set("date", dateTimeType); + mapping.set("date-time", dateTimeType); + return mapping; + } + + get supportsOptionalClassProperties(): boolean { + return true; + } + + get supportsFullObjectType(): boolean { + return true; } protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): FlowRenderer { diff --git a/packages/quicktype-core/src/language/TypeScriptZod.ts b/packages/quicktype-core/src/language/TypeScriptZod.ts index 44841c73a..6717e95c3 100644 --- a/packages/quicktype-core/src/language/TypeScriptZod.ts +++ b/packages/quicktype-core/src/language/TypeScriptZod.ts @@ -77,7 +77,7 @@ export class TypeScriptZodTargetLanguage extends TargetLanguage ) { diff --git a/packages/quicktype-core/src/language/ruby/index.ts b/packages/quicktype-core/src/language/ruby/index.ts index 57ac5d8c3..0716736b8 100644 --- a/packages/quicktype-core/src/language/ruby/index.ts +++ b/packages/quicktype-core/src/language/ruby/index.ts @@ -121,7 +121,7 @@ function memberNameStyle(original: string): string { export class RubyRenderer extends ConvenienceRenderer { constructor( - targetLanguage: RubyTargetLanguage, + targetLanguage: TargetLanguage, renderContext: RenderContext, private readonly _options: OptionValues ) { From 8e6fc4f9aee06f362ac75e4b4a37894fa169f923 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Mon, 29 Apr 2024 20:37:58 -0700 Subject: [PATCH 60/94] fix new lint errors --- packages/quicktype-core/src/input/io/NodeIO.ts | 2 ++ packages/quicktype-core/src/language/TypeScriptFlow.ts | 1 + 2 files changed, 3 insertions(+) diff --git a/packages/quicktype-core/src/input/io/NodeIO.ts b/packages/quicktype-core/src/input/io/NodeIO.ts index d23363b65..f8cf94b44 100644 --- a/packages/quicktype-core/src/input/io/NodeIO.ts +++ b/packages/quicktype-core/src/input/io/NodeIO.ts @@ -12,6 +12,8 @@ import { messageError, panic } from "../../index"; import { getStream } from "./get-stream"; // Only use cross-fetch in CI +// FIXME: type global +// eslint-disable-next-line @typescript-eslint/no-explicit-any const fetch = process.env.CI ? _fetch : (global as any).fetch ?? _fetch; interface HttpHeaders { diff --git a/packages/quicktype-core/src/language/TypeScriptFlow.ts b/packages/quicktype-core/src/language/TypeScriptFlow.ts index 74b527568..202b95b4e 100644 --- a/packages/quicktype-core/src/language/TypeScriptFlow.ts +++ b/packages/quicktype-core/src/language/TypeScriptFlow.ts @@ -212,6 +212,7 @@ export abstract class TypeScriptFlowBaseRenderer extends JavaScriptRenderer { if (!t.isPrimitive()) { return; } + this.ensureBlankLine(); this.emitDescription(this.descriptionForType(t)); this.emitLine("type ", name, " = ", this.sourceFor(t).source, ";"); From f16e6ad9323b4501ae0ff70e0ae10e0e1d9c7ba5 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sun, 5 May 2024 16:01:00 -0700 Subject: [PATCH 61/94] Merge branch 'refactor/imports/languages' --- .../quicktype-core/src/ConvenienceRenderer.ts | 2 +- packages/quicktype-core/src/Naming.ts | 2 +- packages/quicktype-core/src/index.ts | 33 +- packages/quicktype-core/src/language/All.ts | 40 +- .../{CJSON.ts => CJSON/CJSONRenderer.ts} | 386 +-- .../src/language/CJSON/constants.ts | 123 + .../src/language/CJSON/index.ts | 2 + .../src/language/CJSON/language.ts | 169 ++ .../src/language/CJSON/utils.ts | 57 + .../CPlusPlusRenderer.ts} | 504 +--- .../src/language/CPlusPlus/constants.ts | 103 + .../src/language/CPlusPlus/index.ts | 2 + .../src/language/CPlusPlus/language.ts | 129 + .../src/language/CPlusPlus/utils.ts | 208 ++ .../quicktype-core/src/language/CSharp.ts | 2498 ----------------- .../src/language/CSharp/CSharpRenderer.ts | 390 +++ .../CSharp/NewtonSoftCSharpRenderer.ts | 803 ++++++ .../CSharp/SystemTextJsonCSharpRenderer.ts | 982 +++++++ .../src/language/CSharp/constants.ts | 79 + .../src/language/CSharp/index.ts | 4 + .../src/language/CSharp/language.ts | 175 ++ .../src/language/CSharp/utils.ts | 147 + .../CrystalRenderer.ts} | 244 +- .../src/language/Crystal/constants.ts | 138 + .../src/language/Crystal/index.ts | 2 + .../src/language/Crystal/language.ts | 24 + .../src/language/Crystal/utils.ts | 65 + .../{Dart.ts => Dart/DartRenderer.ts} | 246 +- .../src/language/Dart/constants.ts | 71 + .../quicktype-core/src/language/Dart/index.ts | 2 + .../src/language/Dart/language.ts | 70 + .../quicktype-core/src/language/Dart/utils.ts | 60 + .../{Elixir.ts => Elixir/ElixirRenderer.ts} | 282 +- .../src/language/Elixir/constants.ts | 101 + .../src/language/Elixir/index.ts | 2 + .../src/language/Elixir/language.ts | 33 + .../src/language/Elixir/utils.ts | 74 + .../language/{Elm.ts => Elm/ElmRenderer.ts} | 170 +- .../src/language/Elm/constants.ts | 40 + .../quicktype-core/src/language/Elm/index.ts | 2 + .../src/language/Elm/language.ts | 38 + .../quicktype-core/src/language/Elm/utils.ts | 55 + .../{Golang.ts => Golang/GolangRenderer.ts} | 336 +-- .../src/language/Golang/index.ts | 2 + .../src/language/Golang/language.ts | 60 + .../src/language/Golang/utils.ts | 44 + .../HaskellRenderer.ts} | 148 +- .../src/language/Haskell/constants.ts | 54 + .../src/language/Haskell/index.ts | 2 + .../src/language/Haskell/language.ts | 37 + .../src/language/Haskell/utils.ts | 31 + .../JSONSchemaRenderer.ts} | 68 +- .../src/language/JSONSchema/index.ts | 2 + .../src/language/JSONSchema/language.ts | 33 + .../src/language/JSONSchema/utils.ts | 26 + .../src/language/Java/DateTimeProvider.ts | 261 ++ .../src/language/Java/JavaJacksonRenderer.ts | 567 ++++ .../src/language/Java/JavaRenderer.ts | 514 ++++ .../src/language/Java/constants.ts | 69 + .../quicktype-core/src/language/Java/index.ts | 3 + .../src/language/Java/language.ts | 77 + .../quicktype-core/src/language/Java/utils.ts | 46 + .../JavaScriptRenderer.ts} | 100 +- .../src/language/JavaScript/index.ts | 2 + .../src/language/JavaScript/language.ts | 68 + .../unicodeMaps.ts} | 0 .../src/language/JavaScript/utils.ts | 5 + .../JavaScriptPropTypesRenderer.ts} | 77 +- .../src/language/JavaScriptPropTypes/index.ts | 2 + .../language/JavaScriptPropTypes/language.ts | 47 + .../quicktype-core/src/language/Kotlin.ts | 1129 -------- .../language/Kotlin/KotlinJacksonRenderer.ts | 293 ++ .../language/Kotlin/KotlinKlaxonRenderer.ts | 306 ++ .../src/language/Kotlin/KotlinRenderer.ts | 300 ++ .../src/language/Kotlin/KotlinXRenderer.ts | 121 + .../src/language/Kotlin/constants.ts | 51 + .../src/language/Kotlin/index.ts | 5 + .../src/language/Kotlin/language.ts | 70 + .../src/language/Kotlin/utils.ts | 55 + .../ObjectiveCRenderer.ts} | 267 +- .../src/language/Objective-C/constants.ts | 82 + .../src/language/Objective-C/index.ts | 2 + .../src/language/Objective-C/language.ts | 45 + .../src/language/Objective-C/utils.ts | 88 + .../language/{Php.ts => Php/PhpRenderer.ts} | 109 +- .../quicktype-core/src/language/Php/index.ts | 2 + .../src/language/Php/language.ts | 46 + .../quicktype-core/src/language/Php/utils.ts | 48 + .../{Pike.ts => Pike/PikeRenderer.ts} | 103 +- .../src/language/Pike/constants.ts | 54 + .../quicktype-core/src/language/Pike/index.ts | 2 + .../src/language/Pike/language.ts | 22 + .../quicktype-core/src/language/Pike/utils.ts | 7 + .../JSONPythonRenderer.ts} | 543 +--- .../src/language/Python/PythonRenderer.ts | 321 +++ .../src/language/Python/constants.ts | 59 + .../src/language/Python/index.ts | 3 + .../src/language/Python/language.ts | 74 + .../src/language/Python/utils.ts | 76 + .../{ruby/index.ts => Ruby/RubyRenderer.ts} | 124 +- .../{ruby/keywords.ts => Ruby/constants.ts} | 18 +- .../quicktype-core/src/language/Ruby/index.ts | 2 + .../src/language/Ruby/language.ts | 39 + .../quicktype-core/src/language/Ruby/utils.ts | 71 + .../{Rust.ts => Rust/RustRenderer.ts} | 318 +-- .../src/language/Rust/constants.ts | 76 + .../quicktype-core/src/language/Rust/index.ts | 2 + .../src/language/Rust/language.ts | 48 + .../quicktype-core/src/language/Rust/utils.ts | 166 ++ .../quicktype-core/src/language/Scala3.ts | 721 ----- .../src/language/Scala3/CirceRenderer.ts | 193 ++ .../src/language/Scala3/Scala3Renderer.ts | 313 +++ .../src/language/Scala3/UpickleRenderer.ts | 14 + .../src/language/Scala3/constants.ts | 87 + .../src/language/Scala3/index.ts | 4 + .../src/language/Scala3/language.ts | 63 + .../src/language/Scala3/utils.ts | 73 + .../Smithy4sRenderer.ts} | 201 +- .../src/language/Smithy4s/constants.ts | 77 + .../src/language/Smithy4s/index.ts | 2 + .../src/language/Smithy4s/language.ts | 46 + .../src/language/Smithy4s/utils.ts | 55 + .../{Swift.ts => Swift/SwiftRenderer.ts} | 843 ++---- .../src/language/Swift/constants.ts | 101 + .../src/language/Swift/index.ts | 2 + .../src/language/Swift/language.ts | 128 + .../src/language/Swift/utils.ts | 84 + .../TypeScriptEffectSchemaRenderer.ts} | 57 +- .../language/TypeScriptEffectSchema/index.ts | 2 + .../TypeScriptEffectSchema/language.ts | 35 + .../src/language/TypeScriptFlow.ts | 406 --- .../language/TypeScriptFlow/FlowRenderer.ts | 47 + .../TypeScriptFlowBaseRenderer.ts | 190 ++ .../TypeScriptFlow/TypeScriptRenderer.ts | 88 + .../src/language/TypeScriptFlow/index.ts | 3 + .../src/language/TypeScriptFlow/language.ts | 68 + .../src/language/TypeScriptFlow/utils.ts | 29 + .../TypeScriptZodRenderer.ts} | 66 +- .../src/language/TypeScriptZod/index.ts | 2 + .../src/language/TypeScriptZod/language.ts | 45 + packages/quicktype-core/src/language/index.ts | 26 + test/languages.ts | 54 +- 142 files changed, 11237 insertions(+), 9273 deletions(-) rename packages/quicktype-core/src/language/{CJSON.ts => CJSON/CJSONRenderer.ts} (95%) create mode 100644 packages/quicktype-core/src/language/CJSON/constants.ts create mode 100644 packages/quicktype-core/src/language/CJSON/index.ts create mode 100644 packages/quicktype-core/src/language/CJSON/language.ts create mode 100644 packages/quicktype-core/src/language/CJSON/utils.ts rename packages/quicktype-core/src/language/{CPlusPlus.ts => CPlusPlus/CPlusPlusRenderer.ts} (89%) create mode 100644 packages/quicktype-core/src/language/CPlusPlus/constants.ts create mode 100644 packages/quicktype-core/src/language/CPlusPlus/index.ts create mode 100644 packages/quicktype-core/src/language/CPlusPlus/language.ts create mode 100644 packages/quicktype-core/src/language/CPlusPlus/utils.ts delete mode 100644 packages/quicktype-core/src/language/CSharp.ts create mode 100644 packages/quicktype-core/src/language/CSharp/CSharpRenderer.ts create mode 100644 packages/quicktype-core/src/language/CSharp/NewtonSoftCSharpRenderer.ts create mode 100644 packages/quicktype-core/src/language/CSharp/SystemTextJsonCSharpRenderer.ts create mode 100644 packages/quicktype-core/src/language/CSharp/constants.ts create mode 100644 packages/quicktype-core/src/language/CSharp/index.ts create mode 100644 packages/quicktype-core/src/language/CSharp/language.ts create mode 100644 packages/quicktype-core/src/language/CSharp/utils.ts rename packages/quicktype-core/src/language/{Crystal.ts => Crystal/CrystalRenderer.ts} (56%) create mode 100644 packages/quicktype-core/src/language/Crystal/constants.ts create mode 100644 packages/quicktype-core/src/language/Crystal/index.ts create mode 100644 packages/quicktype-core/src/language/Crystal/language.ts create mode 100644 packages/quicktype-core/src/language/Crystal/utils.ts rename packages/quicktype-core/src/language/{Dart.ts => Dart/DartRenderer.ts} (80%) create mode 100644 packages/quicktype-core/src/language/Dart/constants.ts create mode 100644 packages/quicktype-core/src/language/Dart/index.ts create mode 100644 packages/quicktype-core/src/language/Dart/language.ts create mode 100644 packages/quicktype-core/src/language/Dart/utils.ts rename packages/quicktype-core/src/language/{Elixir.ts => Elixir/ElixirRenderer.ts} (85%) create mode 100644 packages/quicktype-core/src/language/Elixir/constants.ts create mode 100644 packages/quicktype-core/src/language/Elixir/index.ts create mode 100644 packages/quicktype-core/src/language/Elixir/language.ts create mode 100644 packages/quicktype-core/src/language/Elixir/utils.ts rename packages/quicktype-core/src/language/{Elm.ts => Elm/ElmRenderer.ts} (84%) create mode 100644 packages/quicktype-core/src/language/Elm/constants.ts create mode 100644 packages/quicktype-core/src/language/Elm/index.ts create mode 100644 packages/quicktype-core/src/language/Elm/language.ts create mode 100644 packages/quicktype-core/src/language/Elm/utils.ts rename packages/quicktype-core/src/language/{Golang.ts => Golang/GolangRenderer.ts} (73%) create mode 100644 packages/quicktype-core/src/language/Golang/index.ts create mode 100644 packages/quicktype-core/src/language/Golang/language.ts create mode 100644 packages/quicktype-core/src/language/Golang/utils.ts rename packages/quicktype-core/src/language/{Haskell.ts => Haskell/HaskellRenderer.ts} (82%) create mode 100644 packages/quicktype-core/src/language/Haskell/constants.ts create mode 100644 packages/quicktype-core/src/language/Haskell/index.ts create mode 100644 packages/quicktype-core/src/language/Haskell/language.ts create mode 100644 packages/quicktype-core/src/language/Haskell/utils.ts rename packages/quicktype-core/src/language/{JSONSchema.ts => JSONSchema/JSONSchemaRenderer.ts} (75%) create mode 100644 packages/quicktype-core/src/language/JSONSchema/index.ts create mode 100644 packages/quicktype-core/src/language/JSONSchema/language.ts create mode 100644 packages/quicktype-core/src/language/JSONSchema/utils.ts create mode 100644 packages/quicktype-core/src/language/Java/DateTimeProvider.ts create mode 100644 packages/quicktype-core/src/language/Java/JavaJacksonRenderer.ts create mode 100644 packages/quicktype-core/src/language/Java/JavaRenderer.ts create mode 100644 packages/quicktype-core/src/language/Java/constants.ts create mode 100644 packages/quicktype-core/src/language/Java/index.ts create mode 100644 packages/quicktype-core/src/language/Java/language.ts create mode 100644 packages/quicktype-core/src/language/Java/utils.ts rename packages/quicktype-core/src/language/{JavaScript.ts => JavaScript/JavaScriptRenderer.ts} (84%) create mode 100644 packages/quicktype-core/src/language/JavaScript/index.ts create mode 100644 packages/quicktype-core/src/language/JavaScript/language.ts rename packages/quicktype-core/src/language/{JavaScriptUnicodeMaps.ts => JavaScript/unicodeMaps.ts} (100%) create mode 100644 packages/quicktype-core/src/language/JavaScript/utils.ts rename packages/quicktype-core/src/language/{JavaScriptPropTypes.ts => JavaScriptPropTypes/JavaScriptPropTypesRenderer.ts} (80%) create mode 100644 packages/quicktype-core/src/language/JavaScriptPropTypes/index.ts create mode 100644 packages/quicktype-core/src/language/JavaScriptPropTypes/language.ts delete mode 100644 packages/quicktype-core/src/language/Kotlin.ts create mode 100644 packages/quicktype-core/src/language/Kotlin/KotlinJacksonRenderer.ts create mode 100644 packages/quicktype-core/src/language/Kotlin/KotlinKlaxonRenderer.ts create mode 100644 packages/quicktype-core/src/language/Kotlin/KotlinRenderer.ts create mode 100644 packages/quicktype-core/src/language/Kotlin/KotlinXRenderer.ts create mode 100644 packages/quicktype-core/src/language/Kotlin/constants.ts create mode 100644 packages/quicktype-core/src/language/Kotlin/index.ts create mode 100644 packages/quicktype-core/src/language/Kotlin/language.ts create mode 100644 packages/quicktype-core/src/language/Kotlin/utils.ts rename packages/quicktype-core/src/language/{Objective-C.ts => Objective-C/ObjectiveCRenderer.ts} (84%) create mode 100644 packages/quicktype-core/src/language/Objective-C/constants.ts create mode 100644 packages/quicktype-core/src/language/Objective-C/index.ts create mode 100644 packages/quicktype-core/src/language/Objective-C/language.ts create mode 100644 packages/quicktype-core/src/language/Objective-C/utils.ts rename packages/quicktype-core/src/language/{Php.ts => Php/PhpRenderer.ts} (91%) create mode 100644 packages/quicktype-core/src/language/Php/index.ts create mode 100644 packages/quicktype-core/src/language/Php/language.ts create mode 100644 packages/quicktype-core/src/language/Php/utils.ts rename packages/quicktype-core/src/language/{Pike.ts => Pike/PikeRenderer.ts} (81%) create mode 100644 packages/quicktype-core/src/language/Pike/constants.ts create mode 100644 packages/quicktype-core/src/language/Pike/index.ts create mode 100644 packages/quicktype-core/src/language/Pike/language.ts create mode 100644 packages/quicktype-core/src/language/Pike/utils.ts rename packages/quicktype-core/src/language/{Python.ts => Python/JSONPythonRenderer.ts} (63%) create mode 100644 packages/quicktype-core/src/language/Python/PythonRenderer.ts create mode 100644 packages/quicktype-core/src/language/Python/constants.ts create mode 100644 packages/quicktype-core/src/language/Python/index.ts create mode 100644 packages/quicktype-core/src/language/Python/language.ts create mode 100644 packages/quicktype-core/src/language/Python/utils.ts rename packages/quicktype-core/src/language/{ruby/index.ts => Ruby/RubyRenderer.ts} (87%) rename packages/quicktype-core/src/language/{ruby/keywords.ts => Ruby/constants.ts} (97%) create mode 100644 packages/quicktype-core/src/language/Ruby/index.ts create mode 100644 packages/quicktype-core/src/language/Ruby/language.ts create mode 100644 packages/quicktype-core/src/language/Ruby/utils.ts rename packages/quicktype-core/src/language/{Rust.ts => Rust/RustRenderer.ts} (54%) create mode 100644 packages/quicktype-core/src/language/Rust/constants.ts create mode 100644 packages/quicktype-core/src/language/Rust/index.ts create mode 100644 packages/quicktype-core/src/language/Rust/language.ts create mode 100644 packages/quicktype-core/src/language/Rust/utils.ts delete mode 100644 packages/quicktype-core/src/language/Scala3.ts create mode 100644 packages/quicktype-core/src/language/Scala3/CirceRenderer.ts create mode 100644 packages/quicktype-core/src/language/Scala3/Scala3Renderer.ts create mode 100644 packages/quicktype-core/src/language/Scala3/UpickleRenderer.ts create mode 100644 packages/quicktype-core/src/language/Scala3/constants.ts create mode 100644 packages/quicktype-core/src/language/Scala3/index.ts create mode 100644 packages/quicktype-core/src/language/Scala3/language.ts create mode 100644 packages/quicktype-core/src/language/Scala3/utils.ts rename packages/quicktype-core/src/language/{Smithy4s.ts => Smithy4s/Smithy4sRenderer.ts} (73%) create mode 100644 packages/quicktype-core/src/language/Smithy4s/constants.ts create mode 100644 packages/quicktype-core/src/language/Smithy4s/index.ts create mode 100644 packages/quicktype-core/src/language/Smithy4s/language.ts create mode 100644 packages/quicktype-core/src/language/Smithy4s/utils.ts rename packages/quicktype-core/src/language/{Swift.ts => Swift/SwiftRenderer.ts} (66%) create mode 100644 packages/quicktype-core/src/language/Swift/constants.ts create mode 100644 packages/quicktype-core/src/language/Swift/index.ts create mode 100644 packages/quicktype-core/src/language/Swift/language.ts create mode 100644 packages/quicktype-core/src/language/Swift/utils.ts rename packages/quicktype-core/src/language/{TypeScriptEffectSchema.ts => TypeScriptEffectSchema/TypeScriptEffectSchemaRenderer.ts} (82%) create mode 100644 packages/quicktype-core/src/language/TypeScriptEffectSchema/index.ts create mode 100644 packages/quicktype-core/src/language/TypeScriptEffectSchema/language.ts delete mode 100644 packages/quicktype-core/src/language/TypeScriptFlow.ts create mode 100644 packages/quicktype-core/src/language/TypeScriptFlow/FlowRenderer.ts create mode 100644 packages/quicktype-core/src/language/TypeScriptFlow/TypeScriptFlowBaseRenderer.ts create mode 100644 packages/quicktype-core/src/language/TypeScriptFlow/TypeScriptRenderer.ts create mode 100644 packages/quicktype-core/src/language/TypeScriptFlow/index.ts create mode 100644 packages/quicktype-core/src/language/TypeScriptFlow/language.ts create mode 100644 packages/quicktype-core/src/language/TypeScriptFlow/utils.ts rename packages/quicktype-core/src/language/{TypeScriptZod.ts => TypeScriptZod/TypeScriptZodRenderer.ts} (85%) create mode 100644 packages/quicktype-core/src/language/TypeScriptZod/index.ts create mode 100644 packages/quicktype-core/src/language/TypeScriptZod/language.ts create mode 100644 packages/quicktype-core/src/language/index.ts diff --git a/packages/quicktype-core/src/ConvenienceRenderer.ts b/packages/quicktype-core/src/ConvenienceRenderer.ts index 2c9c6ff42..aef41b181 100644 --- a/packages/quicktype-core/src/ConvenienceRenderer.ts +++ b/packages/quicktype-core/src/ConvenienceRenderer.ts @@ -129,7 +129,7 @@ export abstract class ConvenienceRenderer extends Renderer { * that can conflict with that, such as reserved keywords or common type * names. */ - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace(): readonly string[] { return []; } diff --git a/packages/quicktype-core/src/Naming.ts b/packages/quicktype-core/src/Naming.ts index 6b2b2b825..cc98c50fc 100644 --- a/packages/quicktype-core/src/Naming.ts +++ b/packages/quicktype-core/src/Naming.ts @@ -319,7 +319,7 @@ export class DependencyName extends Name { } } -export function keywordNamespace(name: string, keywords: string[]): Namespace { +export function keywordNamespace(name: string, keywords: readonly string[]): Namespace { const ns = new Namespace(name, undefined, [], []); for (const kw of keywords) { ns.add(new FixedName(kw)); diff --git a/packages/quicktype-core/src/index.ts b/packages/quicktype-core/src/index.ts index fa1ea78be..6da647b12 100644 --- a/packages/quicktype-core/src/index.ts +++ b/packages/quicktype-core/src/index.ts @@ -84,35 +84,4 @@ export { removeNullFromUnion, matchType, nullableFromUnion } from "./TypeUtils"; export { ConvenienceRenderer } from "./ConvenienceRenderer"; export { uriTypeAttributeKind } from "./attributes/URIAttributes"; -export { CJSONTargetLanguage, CJSONRenderer, cJSONOptions } from "./language/CJSON"; -export { CPlusPlusTargetLanguage, CPlusPlusRenderer, cPlusPlusOptions } from "./language/CPlusPlus"; -export { CSharpTargetLanguage, cSharpOptions, CSharpRenderer } from "./language/CSharp"; -export { PythonTargetLanguage, PythonRenderer, pythonOptions } from "./language/Python"; -export { GoTargetLanguage, GoRenderer, goOptions } from "./language/Golang"; -export { ObjectiveCTargetLanguage, ObjectiveCRenderer, objcOptions } from "./language/Objective-C"; -export { JavaTargetLanguage, JavaRenderer, javaOptions } from "./language/Java"; -export { JavaScriptTargetLanguage, JavaScriptRenderer, javaScriptOptions } from "./language/JavaScript"; -export { - JavaScriptPropTypesTargetLanguage, - JavaScriptPropTypesRenderer, - javaScriptPropTypesOptions -} from "./language/JavaScriptPropTypes"; -export { - TypeScriptTargetLanguage, - TypeScriptRenderer, - FlowTargetLanguage, - FlowRenderer, - tsFlowOptions -} from "./language/TypeScriptFlow"; -export { SwiftTargetLanguage, SwiftRenderer, swiftOptions } from "./language/Swift"; -export { KotlinTargetLanguage, KotlinRenderer, kotlinOptions } from "./language/Kotlin"; -export { Scala3TargetLanguage, Scala3Renderer, scala3Options } from "./language/Scala3"; -export { SmithyTargetLanguage, Smithy4sRenderer, SmithyOptions } from "./language/Smithy4s"; -export { ElmTargetLanguage, ElmRenderer, elmOptions } from "./language/Elm"; -export { JSONSchemaTargetLanguage, JSONSchemaRenderer } from "./language/JSONSchema"; -export { RustTargetLanguage, RustRenderer, rustOptions } from "./language/Rust"; -export { RubyTargetLanguage, RubyRenderer, rubyOptions } from "./language/ruby"; -export { CrystalTargetLanguage, CrystalRenderer } from "./language/Crystal"; -export { HaskellTargetLanguage, HaskellRenderer, haskellOptions } from "./language/Haskell"; -export { DartTargetLanguage, DartRenderer, dartOptions } from "./language/Dart"; -export { ElixirTargetLanguage, ElixirRenderer, elixirOptions } from "./language/Elixir"; +export * from "./language"; diff --git a/packages/quicktype-core/src/language/All.ts b/packages/quicktype-core/src/language/All.ts index 297af4d1c..227ca4322 100644 --- a/packages/quicktype-core/src/language/All.ts +++ b/packages/quicktype-core/src/language/All.ts @@ -21,7 +21,7 @@ import { ObjectiveCTargetLanguage } from "./Objective-C"; import { PhpTargetLanguage } from "./Php"; import { PikeTargetLanguage } from "./Pike"; import { PythonTargetLanguage } from "./Python"; -import { RubyTargetLanguage } from "./ruby"; +import { RubyTargetLanguage } from "./Ruby"; import { RustTargetLanguage } from "./Rust"; import { Scala3TargetLanguage } from "./Scala3"; import { SmithyTargetLanguage } from "./Smithy4s"; @@ -31,33 +31,33 @@ import { FlowTargetLanguage, TypeScriptTargetLanguage } from "./TypeScriptFlow"; import { TypeScriptZodTargetLanguage } from "./TypeScriptZod"; export const all: TargetLanguage[] = [ - new CSharpTargetLanguage(), - new GoTargetLanguage(), - new RustTargetLanguage(), - new CrystalTargetLanguage(), new CJSONTargetLanguage(), new CPlusPlusTargetLanguage(), - new ObjectiveCTargetLanguage(), + new CrystalTargetLanguage(), + new CSharpTargetLanguage(), + new DartTargetLanguage(), + new ElixirTargetLanguage(), + new ElmTargetLanguage(), + new FlowTargetLanguage(), + new GoTargetLanguage(), + new HaskellTargetLanguage(), new JavaTargetLanguage(), - new TypeScriptTargetLanguage(), new JavaScriptTargetLanguage(), new JavaScriptPropTypesTargetLanguage(), - new FlowTargetLanguage(), - new SwiftTargetLanguage(), - new Scala3TargetLanguage(), - new SmithyTargetLanguage(), - new KotlinTargetLanguage(), - new ElmTargetLanguage(), new JSONSchemaTargetLanguage(), - new RubyTargetLanguage(), - new DartTargetLanguage(), - new PythonTargetLanguage("Python", ["python", "py"], "py"), + new KotlinTargetLanguage(), + new ObjectiveCTargetLanguage(), + new PhpTargetLanguage(), new PikeTargetLanguage(), - new HaskellTargetLanguage(), - new TypeScriptZodTargetLanguage(), + new PythonTargetLanguage("Python", ["python", "py"], "py"), + new RubyTargetLanguage(), + new RustTargetLanguage(), + new Scala3TargetLanguage(), + new SmithyTargetLanguage(), + new SwiftTargetLanguage(), + new TypeScriptTargetLanguage(), new TypeScriptEffectSchemaTargetLanguage(), - new ElixirTargetLanguage(), - new PhpTargetLanguage() + new TypeScriptZodTargetLanguage() ]; export function languageNamed(name: string, targetLanguages?: TargetLanguage[]): TargetLanguage | undefined { diff --git a/packages/quicktype-core/src/language/CJSON.ts b/packages/quicktype-core/src/language/CJSON/CJSONRenderer.ts similarity index 95% rename from packages/quicktype-core/src/language/CJSON.ts rename to packages/quicktype-core/src/language/CJSON/CJSONRenderer.ts index 28499a4b4..6f9dc33b9 100644 --- a/packages/quicktype-core/src/language/CJSON.ts +++ b/packages/quicktype-core/src/language/CJSON/CJSONRenderer.ts @@ -1,368 +1,32 @@ // FIXME: NEEDS REFACTOR /* eslint-disable @typescript-eslint/no-shadow */ /* eslint-disable @typescript-eslint/naming-convention */ -/** - * CJSON.ts - * This file is used to generate cJSON code with quicktype - * The generated code depends of https://github.com/DaveGamble/cJSON, https://github.com/joelguittet/c-list and https://github.com/joelguittet/c-hashtable - * - * Similarly to C++ generator, it is possible to generate a single header file or multiple header files. - * To generate multiple header files, use the following option: --source-style multi-source - * - * JSON data are represented using structures, and functions in the cJSON style are created to use them. - * To parse json data from json string use the following: struct * data = cJSON_Parse(); - * To get json data from cJSON object use the following: struct * data = cJSON_GetValue(); - * To get cJSON object from json data use the following: cJSON * cjson = cJSON_Create(); - * To print json string from json data use the following: char * string = cJSON_Print(); - * To delete json data use the following: cJSON_Delete(); - * - * TODO list for future enhancements: - * - Management of Class, Union and TopLevel should be mutualized to reduce code size and to permit Union and TopLevel having recursive Array/Map - * - Types check should be added to verify unwanted inputs (for example a Number passed while a String is expected, etc) - * - Constraints should be implemented (verification of Enum values, min/max values for Numbers and min/max length for Strings, regex) - * - Support of pure Any type for example providing a callback from the application to handle these cases dynamically - * See test/languages.ts for the test cases which are not implmented/checked. - */ - -/* Imports */ -import { getAccessorName } from "../attributes/AccessorNames"; -import { enumCaseValues } from "../attributes/EnumValues"; -import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { type Name, type NameStyle, type Namer, funPrefixNamer } from "../Naming"; -import { type RenderContext } from "../Renderer"; -import { EnumOption, type Option, type OptionValues, StringOption, getOptionValues } from "../RendererOptions"; -import { type Sourcelike } from "../Source"; -import { - type NamingStyle, - allUpperWordStyle, - isAscii, - isLetterOrUnderscoreOrDigit, - legalizeCharacters, - makeNameStyle -} from "../support/Strings"; -import { assert, assertNever, defined, numberEnumValues, panic } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; -import { ArrayType, ClassType, EnumType, MapType, type Type, type TypeKind, UnionType } from "../Type"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; -import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; - -/* Naming styles */ -const pascalValue: [string, NamingStyle] = ["pascal-case", "pascal"]; -const underscoreValue: [string, NamingStyle] = ["underscore-case", "underscore"]; -const camelValue: [string, NamingStyle] = ["camel-case", "camel"]; -const upperUnderscoreValue: [string, NamingStyle] = ["upper-underscore-case", "upper-underscore"]; -const pascalUpperAcronymsValue: [string, NamingStyle] = ["pascal-case-upper-acronyms", "pascal-upper-acronyms"]; -const camelUpperAcronymsValue: [string, NamingStyle] = ["camel-case-upper-acronyms", "camel-upper-acronyms"]; - -/* cJSON generator options */ -export const cJSONOptions = { - typeSourceStyle: new EnumOption( - "source-style", - "Source code generation type, whether to generate single or multiple source files", - [ - ["single-source", true], - ["multi-source", false] - ], - "single-source", - "secondary" - ), - typeIntegerSize: new EnumOption( - "integer-size", - "Integer code generation type (int64_t by default)", - [ - ["int8_t", "int8_t"], - ["int16_t", "int16_t"], - ["int32_t", "int32_t"], - ["int64_t", "int64_t"] - ], - "int64_t", - "secondary" - ), - hashtableSize: new StringOption( - "hashtable-size", - "Hashtable size, used when maps are created (64 by default)", - "SIZE", - "64" - ), - addTypedefAlias: new EnumOption( - "typedef-alias", - "Add typedef alias to unions, structs, and enums (no typedef by default)", - [ - ["no-typedef", false], - ["add-typedef", true] - ], - "no-typedef", - "secondary" - ), - printStyle: new EnumOption( - "print-style", - "Which cJSON print should be used (formatted by default)", - [ - ["print-formatted", false], - ["print-unformatted", true] - ], - "print-formatted", - "secondary" - ), - typeNamingStyle: new EnumOption("type-style", "Naming style for types", [ - pascalValue, - underscoreValue, - camelValue, - upperUnderscoreValue, - pascalUpperAcronymsValue, - camelUpperAcronymsValue - ]), - memberNamingStyle: new EnumOption("member-style", "Naming style for members", [ - underscoreValue, - pascalValue, - camelValue, - upperUnderscoreValue, - pascalUpperAcronymsValue, - camelUpperAcronymsValue - ]), - enumeratorNamingStyle: new EnumOption("enumerator-style", "Naming style for enumerators", [ - upperUnderscoreValue, - underscoreValue, - pascalValue, - camelValue, - pascalUpperAcronymsValue, - camelUpperAcronymsValue - ]) -}; - -/* cJSON generator target language */ -export class CJSONTargetLanguage extends TargetLanguage { - /** - * Constructor - * @param displayName: display name - * @params names: names - * @param extension: extension of files - */ - public constructor(displayName = "C (cJSON)", names: string[] = ["cjson", "cJSON"], extension = "h") { - super(displayName, names, extension); - } - - /** - * Return cJSON generator options - * @return cJSON generator options array - */ - protected getOptions(): Array> { - return [ - cJSONOptions.typeSourceStyle, - cJSONOptions.typeIntegerSize, - cJSONOptions.addTypedefAlias, - cJSONOptions.printStyle, - cJSONOptions.hashtableSize, - cJSONOptions.typeNamingStyle, - cJSONOptions.memberNamingStyle, - cJSONOptions.enumeratorNamingStyle - ]; - } - - /** - * Indicate if language support union with both number types - * @return true - */ - public get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - /** - * Indicate if language support optional class properties - * @return true - */ - public get supportsOptionalClassProperties(): boolean { - return true; - } - - /** - * Create renderer - * @param renderContext: render context - * @param untypedOptionValues - * @return cJSON renderer - */ - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): CJSONRenderer { - return new CJSONRenderer(this, renderContext, getOptionValues(cJSONOptions, untypedOptionValues)); - } -} - -/* Function used to format names */ -const legalizeName = legalizeCharacters(cp => isAscii(cp) && isLetterOrUnderscoreOrDigit(cp)); - -/* Forbidden names for namespace */ -const keywords = [ - /* C and C++ keywords */ - "alignas", - "alignof", - "and", - "and_eq", - "asm", - "atomic_cancel", - "atomic_commit", - "atomic_noexcept", - "auto", - "bitand", - "bitor", - "bool", - "break", - "case", - "catch", - "char", - "char16_t", - "char32_t", - "class", - "compl", - "concept", - "const", - "constexpr", - "const_cast", - "continue", - "co_await", - "co_return", - "co_yield", - "decltype", - "default", - "delete", - "do", - "double", - "dynamic_cast", - "else", - "enum", - "explicit", - "export", - "extern", - "false", - "float", - "for", - "friend", - "goto", - "if", - "import", - "inline", - "int", - "long", - "module", - "mutable", - "namespace", - "new", - "noexcept", - "not", - "not_eq", - "nullptr", - "operator", - "or", - "or_eq", - "private", - "protected", - "public", - "register", - "reinterpret_cast", - "requires", - "restrict", - "return", - "short", - "signed", - "sizeof", - "static", - "static_assert", - "static_cast", - "struct", - "switch", - "synchronized", - "template", - "this", - "thread_local", - "throw", - "true", - "try", - "typedef", - "typeid", - "typename", - "typeof", - "union", - "unsigned", - "using", - "virtual", - "void", - "volatile", - "wchar_t", - "while", - "xor", - "xor_eq", - "override", - "final", - "transaction_safe", - "transaction_safe_dynamic", - "NULL", - /* cJSON keywords */ - "Array", - "ArrayReference", - "Bool", - "DoubleArray", - "False", - "FloatArray", - "IntArray", - "Object", - "Null", - "Number", - "Raw", - "String", - "StringArray", - "StringReference", - "True" -]; - -/* Used to build forbidden global names */ -export enum GlobalNames { - ClassMemberConstraints = 1, - ClassMemberConstraintException = 2, - ValueTooLowException = 3, - ValueTooHighException = 4, - ValueTooShortException = 5, - ValueTooLongException = 6, - InvalidPatternException = 7, - CheckConstraint = 8 -} -/* To be able to support circles in multiple files - e.g. class#A using class#B using class#A (obviously not directly) we can forward declare them */ -export enum IncludeKind { - ForwardDeclare = "ForwardDeclare", - Include = "Include" -} - -/* Used to map includes */ -export interface IncludeRecord { - kind: IncludeKind | undefined /* How to include that */; - typeKind: TypeKind | undefined /* What exactly to include */; -} - -/* Used to map includes */ -export interface TypeRecord { - forceInclude: boolean; - level: number; - name: Name; - type: Type; - variant: boolean; -} - -/* Map each and every unique type to a include kind, e.g. how to include the given type */ -export type IncludeMap = Map; - -/* cJSON type */ -export interface TypeCJSON { - addToObject: Sourcelike /* cJSON add to object function */; - cType: Sourcelike /* C type */; - cjsonType: string /* cJSON type */; - createObject: Sourcelike /* cJSON create object function */; - deleteType: Sourcelike /* cJSON delete function */; - getValue: Sourcelike /* cJSON get value function */; - isNullable: boolean /* True if the field is nullable */; - isType: Sourcelike /* cJSON check type function */; - items: TypeCJSON | undefined /* Sub-items, used for arrays and map */; - optionalQualifier: string /* C optional qualifier, empty string if not defined */; -} +import { getAccessorName } from "../../attributes/AccessorNames"; +import { enumCaseValues } from "../../attributes/EnumValues"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../../ConvenienceRenderer"; +import { type Name, type NameStyle, type Namer, funPrefixNamer } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type Sourcelike } from "../../Source"; +import { type NamingStyle, allUpperWordStyle, makeNameStyle } from "../../support/Strings"; +import { assert, assertNever, defined, numberEnumValues, panic } from "../../support/Support"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { ArrayType, ClassType, EnumType, MapType, type Type, UnionType } from "../../Type"; +import { matchType, nullableFromUnion, removeNullFromUnion } from "../../TypeUtils"; + +import { keywords } from "./constants"; +import { type cJSONOptions } from "./language"; +import { + GlobalNames, + IncludeKind, + type IncludeMap, + type IncludeRecord, + type TypeCJSON, + type TypeRecord, + legalizeName +} from "./utils"; -/* cJSON renderer */ export class CJSONRenderer extends ConvenienceRenderer { private currentFilename: string | undefined; /* Current filename */ @@ -3409,7 +3073,7 @@ export class CJSONRenderer extends ConvenienceRenderer { } else { this.emitLine( "list_add_tail(x->value, ", - // @ts-expect-error awaiting refactor + // @ts-expect-error awaiting refactor cJSON.items?.getValue, "(e), sizeof(", cJSON.items?.cType, diff --git a/packages/quicktype-core/src/language/CJSON/constants.ts b/packages/quicktype-core/src/language/CJSON/constants.ts new file mode 100644 index 000000000..cdccf419c --- /dev/null +++ b/packages/quicktype-core/src/language/CJSON/constants.ts @@ -0,0 +1,123 @@ + +/* Forbidden names for namespace */ +export const keywords = [ + /* C and C++ keywords */ + "alignas", + "alignof", + "and", + "and_eq", + "asm", + "atomic_cancel", + "atomic_commit", + "atomic_noexcept", + "auto", + "bitand", + "bitor", + "bool", + "break", + "case", + "catch", + "char", + "char16_t", + "char32_t", + "class", + "compl", + "concept", + "const", + "constexpr", + "const_cast", + "continue", + "co_await", + "co_return", + "co_yield", + "decltype", + "default", + "delete", + "do", + "double", + "dynamic_cast", + "else", + "enum", + "explicit", + "export", + "extern", + "false", + "float", + "for", + "friend", + "goto", + "if", + "import", + "inline", + "int", + "long", + "module", + "mutable", + "namespace", + "new", + "noexcept", + "not", + "not_eq", + "nullptr", + "operator", + "or", + "or_eq", + "private", + "protected", + "public", + "register", + "reinterpret_cast", + "requires", + "restrict", + "return", + "short", + "signed", + "sizeof", + "static", + "static_assert", + "static_cast", + "struct", + "switch", + "synchronized", + "template", + "this", + "thread_local", + "throw", + "true", + "try", + "typedef", + "typeid", + "typename", + "typeof", + "union", + "unsigned", + "using", + "virtual", + "void", + "volatile", + "wchar_t", + "while", + "xor", + "xor_eq", + "override", + "final", + "transaction_safe", + "transaction_safe_dynamic", + "NULL", + /* cJSON keywords */ + "Array", + "ArrayReference", + "Bool", + "DoubleArray", + "False", + "FloatArray", + "IntArray", + "Object", + "Null", + "Number", + "Raw", + "String", + "StringArray", + "StringReference", + "True" +] as const; diff --git a/packages/quicktype-core/src/language/CJSON/index.ts b/packages/quicktype-core/src/language/CJSON/index.ts new file mode 100644 index 000000000..1534721aa --- /dev/null +++ b/packages/quicktype-core/src/language/CJSON/index.ts @@ -0,0 +1,2 @@ +export { CJSONTargetLanguage, cJSONOptions } from "./language"; +export { CJSONRenderer } from "./CJSONRenderer"; diff --git a/packages/quicktype-core/src/language/CJSON/language.ts b/packages/quicktype-core/src/language/CJSON/language.ts new file mode 100644 index 000000000..fdcde98a7 --- /dev/null +++ b/packages/quicktype-core/src/language/CJSON/language.ts @@ -0,0 +1,169 @@ +/** + * CJSON.ts + * This file is used to generate cJSON code with quicktype + * The generated code depends of https://github.com/DaveGamble/cJSON, https://github.com/joelguittet/c-list and https://github.com/joelguittet/c-hashtable + * + * Similarly to C++ generator, it is possible to generate a single header file or multiple header files. + * To generate multiple header files, use the following option: --source-style multi-source + * + * JSON data are represented using structures, and functions in the cJSON style are created to use them. + * To parse json data from json string use the following: struct * data = cJSON_Parse(); + * To get json data from cJSON object use the following: struct * data = cJSON_GetValue(); + * To get cJSON object from json data use the following: cJSON * cjson = cJSON_Create(); + * To print json string from json data use the following: char * string = cJSON_Print(); + * To delete json data use the following: cJSON_Delete(); + * + * TODO list for future enhancements: + * - Management of Class, Union and TopLevel should be mutualized to reduce code size and to permit Union and TopLevel having recursive Array/Map + * - Types check should be added to verify unwanted inputs (for example a Number passed while a String is expected, etc) + * - Constraints should be implemented (verification of Enum values, min/max values for Numbers and min/max length for Strings, regex) + * - Support of pure Any type for example providing a callback from the application to handle these cases dynamically + * See test/languages.ts for the test cases which are not implmented/checked. + */ + +import { type RenderContext } from "../../Renderer"; +import { EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { type NamingStyle } from "../../support/Strings"; +import { TargetLanguage } from "../../TargetLanguage"; + +import { CJSONRenderer } from "./CJSONRenderer"; + +/* Naming styles */ +const pascalValue: [string, NamingStyle] = ["pascal-case", "pascal"]; +const underscoreValue: [string, NamingStyle] = ["underscore-case", "underscore"]; +const camelValue: [string, NamingStyle] = ["camel-case", "camel"]; +const upperUnderscoreValue: [string, NamingStyle] = ["upper-underscore-case", "upper-underscore"]; +const pascalUpperAcronymsValue: [string, NamingStyle] = ["pascal-case-upper-acronyms", "pascal-upper-acronyms"]; +const camelUpperAcronymsValue: [string, NamingStyle] = ["camel-case-upper-acronyms", "camel-upper-acronyms"]; + +/* cJSON generator options */ +export const cJSONOptions = { + typeSourceStyle: new EnumOption( + "source-style", + "Source code generation type, whether to generate single or multiple source files", + [ + ["single-source", true], + ["multi-source", false] + ], + "single-source", + "secondary" + ), + typeIntegerSize: new EnumOption( + "integer-size", + "Integer code generation type (int64_t by default)", + [ + ["int8_t", "int8_t"], + ["int16_t", "int16_t"], + ["int32_t", "int32_t"], + ["int64_t", "int64_t"] + ], + "int64_t", + "secondary" + ), + hashtableSize: new StringOption( + "hashtable-size", + "Hashtable size, used when maps are created (64 by default)", + "SIZE", + "64" + ), + addTypedefAlias: new EnumOption( + "typedef-alias", + "Add typedef alias to unions, structs, and enums (no typedef by default)", + [ + ["no-typedef", false], + ["add-typedef", true] + ], + "no-typedef", + "secondary" + ), + printStyle: new EnumOption( + "print-style", + "Which cJSON print should be used (formatted by default)", + [ + ["print-formatted", false], + ["print-unformatted", true] + ], + "print-formatted", + "secondary" + ), + typeNamingStyle: new EnumOption("type-style", "Naming style for types", [ + pascalValue, + underscoreValue, + camelValue, + upperUnderscoreValue, + pascalUpperAcronymsValue, + camelUpperAcronymsValue + ]), + memberNamingStyle: new EnumOption("member-style", "Naming style for members", [ + underscoreValue, + pascalValue, + camelValue, + upperUnderscoreValue, + pascalUpperAcronymsValue, + camelUpperAcronymsValue + ]), + enumeratorNamingStyle: new EnumOption("enumerator-style", "Naming style for enumerators", [ + upperUnderscoreValue, + underscoreValue, + pascalValue, + camelValue, + pascalUpperAcronymsValue, + camelUpperAcronymsValue + ]) +}; + +/* cJSON generator target language */ +export class CJSONTargetLanguage extends TargetLanguage { + /** + * Constructor + * @param displayName: display name + * @params names: names + * @param extension: extension of files + */ + public constructor(displayName = "C (cJSON)", names: string[] = ["cjson", "cJSON"], extension = "h") { + super(displayName, names, extension); + } + + /** + * Return cJSON generator options + * @return cJSON generator options array + */ + protected getOptions(): Array> { + return [ + cJSONOptions.typeSourceStyle, + cJSONOptions.typeIntegerSize, + cJSONOptions.addTypedefAlias, + cJSONOptions.printStyle, + cJSONOptions.hashtableSize, + cJSONOptions.typeNamingStyle, + cJSONOptions.memberNamingStyle, + cJSONOptions.enumeratorNamingStyle + ]; + } + + /** + * Indicate if language support union with both number types + * @return true + */ + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + /** + * Indicate if language support optional class properties + * @return true + */ + public get supportsOptionalClassProperties(): boolean { + return true; + } + + /** + * Create renderer + * @param renderContext: render context + * @param untypedOptionValues + * @return cJSON renderer + */ + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): CJSONRenderer { + return new CJSONRenderer(this, renderContext, getOptionValues(cJSONOptions, untypedOptionValues)); + } +} diff --git a/packages/quicktype-core/src/language/CJSON/utils.ts b/packages/quicktype-core/src/language/CJSON/utils.ts new file mode 100644 index 000000000..2e74a50c7 --- /dev/null +++ b/packages/quicktype-core/src/language/CJSON/utils.ts @@ -0,0 +1,57 @@ +import { type Name } from "../../Naming"; +import { type Sourcelike } from "../../Source"; +import { isAscii, isLetterOrUnderscoreOrDigit, legalizeCharacters } from "../../support/Strings"; +import { type Type, type TypeKind } from "../../Type"; + +/* Function used to format names */ +export const legalizeName = legalizeCharacters(cp => isAscii(cp) && isLetterOrUnderscoreOrDigit(cp)); + +/* Used to build forbidden global names */ +export enum GlobalNames { + ClassMemberConstraints = 1, + ClassMemberConstraintException = 2, + ValueTooLowException = 3, + ValueTooHighException = 4, + ValueTooShortException = 5, + ValueTooLongException = 6, + InvalidPatternException = 7, + CheckConstraint = 8 +} + +/* To be able to support circles in multiple files - e.g. class#A using class#B using class#A (obviously not directly) we can forward declare them */ +export enum IncludeKind { + ForwardDeclare = "ForwardDeclare", + Include = "Include" +} + +/* Used to map includes */ +export interface IncludeRecord { + kind: IncludeKind | undefined /* How to include that */; + typeKind: TypeKind | undefined /* What exactly to include */; +} + +/* Used to map includes */ +export interface TypeRecord { + forceInclude: boolean; + level: number; + name: Name; + type: Type; + variant: boolean; +} + +/* Map each and every unique type to a include kind, e.g. how to include the given type */ +export type IncludeMap = Map; + +/* cJSON type */ +export interface TypeCJSON { + addToObject: Sourcelike /* cJSON add to object function */; + cType: Sourcelike /* C type */; + cjsonType: string /* cJSON type */; + createObject: Sourcelike /* cJSON create object function */; + deleteType: Sourcelike /* cJSON delete function */; + getValue: Sourcelike /* cJSON get value function */; + isNullable: boolean /* True if the field is nullable */; + isType: Sourcelike /* cJSON check type function */; + items: TypeCJSON | undefined /* Sub-items, used for arrays and map */; + optionalQualifier: string /* C optional qualifier, empty string if not defined */; +} diff --git a/packages/quicktype-core/src/language/CPlusPlus.ts b/packages/quicktype-core/src/language/CPlusPlus/CPlusPlusRenderer.ts similarity index 89% rename from packages/quicktype-core/src/language/CPlusPlus.ts rename to packages/quicktype-core/src/language/CPlusPlus/CPlusPlusRenderer.ts index 910f714f9..4b70339f2 100644 --- a/packages/quicktype-core/src/language/CPlusPlus.ts +++ b/packages/quicktype-core/src/language/CPlusPlus/CPlusPlusRenderer.ts @@ -8,473 +8,47 @@ import { withDefault } from "collection-utils"; -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { getAccessorName } from "../attributes/AccessorNames"; +import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../../Annotation"; +import { getAccessorName } from "../../attributes/AccessorNames"; +import { enumCaseValues } from "../../attributes/EnumValues"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../../ConvenienceRenderer"; +import { type Declaration } from "../../DeclarationIR"; +import { DependencyName, type Name, type NameStyle, type Namer, funPrefixNamer } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type Sourcelike, maybeAnnotated } from "../../Source"; +import { type NamingStyle, makeNameStyle, stringEscape } from "../../support/Strings"; +import { assert, assertNever, defined, numberEnumValues, panic } from "../../support/Support"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { ArrayType, type ClassProperty, ClassType, EnumType, MapType, type Type, UnionType } from "../../Type"; import { - type MinMaxConstraint, - minMaxLengthForType, - minMaxValueForType, - patternForType -} from "../attributes/Constraints"; -import { enumCaseValues } from "../attributes/EnumValues"; -import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { type Declaration } from "../DeclarationIR"; -import { DependencyName, type Name, type NameStyle, type Namer, funPrefixNamer } from "../Naming"; -import { type RenderContext } from "../Renderer"; + directlyReachableTypes, + isNamedType, + matchType, + nullableFromUnion, + removeNullFromUnion +} from "../../TypeUtils"; + +import { keywords } from "./constants"; +import { type cPlusPlusOptions } from "./language"; import { - BooleanOption, - EnumOption, - type Option, - type OptionValues, - StringOption, - getOptionValues -} from "../RendererOptions"; -import { type Sourcelike, maybeAnnotated } from "../Source"; -import { - type NamingStyle, - isAscii, - isLetterOrUnderscoreOrDigit, - legalizeCharacters, - makeNameStyle, - stringEscape -} from "../support/Strings"; -import { assert, assertNever, defined, numberEnumValues, panic } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; -import { - ArrayType, - type ClassProperty, - ClassType, - EnumType, - MapType, - type Type, - type TypeKind, - UnionType -} from "../Type"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; -import { directlyReachableTypes, isNamedType, matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; - -const pascalValue: [string, NamingStyle] = ["pascal-case", "pascal"]; -const underscoreValue: [string, NamingStyle] = ["underscore-case", "underscore"]; -const camelValue: [string, NamingStyle] = ["camel-case", "camel"]; -const upperUnderscoreValue: [string, NamingStyle] = ["upper-underscore-case", "upper-underscore"]; -const pascalUpperAcronymsValue: [string, NamingStyle] = ["pascal-case-upper-acronyms", "pascal-upper-acronyms"]; -const camelUpperAcronymsValue: [string, NamingStyle] = ["camel-case-upper-acronyms", "camel-upper-acronyms"]; - -export const cPlusPlusOptions = { - typeSourceStyle: new EnumOption( - "source-style", - "Source code generation type, whether to generate single or multiple source files", - [ - ["single-source", true], - ["multi-source", false] - ], - "single-source", - "secondary" - ), - includeLocation: new EnumOption( - "include-location", - "Whether json.hpp is to be located globally or locally", - [ - ["local-include", true], - ["global-include", false] - ], - "local-include", - "secondary" - ), - codeFormat: new EnumOption( - "code-format", - "Generate classes with getters/setters, instead of structs", - [ - ["with-struct", false], - ["with-getter-setter", true] - ], - "with-getter-setter" - ), - wstring: new EnumOption( - "wstring", - "Store strings using Utf-16 std::wstring, rather than Utf-8 std::string", - [ - ["use-string", false], - ["use-wstring", true] - ], - "use-string" - ), - westConst: new EnumOption( - "const-style", - "Put const to the left/west (const T) or right/east (T const)", - [ - ["west-const", true], - ["east-const", false] - ], - "west-const" - ), - justTypes: new BooleanOption("just-types", "Plain types only", false), - namespace: new StringOption("namespace", "Name of the generated namespace(s)", "NAME", "quicktype"), - enumType: new StringOption("enum-type", "Type of enum class", "NAME", "int", "secondary"), - typeNamingStyle: new EnumOption("type-style", "Naming style for types", [ - pascalValue, - underscoreValue, - camelValue, - upperUnderscoreValue, - pascalUpperAcronymsValue, - camelUpperAcronymsValue - ]), - memberNamingStyle: new EnumOption("member-style", "Naming style for members", [ - underscoreValue, - pascalValue, - camelValue, - upperUnderscoreValue, - pascalUpperAcronymsValue, - camelUpperAcronymsValue - ]), - enumeratorNamingStyle: new EnumOption("enumerator-style", "Naming style for enumerators", [ - upperUnderscoreValue, - underscoreValue, - pascalValue, - camelValue, - pascalUpperAcronymsValue, - camelUpperAcronymsValue - ]), - boost: new BooleanOption("boost", "Require a dependency on boost. Without boost, C++17 is required", true), - hideNullOptional: new BooleanOption("hide-null-optional", "Hide null value for optional field", false) -}; - -export class CPlusPlusTargetLanguage extends TargetLanguage { - public constructor(displayName = "C++", names: string[] = ["c++", "cpp", "cplusplus"], extension = "cpp") { - super(displayName, names, extension); - } - - protected getOptions(): Array> { - return [ - cPlusPlusOptions.justTypes, - cPlusPlusOptions.namespace, - cPlusPlusOptions.codeFormat, - cPlusPlusOptions.wstring, - cPlusPlusOptions.westConst, - cPlusPlusOptions.typeSourceStyle, - cPlusPlusOptions.includeLocation, - cPlusPlusOptions.typeNamingStyle, - cPlusPlusOptions.memberNamingStyle, - cPlusPlusOptions.enumeratorNamingStyle, - cPlusPlusOptions.enumType, - cPlusPlusOptions.boost, - cPlusPlusOptions.hideNullOptional - ]; - } - - public get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - public get supportsOptionalClassProperties(): boolean { - return true; - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): CPlusPlusRenderer { - return new CPlusPlusRenderer(this, renderContext, getOptionValues(cPlusPlusOptions, untypedOptionValues)); - } -} - -function constraintsForType(t: Type): - | { - minMax?: MinMaxConstraint; - minMaxLength?: MinMaxConstraint; - pattern?: string; - } - | undefined { - const minMax = minMaxValueForType(t); - const minMaxLength = minMaxLengthForType(t); - const pattern = patternForType(t); - if (minMax === undefined && minMaxLength === undefined && pattern === undefined) return undefined; - return { minMax, minMaxLength, pattern }; -} - -const legalizeName = legalizeCharacters(cp => isAscii(cp) && isLetterOrUnderscoreOrDigit(cp)); - -const keywords = [ - "alignas", - "alignof", - "and", - "and_eq", - "asm", - "atomic_cancel", - "atomic_commit", - "atomic_noexcept", - "auto", - "bitand", - "bitor", - "bool", - "break", - "case", - "catch", - "char", - "char16_t", - "char32_t", - "class", - "compl", - "concept", - "const", - "constexpr", - "const_cast", - "continue", - "co_await", - "co_return", - "co_yield", - "decltype", - "default", - "delete", - "do", - "double", - "dynamic_cast", - "else", - "enum", - "explicit", - "export", - "extern", - "false", - "float", - "for", - "friend", - "goto", - "if", - "import", - "inline", - "int", - "long", - "module", - "mutable", - "namespace", - "new", - "noexcept", - "not", - "not_eq", - "nullptr", - "operator", - "or", - "or_eq", - "private", - "protected", - "public", - "register", - "reinterpret_cast", - "requires", - "return", - "short", - "signed", - "sizeof", - "static", - "static_assert", - "static_cast", - "struct", - "switch", - "synchronized", - "template", - "this", - "thread_local", - "throw", - "true", - "try", - "typedef", - "typeid", - "typename", - "union", - "unsigned", - "using", - "virtual", - "void", - "volatile", - "wchar_t", - "while", - "xor", - "xor_eq", - "override", - "final", - "transaction_safe", - "transaction_safe_dynamic", - "NULL" -]; - -/// Type to use as an optional if cycle breaking is required -const optionalAsSharedType = "std::shared_ptr"; -/// Factory to use when creating an optional if cycle breaking is required -const optionalFactoryAsSharedType = "std::make_shared"; - -/** - * To be able to support circles in multiple files - - * e.g. class#A using class#B using class#A (obviously not directly, - * but in vector or in variant) we can forward declare them; - */ -export enum IncludeKind { - ForwardDeclare = "ForwardDeclare", - Include = "Include" -} - -// FIXME: make these string enums eventually -export enum GlobalNames { - ClassMemberConstraints = 1, - ClassMemberConstraintException = 2, - ValueTooLowException = 3, - ValueTooHighException = 4, - ValueTooShortException = 5, - ValueTooLongException = 6, - InvalidPatternException = 7, - CheckConstraint = 8 -} - -// FIXME: make these string enums eventually -export enum MemberNames { - MinIntValue = 1, - GetMinIntValue = 2, - SetMinIntValue = 3, - MaxIntValue = 4, - GetMaxIntValue = 5, - SetMaxIntValue = 6, - MinDoubleValue = 7, - GetMinDoubleValue = 8, - SetMinDoubleValue = 9, - MaxDoubleValue = 10, - GetMaxDoubleValue = 11, - SetMaxDoubleValue = 12, - MinLength = 13, - GetMinLength = 14, - SetMinLength = 15, - MaxLength = 16, - GetMaxLength = 17, - SetMaxLength = 18, - Pattern = 19, - GetPattern = 20, - SetPattern = 21 -} - -interface ConstraintMember { - cppConstType?: string; - cppType: string; - getter: MemberNames; - name: MemberNames; - setter: MemberNames; -} - -export interface IncludeRecord { - kind: IncludeKind | undefined /** How to include that */; - typeKind: TypeKind | undefined /** What exactly to include */; -} - -export interface TypeRecord { - forceInclude: boolean; - level: number; - name: Name; - type: Type; - variant: boolean; -} - -/** - * We map each and every unique type to a include kind, e.g. how - * to include the given type - */ -export type IncludeMap = Map; - -export interface TypeContext { - inJsonNamespace: boolean; - needsForwardIndirection: boolean; - needsOptionalIndirection: boolean; -} - -interface StringType { - createStringLiteral: (inner: Sourcelike) => Sourcelike; - emitHelperFunctions: () => void; - getConstType: () => string; - getRegex: () => string; - getSMatch: () => string; - getType: () => string; - wrapEncodingChange: ( - qualifier: Sourcelike[], - fromType: Sourcelike, - toType: Sourcelike, - inner: Sourcelike - ) => Sourcelike; - wrapToString: (inner: Sourcelike) => Sourcelike; -} - -function addQualifier(qualifier: Sourcelike, qualified: Sourcelike[]): Sourcelike[] { - if (qualified.length === 0) { - return []; - } - - return [qualifier, qualified]; -} - -class WrappingCode { - public constructor( - private readonly start: Sourcelike[], - private readonly end: Sourcelike[] - ) {} - - public wrap(qualifier: Sourcelike, inner: Sourcelike): Sourcelike { - return [addQualifier(qualifier, this.start), inner, this.end]; - } -} - -class BaseString { - public _stringType: string; - - public _constStringType: string; - - public _smatch: string; - - public _regex: string; - - public _stringLiteralPrefix: string; - - public _toString: WrappingCode; - - public _encodingClass: Sourcelike; - - public _encodingFunction: Sourcelike; - - public constructor( - stringType: string, - constStringType: string, - smatch: string, - regex: string, - stringLiteralPrefix: string, - toString: WrappingCode, - encodingClass: string, - encodingFunction: string - ) { - this._stringType = stringType; - this._constStringType = constStringType; - this._smatch = smatch; - this._regex = regex; - this._stringLiteralPrefix = stringLiteralPrefix; - this._toString = toString; - this._encodingClass = encodingClass; - this._encodingFunction = encodingFunction; - } - - public getType(): string { - return this._stringType; - } - - public getConstType(): string { - return this._constStringType; - } - - public getSMatch(): string { - return this._smatch; - } - - public getRegex(): string { - return this._regex; - } - - public createStringLiteral(inner: Sourcelike): Sourcelike { - return [this._stringLiteralPrefix, '"', inner, '"']; - } - - public wrapToString(inner: Sourcelike): Sourcelike { - return this._toString.wrap([], inner); - } -} + BaseString, + type ConstraintMember, + GlobalNames, + IncludeKind, + type IncludeMap, + type IncludeRecord, + MemberNames, + type StringType, + type TypeContext, + type TypeRecord, + WrappingCode, + addQualifier, + constraintsForType, + legalizeName, + optionalAsSharedType, + optionalFactoryAsSharedType +} from "./utils"; export class CPlusPlusRenderer extends ConvenienceRenderer { /** diff --git a/packages/quicktype-core/src/language/CPlusPlus/constants.ts b/packages/quicktype-core/src/language/CPlusPlus/constants.ts new file mode 100644 index 000000000..4ed53bd81 --- /dev/null +++ b/packages/quicktype-core/src/language/CPlusPlus/constants.ts @@ -0,0 +1,103 @@ + +export const keywords = [ + "alignas", + "alignof", + "and", + "and_eq", + "asm", + "atomic_cancel", + "atomic_commit", + "atomic_noexcept", + "auto", + "bitand", + "bitor", + "bool", + "break", + "case", + "catch", + "char", + "char16_t", + "char32_t", + "class", + "compl", + "concept", + "const", + "constexpr", + "const_cast", + "continue", + "co_await", + "co_return", + "co_yield", + "decltype", + "default", + "delete", + "do", + "double", + "dynamic_cast", + "else", + "enum", + "explicit", + "export", + "extern", + "false", + "float", + "for", + "friend", + "goto", + "if", + "import", + "inline", + "int", + "long", + "module", + "mutable", + "namespace", + "new", + "noexcept", + "not", + "not_eq", + "nullptr", + "operator", + "or", + "or_eq", + "private", + "protected", + "public", + "register", + "reinterpret_cast", + "requires", + "return", + "short", + "signed", + "sizeof", + "static", + "static_assert", + "static_cast", + "struct", + "switch", + "synchronized", + "template", + "this", + "thread_local", + "throw", + "true", + "try", + "typedef", + "typeid", + "typename", + "union", + "unsigned", + "using", + "virtual", + "void", + "volatile", + "wchar_t", + "while", + "xor", + "xor_eq", + "override", + "final", + "transaction_safe", + "transaction_safe_dynamic", + "NULL" +] as const; diff --git a/packages/quicktype-core/src/language/CPlusPlus/index.ts b/packages/quicktype-core/src/language/CPlusPlus/index.ts new file mode 100644 index 000000000..8ee7d4d66 --- /dev/null +++ b/packages/quicktype-core/src/language/CPlusPlus/index.ts @@ -0,0 +1,2 @@ +export { CPlusPlusTargetLanguage, cPlusPlusOptions } from "./language"; +export { CPlusPlusRenderer } from "./CPlusPlusRenderer"; diff --git a/packages/quicktype-core/src/language/CPlusPlus/language.ts b/packages/quicktype-core/src/language/CPlusPlus/language.ts new file mode 100644 index 000000000..292d21a11 --- /dev/null +++ b/packages/quicktype-core/src/language/CPlusPlus/language.ts @@ -0,0 +1,129 @@ +import { type RenderContext } from "../../Renderer"; +import { BooleanOption, EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { type NamingStyle } from "../../support/Strings"; +import { TargetLanguage } from "../../TargetLanguage"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; + +import { CPlusPlusRenderer } from "./CPlusPlusRenderer"; + +const pascalValue: [string, NamingStyle] = ["pascal-case", "pascal"]; +const underscoreValue: [string, NamingStyle] = ["underscore-case", "underscore"]; +const camelValue: [string, NamingStyle] = ["camel-case", "camel"]; +const upperUnderscoreValue: [string, NamingStyle] = ["upper-underscore-case", "upper-underscore"]; +const pascalUpperAcronymsValue: [string, NamingStyle] = ["pascal-case-upper-acronyms", "pascal-upper-acronyms"]; +const camelUpperAcronymsValue: [string, NamingStyle] = ["camel-case-upper-acronyms", "camel-upper-acronyms"]; + +export const cPlusPlusOptions = { + typeSourceStyle: new EnumOption( + "source-style", + "Source code generation type, whether to generate single or multiple source files", + [ + ["single-source", true], + ["multi-source", false] + ], + "single-source", + "secondary" + ), + includeLocation: new EnumOption( + "include-location", + "Whether json.hpp is to be located globally or locally", + [ + ["local-include", true], + ["global-include", false] + ], + "local-include", + "secondary" + ), + codeFormat: new EnumOption( + "code-format", + "Generate classes with getters/setters, instead of structs", + [ + ["with-struct", false], + ["with-getter-setter", true] + ], + "with-getter-setter" + ), + wstring: new EnumOption( + "wstring", + "Store strings using Utf-16 std::wstring, rather than Utf-8 std::string", + [ + ["use-string", false], + ["use-wstring", true] + ], + "use-string" + ), + westConst: new EnumOption( + "const-style", + "Put const to the left/west (const T) or right/east (T const)", + [ + ["west-const", true], + ["east-const", false] + ], + "west-const" + ), + justTypes: new BooleanOption("just-types", "Plain types only", false), + namespace: new StringOption("namespace", "Name of the generated namespace(s)", "NAME", "quicktype"), + enumType: new StringOption("enum-type", "Type of enum class", "NAME", "int", "secondary"), + typeNamingStyle: new EnumOption("type-style", "Naming style for types", [ + pascalValue, + underscoreValue, + camelValue, + upperUnderscoreValue, + pascalUpperAcronymsValue, + camelUpperAcronymsValue + ]), + memberNamingStyle: new EnumOption("member-style", "Naming style for members", [ + underscoreValue, + pascalValue, + camelValue, + upperUnderscoreValue, + pascalUpperAcronymsValue, + camelUpperAcronymsValue + ]), + enumeratorNamingStyle: new EnumOption("enumerator-style", "Naming style for enumerators", [ + upperUnderscoreValue, + underscoreValue, + pascalValue, + camelValue, + pascalUpperAcronymsValue, + camelUpperAcronymsValue + ]), + boost: new BooleanOption("boost", "Require a dependency on boost. Without boost, C++17 is required", true), + hideNullOptional: new BooleanOption("hide-null-optional", "Hide null value for optional field", false) +}; + +export class CPlusPlusTargetLanguage extends TargetLanguage { + public constructor(displayName = "C++", names: string[] = ["c++", "cpp", "cplusplus"], extension = "cpp") { + super(displayName, names, extension); + } + + protected getOptions(): Array> { + return [ + cPlusPlusOptions.justTypes, + cPlusPlusOptions.namespace, + cPlusPlusOptions.codeFormat, + cPlusPlusOptions.wstring, + cPlusPlusOptions.westConst, + cPlusPlusOptions.typeSourceStyle, + cPlusPlusOptions.includeLocation, + cPlusPlusOptions.typeNamingStyle, + cPlusPlusOptions.memberNamingStyle, + cPlusPlusOptions.enumeratorNamingStyle, + cPlusPlusOptions.enumType, + cPlusPlusOptions.boost, + cPlusPlusOptions.hideNullOptional + ]; + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): CPlusPlusRenderer { + return new CPlusPlusRenderer(this, renderContext, getOptionValues(cPlusPlusOptions, untypedOptionValues)); + } +} diff --git a/packages/quicktype-core/src/language/CPlusPlus/utils.ts b/packages/quicktype-core/src/language/CPlusPlus/utils.ts new file mode 100644 index 000000000..f93ce5d54 --- /dev/null +++ b/packages/quicktype-core/src/language/CPlusPlus/utils.ts @@ -0,0 +1,208 @@ +import { + type MinMaxConstraint, + minMaxLengthForType, + minMaxValueForType, + patternForType +} from "../../attributes/Constraints"; +import { type Name } from "../../Naming"; +import { type Sourcelike } from "../../Source"; +import { isAscii, isLetterOrUnderscoreOrDigit, legalizeCharacters } from "../../support/Strings"; +import { type Type, type TypeKind } from "../../Type"; + +export function constraintsForType(t: Type): + | { + minMax?: MinMaxConstraint; + minMaxLength?: MinMaxConstraint; + pattern?: string; + } + | undefined { + const minMax = minMaxValueForType(t); + const minMaxLength = minMaxLengthForType(t); + const pattern = patternForType(t); + if (minMax === undefined && minMaxLength === undefined && pattern === undefined) return undefined; + return { minMax, minMaxLength, pattern }; +} + +export const legalizeName = legalizeCharacters(cp => isAscii(cp) && isLetterOrUnderscoreOrDigit(cp)); + +/// Type to use as an optional if cycle breaking is required +export const optionalAsSharedType = "std::shared_ptr"; +/// Factory to use when creating an optional if cycle breaking is required +export const optionalFactoryAsSharedType = "std::make_shared"; + +/** + * To be able to support circles in multiple files - + * e.g. class#A using class#B using class#A (obviously not directly, + * but in vector or in variant) we can forward declare them; + */ +export enum IncludeKind { + ForwardDeclare = "ForwardDeclare", + Include = "Include" +} + +// FIXME: make these string enums eventually +export enum GlobalNames { + ClassMemberConstraints = 1, + ClassMemberConstraintException = 2, + ValueTooLowException = 3, + ValueTooHighException = 4, + ValueTooShortException = 5, + ValueTooLongException = 6, + InvalidPatternException = 7, + CheckConstraint = 8 +} + +// FIXME: make these string enums eventually +export enum MemberNames { + MinIntValue = 1, + GetMinIntValue = 2, + SetMinIntValue = 3, + MaxIntValue = 4, + GetMaxIntValue = 5, + SetMaxIntValue = 6, + MinDoubleValue = 7, + GetMinDoubleValue = 8, + SetMinDoubleValue = 9, + MaxDoubleValue = 10, + GetMaxDoubleValue = 11, + SetMaxDoubleValue = 12, + MinLength = 13, + GetMinLength = 14, + SetMinLength = 15, + MaxLength = 16, + GetMaxLength = 17, + SetMaxLength = 18, + Pattern = 19, + GetPattern = 20, + SetPattern = 21 +} + +export interface ConstraintMember { + cppConstType?: string; + cppType: string; + getter: MemberNames; + name: MemberNames; + setter: MemberNames; +} + +export interface IncludeRecord { + kind: IncludeKind | undefined /** How to include that */; + typeKind: TypeKind | undefined /** What exactly to include */; +} + +export interface TypeRecord { + forceInclude: boolean; + level: number; + name: Name; + type: Type; + variant: boolean; +} + +/** + * We map each and every unique type to a include kind, e.g. how + * to include the given type + */ +export type IncludeMap = Map; + +export interface TypeContext { + inJsonNamespace: boolean; + needsForwardIndirection: boolean; + needsOptionalIndirection: boolean; +} + +export interface StringType { + createStringLiteral: (inner: Sourcelike) => Sourcelike; + emitHelperFunctions: () => void; + getConstType: () => string; + getRegex: () => string; + getSMatch: () => string; + getType: () => string; + wrapEncodingChange: ( + qualifier: Sourcelike[], + fromType: Sourcelike, + toType: Sourcelike, + inner: Sourcelike + ) => Sourcelike; + wrapToString: (inner: Sourcelike) => Sourcelike; +} + +export function addQualifier(qualifier: Sourcelike, qualified: Sourcelike[]): Sourcelike[] { + if (qualified.length === 0) { + return []; + } + + return [qualifier, qualified]; +} + +class WrappingCode { + public constructor( + private readonly start: Sourcelike[], + private readonly end: Sourcelike[] + ) {} + + public wrap(qualifier: Sourcelike, inner: Sourcelike): Sourcelike { + return [addQualifier(qualifier, this.start), inner, this.end]; + } +} + +export class BaseString { + public _stringType: string; + + public _constStringType: string; + + public _smatch: string; + + public _regex: string; + + public _stringLiteralPrefix: string; + + public _toString: WrappingCode; + + public _encodingClass: Sourcelike; + + public _encodingFunction: Sourcelike; + + public constructor( + stringType: string, + constStringType: string, + smatch: string, + regex: string, + stringLiteralPrefix: string, + toString: WrappingCode, + encodingClass: string, + encodingFunction: string + ) { + this._stringType = stringType; + this._constStringType = constStringType; + this._smatch = smatch; + this._regex = regex; + this._stringLiteralPrefix = stringLiteralPrefix; + this._toString = toString; + this._encodingClass = encodingClass; + this._encodingFunction = encodingFunction; + } + + public getType(): string { + return this._stringType; + } + + public getConstType(): string { + return this._constStringType; + } + + public getSMatch(): string { + return this._smatch; + } + + public getRegex(): string { + return this._regex; + } + + public createStringLiteral(inner: Sourcelike): Sourcelike { + return [this._stringLiteralPrefix, '"', inner, '"']; + } + + public wrapToString(inner: Sourcelike): Sourcelike { + return this._toString.wrap([], inner); + } +} diff --git a/packages/quicktype-core/src/language/CSharp.ts b/packages/quicktype-core/src/language/CSharp.ts deleted file mode 100644 index 331345d66..000000000 --- a/packages/quicktype-core/src/language/CSharp.ts +++ /dev/null @@ -1,2498 +0,0 @@ -import { arrayIntercalate } from "collection-utils"; -import unicode from "unicode-properties"; - -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { minMaxLengthForType, minMaxValueForType } from "../attributes/Constraints"; -import { ConvenienceRenderer, type ForbiddenWordsInfo, inferredNameOrder } from "../ConvenienceRenderer"; -import { DependencyName, type Name, type Namer, SimpleName, funPrefixNamer } from "../Naming"; -import { type RenderContext } from "../Renderer"; -import { - BooleanOption, - EnumOption, - type Option, - type OptionValues, - StringOption, - getOptionValues -} from "../RendererOptions"; -import { type Sourcelike, maybeAnnotated, modifySource } from "../Source"; -import { - type WordInName, - camelCase, - combineWords, - firstUpperWordStyle, - splitIntoWords, - utf16LegalizeCharacters, - utf16StringEscape -} from "../support/Strings"; -import { assert, assertNever, defined, panic } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; -import { - ArrayDecodingTransformer, - ArrayEncodingTransformer, - ChoiceTransformer, - DecodingChoiceTransformer, - DecodingTransformer, - EncodingTransformer, - MinMaxLengthCheckTransformer, - MinMaxValueTransformer, - ParseStringTransformer, - StringMatchTransformer, - StringProducerTransformer, - StringifyTransformer, - type Transformation, - type Transformer, - UnionInstantiationTransformer, - UnionMemberMatchTransformer, - followTargetType, - transformationForType -} from "../Transformers"; -import { - ArrayType, - type ClassProperty, - ClassType, - EnumType, - type PrimitiveStringTypeKind, - type PrimitiveType, - type TransformedStringTypeKind, - type Type, - UnionType -} from "../Type"; -import { type StringTypeMapping } from "../TypeBuilder"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; -import { directlyReachableSingleNamedType, matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; - -export enum Framework { - Newtonsoft = "Newtonsoft", - SystemTextJson = "SystemTextJson" -} - -export type Version = 5 | 6; -export interface OutputFeatures { - attributes: boolean; - helpers: boolean; -} - -export enum AccessModifier { - None = "None", - Public = "Public", - Internal = "Internal" -} - -export type CSharpTypeForAny = "object" | "dynamic"; - -function noFollow(t: Type): Type { - return t; -} - -function needTransformerForType(t: Type): "automatic" | "manual" | "nullable" | "none" { - if (t instanceof UnionType) { - const maybeNullable = nullableFromUnion(t); - if (maybeNullable === null) return "automatic"; - if (needTransformerForType(maybeNullable) === "manual") return "nullable"; - return "none"; - } - - if (t instanceof ArrayType) { - const itemsNeed = needTransformerForType(t.items); - if (itemsNeed === "manual" || itemsNeed === "nullable") return "automatic"; - return "none"; - } - - if (t instanceof EnumType) return "automatic"; - if (t.kind === "double") return minMaxValueForType(t) !== undefined ? "manual" : "none"; - if (t.kind === "integer-string" || t.kind === "bool-string") return "manual"; - if (t.kind === "string") { - return minMaxLengthForType(t) !== undefined ? "manual" : "none"; - } - - return "none"; -} - -function alwaysApplyTransformation(xf: Transformation): boolean { - const t = xf.targetType; - if (t instanceof EnumType) return true; - if (t instanceof UnionType) return nullableFromUnion(t) === null; - return false; -} - -/** - * The C# type for a given transformed string type. - */ -function csTypeForTransformedStringType(t: PrimitiveType): Sourcelike { - switch (t.kind) { - case "date-time": - return "DateTimeOffset"; - case "uuid": - return "Guid"; - case "uri": - return "Uri"; - default: - return panic(`Transformed string type ${t.kind} not supported`); - } -} - -export const cSharpOptions = { - framework: new EnumOption( - "framework", - "Serialization framework", - [ - ["NewtonSoft", Framework.Newtonsoft], - ["SystemTextJson", Framework.SystemTextJson] - ], - "NewtonSoft" - ), - useList: new EnumOption("array-type", "Use T[] or List", [ - ["array", false], - ["list", true] - ]), - dense: new EnumOption( - "density", - "Property density", - [ - ["normal", false], - ["dense", true] - ], - "normal", - "secondary" - ), - // FIXME: Do this via a configurable named eventually. - namespace: new StringOption("namespace", "Generated namespace", "NAME", "QuickType"), - version: new EnumOption( - "csharp-version", - "C# version", - [ - ["5", 5], - ["6", 6] - ], - "6", - "secondary" - ), - virtual: new BooleanOption("virtual", "Generate virtual properties", false), - typeForAny: new EnumOption( - "any-type", - 'Type to use for "any"', - [ - ["object", "object"], - ["dynamic", "dynamic"] - ], - "object", - "secondary" - ), - useDecimal: new EnumOption( - "number-type", - "Type to use for numbers", - [ - ["double", false], - ["decimal", true] - ], - "double", - "secondary" - ), - features: new EnumOption("features", "Output features", [ - ["complete", { namespaces: true, helpers: true, attributes: true }], - ["attributes-only", { namespaces: true, helpers: false, attributes: true }], - ["just-types-and-namespace", { namespaces: true, helpers: false, attributes: false }], - ["just-types", { namespaces: true, helpers: false, attributes: false }] - ]), - baseclass: new EnumOption( - "base-class", - "Base class", - [ - ["EntityData", "EntityData"], - ["Object", undefined] - ], - "Object", - "secondary" - ), - checkRequired: new BooleanOption("check-required", "Fail if required properties are missing", false), - keepPropertyName: new BooleanOption("keep-property-name", "Keep original field name generate", false) -}; - -export class CSharpTargetLanguage extends TargetLanguage { - public constructor() { - super("C#", ["cs", "csharp"], "cs"); - } - - protected getOptions(): Array> { - return [ - cSharpOptions.framework, - cSharpOptions.namespace, - cSharpOptions.version, - cSharpOptions.dense, - cSharpOptions.useList, - cSharpOptions.useDecimal, - cSharpOptions.typeForAny, - cSharpOptions.virtual, - cSharpOptions.features, - cSharpOptions.baseclass, - cSharpOptions.checkRequired, - cSharpOptions.keepPropertyName - ]; - } - - public get stringTypeMapping(): StringTypeMapping { - const mapping: Map = new Map(); - mapping.set("date", "date-time"); - mapping.set("time", "date-time"); - mapping.set("date-time", "date-time"); - mapping.set("uuid", "uuid"); - mapping.set("uri", "uri"); - mapping.set("integer-string", "integer-string"); - mapping.set("bool-string", "bool-string"); - return mapping; - } - - public get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - public get supportsOptionalClassProperties(): boolean { - return true; - } - - public needsTransformerForType(t: Type): boolean { - const need = needTransformerForType(t); - return need !== "none" && need !== "nullable"; - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): ConvenienceRenderer { - const options = getOptionValues(cSharpOptions, untypedOptionValues); - - switch (options.framework) { - case Framework.Newtonsoft: - return new NewtonsoftCSharpRenderer( - this, - renderContext, - getOptionValues(newtonsoftCSharpOptions, untypedOptionValues) - ); - case Framework.SystemTextJson: - return new SystemTextJsonCSharpRenderer( - this, - renderContext, - getOptionValues(systemTextJsonCSharpOptions, untypedOptionValues) - ); - default: - return assertNever(options.framework); - } - } -} - -const namingFunction = funPrefixNamer("namer", csNameStyle); -const namingFunctionKeep = funPrefixNamer("namerKeep", csNameStyleKeep); - -// FIXME: Make a Named? -const denseJsonPropertyName = "J"; -const denseRequiredEnumName = "R"; -const denseNullValueHandlingEnumName = "N"; - -function isStartCharacter(utf16Unit: number): boolean { - if (unicode.isAlphabetic(utf16Unit)) { - return true; - } - - return utf16Unit === 0x5f; // underscore -} - -function isPartCharacter(utf16Unit: number): boolean { - const category: string = unicode.getCategory(utf16Unit); - if (["Nd", "Pc", "Mn", "Mc"].includes(category)) { - return true; - } - - return isStartCharacter(utf16Unit); -} - -const legalizeName = utf16LegalizeCharacters(isPartCharacter); - -function csNameStyle(original: string): string { - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - firstUpperWordStyle, - firstUpperWordStyle, - firstUpperWordStyle, - firstUpperWordStyle, - "", - isStartCharacter - ); -} - -function csNameStyleKeep(original: string): string { - const keywords = [ - "abstract", - "as", - "base", - "bool", - "break", - "byte", - "case", - "catch", - "char", - "checked", - "class", - "const", - "continue", - "decimal", - "default", - "delegate", - "do", - "double", - "else", - "enum", - "event", - "explicit", - "extern", - "false", - "finally", - "fixed", - "float", - "for", - "foreach", - "goto", - "if", - "implicit", - "in", - "int", - "interface", - "internal", - "is", - "lock", - "long", - "namespace", - "new", - "null", - "object", - "operator", - "out", - "override", - "params", - "private", - "protected", - "public", - "readonly", - "ref", - "return", - "sbyte", - "sealed", - "short", - "sizeof", - "stackalloc", - "static", - "string", - "struct", - "switch", - "this", - "throw", - "true", - "try", - "typeof", - "uint", - "ulong", - "unchecked", - "unsafe", - "ushort", - "using", - "virtual", - "void", - "volatile", - "while" - ]; - - const words: WordInName[] = [ - { - word: original, - isAcronym: false - } - ]; - - const result = combineWords( - words, - legalizeName, - x => x, - x => x, - x => x, - x => x, - "", - isStartCharacter - ); - - return keywords.includes(result) ? "@" + result : result; -} - -function isValueType(t: Type): boolean { - if (t instanceof UnionType) { - return nullableFromUnion(t) === null; - } - - return ["integer", "double", "bool", "enum", "date-time", "uuid"].includes(t.kind); -} - -export class CSharpRenderer extends ConvenienceRenderer { - public constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - private readonly _csOptions: OptionValues - ) { - super(targetLanguage, renderContext); - } - - protected forbiddenNamesForGlobalNamespace(): string[] { - return ["QuickType", "Type", "System", "Console", "Exception", "DateTimeOffset", "Guid", "Uri"]; - } - - protected forbiddenForObjectProperties(_: ClassType, classNamed: Name): ForbiddenWordsInfo { - return { - names: [ - classNamed, - "ToString", - "GetHashCode", - "Finalize", - "Equals", - "GetType", - "MemberwiseClone", - "ReferenceEquals" - ], - includeGlobalForbidden: false - }; - } - - protected forbiddenForUnionMembers(_: UnionType, unionNamed: Name): ForbiddenWordsInfo { - return { names: [unionNamed], includeGlobalForbidden: true }; - } - - protected makeNamedTypeNamer(): Namer { - return namingFunction; - } - - protected namerForObjectProperty(): Namer { - return this._csOptions.keepPropertyName ? namingFunctionKeep : namingFunction; - } - - protected makeUnionMemberNamer(): Namer { - return namingFunction; - } - - protected makeEnumCaseNamer(): Namer { - return namingFunction; - } - - protected unionNeedsName(u: UnionType): boolean { - return nullableFromUnion(u) === null; - } - - protected namedTypeToNameForTopLevel(type: Type): Type | undefined { - // If the top-level type doesn't contain any classes or unions - // we have to define a class just for the `FromJson` method, in - // emitFromJsonForTopLevel. - return directlyReachableSingleNamedType(type); - } - - protected emitBlock(f: () => void, semicolon = false): void { - this.emitLine("{"); - this.indent(f); - this.emitLine("}", semicolon ? ";" : ""); - } - - protected get doubleType(): string { - return this._csOptions.useDecimal ? "decimal" : "double"; - } - - protected csType(t: Type, follow: (t: Type) => Type = followTargetType, withIssues = false): Sourcelike { - const actualType = follow(t); - return matchType( - actualType, - _anyType => maybeAnnotated(withIssues, anyTypeIssueAnnotation, this._csOptions.typeForAny), - _nullType => maybeAnnotated(withIssues, nullTypeIssueAnnotation, this._csOptions.typeForAny), - _boolType => "bool", - _integerType => "long", - _doubleType => this.doubleType, - _stringType => "string", - arrayType => { - const itemsType = this.csType(arrayType.items, follow, withIssues); - if (this._csOptions.useList) { - return ["List<", itemsType, ">"]; - } else { - return [itemsType, "[]"]; - } - }, - classType => this.nameForNamedType(classType), - mapType => ["Dictionary"], - enumType => this.nameForNamedType(enumType), - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) return this.nullableCSType(nullable, noFollow); - return this.nameForNamedType(unionType); - }, - transformedStringType => csTypeForTransformedStringType(transformedStringType) - ); - } - - protected nullableCSType(t: Type, follow: (t: Type) => Type = followTargetType, withIssues = false): Sourcelike { - t = followTargetType(t); - const csType = this.csType(t, follow, withIssues); - if (isValueType(t)) { - return [csType, "?"]; - } else { - return csType; - } - } - - protected baseclassForType(_t: Type): Sourcelike | undefined { - return undefined; - } - - protected emitType( - description: string[] | undefined, - accessModifier: AccessModifier, - declaration: Sourcelike, - name: Sourcelike, - baseclass: Sourcelike | undefined, - emitter: () => void - ): void { - switch (accessModifier) { - case AccessModifier.Public: - declaration = ["public ", declaration]; - break; - case AccessModifier.Internal: - declaration = ["internal ", declaration]; - break; - default: - break; - } - - this.emitDescription(description); - if (baseclass === undefined) { - this.emitLine(declaration, " ", name); - } else { - this.emitLine(declaration, " ", name, " : ", baseclass); - } - - this.emitBlock(emitter); - } - - protected attributesForProperty( - _property: ClassProperty, - _name: Name, - _c: ClassType, - _jsonName: string - ): Sourcelike[] | undefined { - return undefined; - } - - protected propertyDefinition(property: ClassProperty, name: Name, _c: ClassType, _jsonName: string): Sourcelike { - const t = property.type; - const csType = property.isOptional - ? this.nullableCSType(t, followTargetType, true) - : this.csType(t, followTargetType, true); - - const propertyArray = ["public "]; - - if (this._csOptions.virtual) propertyArray.push("virtual "); - - return [...propertyArray, csType, " ", name, " { get; set; }"]; - } - - protected emitDescriptionBlock(lines: Sourcelike[]): void { - const start = "/// "; - if (this._csOptions.dense) { - this.emitLine(start, lines.join("; "), ""); - } else { - this.emitCommentLines(lines, { lineStart: "/// ", beforeComment: start, afterComment: "/// " }); - } - } - - protected blankLinesBetweenAttributes(): boolean { - return false; - } - - private emitClassDefinition(c: ClassType, className: Name): void { - this.emitType( - this.descriptionForType(c), - AccessModifier.Public, - "partial class", - className, - this.baseclassForType(c), - () => { - if (c.getProperties().size === 0) return; - const blankLines = this.blankLinesBetweenAttributes() ? "interposing" : "none"; - let columns: Sourcelike[][] = []; - let isFirstProperty = true; - let previousDescription: string[] | undefined = undefined; - this.forEachClassProperty(c, blankLines, (name, jsonName, p) => { - const attributes = this.attributesForProperty(p, name, c, jsonName); - const description = this.descriptionForClassProperty(c, jsonName); - const property = this.propertyDefinition(p, name, c, jsonName); - if (attributes === undefined) { - if ( - // Descriptions should be preceded by an empty line - (!isFirstProperty && description !== undefined) || - // If the previous property has a description, leave an empty line - previousDescription !== undefined - ) { - this.ensureBlankLine(); - } - - this.emitDescription(description); - this.emitLine(property); - } else if (this._csOptions.dense && attributes.length > 0) { - const comment = description === undefined ? "" : ` // ${description.join("; ")}`; - columns.push([attributes, " ", property, comment]); - } else { - this.emitDescription(description); - for (const attribute of attributes) { - this.emitLine(attribute); - } - - this.emitLine(property); - } - - isFirstProperty = false; - previousDescription = description; - }); - if (columns.length > 0) { - this.emitTable(columns); - } - } - ); - } - - private emitUnionDefinition(u: UnionType, unionName: Name): void { - const nonNulls = removeNullFromUnion(u, true)[1]; - this.emitType( - this.descriptionForType(u), - AccessModifier.Public, - "partial struct", - unionName, - this.baseclassForType(u), - () => { - this.forEachUnionMember(u, nonNulls, "none", null, (fieldName, t) => { - const csType = this.nullableCSType(t); - this.emitLine("public ", csType, " ", fieldName, ";"); - }); - this.ensureBlankLine(); - const nullTests: Sourcelike[] = Array.from(nonNulls).map(t => [ - this.nameForUnionMember(u, t), - " == null" - ]); - this.ensureBlankLine(); - this.forEachUnionMember(u, nonNulls, "none", null, (fieldName, t) => { - const csType = this.csType(t); - this.emitExpressionMember( - ["public static implicit operator ", unionName, "(", csType, " ", fieldName, ")"], - ["new ", unionName, " { ", fieldName, " = ", fieldName, " }"] - ); - }); - if (u.findMember("null") === undefined) return; - this.emitExpressionMember("public bool IsNull", arrayIntercalate(" && ", nullTests), true); - } - ); - } - - private emitEnumDefinition(e: EnumType, enumName: Name): void { - const caseNames: Sourcelike[] = []; - this.forEachEnumCase(e, "none", name => { - if (caseNames.length > 0) caseNames.push(", "); - caseNames.push(name); - }); - this.emitDescription(this.descriptionForType(e)); - this.emitLine("public enum ", enumName, " { ", caseNames, " };"); - } - - protected emitExpressionMember(declare: Sourcelike, define: Sourcelike, isProperty = false): void { - if (this._csOptions.version === 5) { - this.emitLine(declare); - this.emitBlock(() => { - const stmt = ["return ", define, ";"]; - if (isProperty) { - this.emitLine("get"); - this.emitBlock(() => this.emitLine(stmt)); - } else { - this.emitLine(stmt); - } - }); - } else { - this.emitLine(declare, " => ", define, ";"); - } - } - - protected emitTypeSwitch( - types: Iterable, - condition: (t: T) => Sourcelike, - withBlock: boolean, - withReturn: boolean, - f: (t: T) => void - ): void { - assert(!withReturn || withBlock, "Can only have return with block"); - for (const t of types) { - this.emitLine("if (", condition(t), ")"); - if (withBlock) { - this.emitBlock(() => { - f(t); - if (withReturn) { - this.emitLine("return;"); - } - }); - } else { - this.indent(() => f(t)); - } - } - } - - protected emitUsing(ns: Sourcelike): void { - this.emitLine("using ", ns, ";"); - } - - protected emitUsings(): void { - for (const ns of ["System", "System.Collections.Generic"]) { - this.emitUsing(ns); - } - } - - protected emitRequiredHelpers(): void { - return; - } - - private emitTypesAndSupport(): void { - this.forEachObject("leading-and-interposing", (c: ClassType, name: Name) => this.emitClassDefinition(c, name)); - this.forEachEnum("leading-and-interposing", (e, name) => this.emitEnumDefinition(e, name)); - this.forEachUnion("leading-and-interposing", (u, name) => this.emitUnionDefinition(u, name)); - this.emitRequiredHelpers(); - } - - protected emitDefaultLeadingComments(): void { - return; - } - - protected emitDefaultFollowingComments(): void { - return; - } - - protected needNamespace(): boolean { - return true; - } - - protected emitSourceStructure(): void { - if (this.leadingComments !== undefined) { - this.emitComments(this.leadingComments); - } else { - this.emitDefaultLeadingComments(); - } - - this.ensureBlankLine(); - if (this.needNamespace()) { - this.emitLine("namespace ", this._csOptions.namespace); - this.emitBlock(() => { - this.emitUsings(); - this.emitTypesAndSupport(); - }); - } else { - this.emitUsings(); - this.emitTypesAndSupport(); - } - - this.emitDefaultFollowingComments(); - } -} - -export const newtonsoftCSharpOptions = Object.assign({}, cSharpOptions, {}); - -export class NewtonsoftCSharpRenderer extends CSharpRenderer { - private readonly _enumExtensionsNames = new Map(); - - private readonly _needHelpers: boolean; - - private readonly _needAttributes: boolean; - - private readonly _needNamespaces: boolean; - - public constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - private readonly _options: OptionValues - ) { - super(targetLanguage, renderContext, _options); - this._needHelpers = _options.features.helpers; - this._needAttributes = _options.features.attributes; - this._needNamespaces = _options.features.namespaces; - } - - protected forbiddenNamesForGlobalNamespace(): string[] { - const forbidden = [ - "Converter", - "JsonConverter", - "JsonSerializer", - "JsonWriter", - "JsonToken", - "Serialize", - "Newtonsoft", - "MetadataPropertyHandling", - "DateParseHandling", - "FromJson", - "Required" - ]; - if (this._options.dense) { - forbidden.push("J", "R", "N"); - } - - if (this._options.baseclass !== undefined) { - forbidden.push(this._options.baseclass); - } - - return super.forbiddenNamesForGlobalNamespace().concat(forbidden); - } - - protected forbiddenForObjectProperties(c: ClassType, className: Name): ForbiddenWordsInfo { - const result = super.forbiddenForObjectProperties(c, className); - result.names = result.names.concat(["ToJson", "FromJson", "Required"]); - return result; - } - - protected makeNameForTransformation(xf: Transformation, typeName: Name | undefined): Name { - if (typeName === undefined) { - let xfer = xf.transformer; - if (xfer instanceof DecodingTransformer && xfer.consumer !== undefined) { - xfer = xfer.consumer; - } - - return new SimpleName([`${xfer.kind}_converter`], namingFunction, inferredNameOrder + 30); - } - - return new DependencyName(namingFunction, typeName.order + 30, lookup => `${lookup(typeName)}_converter`); - } - - protected makeNamedTypeDependencyNames(t: Type, name: Name): DependencyName[] { - if (!(t instanceof EnumType)) return []; - - const extensionsName = new DependencyName( - namingFunction, - name.order + 30, - lookup => `${lookup(name)}_extensions` - ); - this._enumExtensionsNames.set(name, extensionsName); - return [extensionsName]; - } - - protected emitUsings(): void { - // FIXME: We need System.Collections.Generic whenever we have maps or use List. - if (!this._needAttributes && !this._needHelpers) return; - - super.emitUsings(); - this.ensureBlankLine(); - - for (const ns of ["System.Globalization", "Newtonsoft.Json", "Newtonsoft.Json.Converters"]) { - this.emitUsing(ns); - } - - if (this._options.dense) { - this.emitUsing([denseJsonPropertyName, " = Newtonsoft.Json.JsonPropertyAttribute"]); - this.emitUsing([denseRequiredEnumName, " = Newtonsoft.Json.Required"]); - this.emitUsing([denseNullValueHandlingEnumName, " = Newtonsoft.Json.NullValueHandling"]); - } - - if (this._options.baseclass === "EntityData") { - this.emitUsing("Microsoft.Azure.Mobile.Server"); - } - } - - protected baseclassForType(_t: Type): Sourcelike | undefined { - return this._options.baseclass; - } - - protected emitDefaultLeadingComments(): void { - if (!this._needHelpers) return; - - this.emitLine("// "); - this.emitLine("//"); - this.emitLine( - "// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do", - this.topLevels.size === 1 ? "" : " one of these", - ":" - ); - this.emitLine("//"); - this.emitLine("// using ", this._options.namespace, ";"); - this.emitLine("//"); - this.forEachTopLevel("none", (t, topLevelName) => { - let rhs: Sourcelike; - if (t instanceof EnumType) { - rhs = ["JsonConvert.DeserializeObject<", topLevelName, ">(jsonString)"]; - } else { - rhs = [topLevelName, ".FromJson(jsonString)"]; - } - - this.emitLine("// var ", modifySource(camelCase, topLevelName), " = ", rhs, ";"); - }); - } - - private converterForType(t: Type): Name | undefined { - let xf = transformationForType(t); - - if (xf === undefined && t instanceof UnionType) { - const maybeNullable = nullableFromUnion(t); - if (maybeNullable !== null) { - t = maybeNullable; - xf = transformationForType(t); - } - } - - if (xf === undefined) return undefined; - - if (alwaysApplyTransformation(xf)) return undefined; - - return defined(this.nameForTransformation(t)); - } - - protected attributesForProperty( - property: ClassProperty, - _name: Name, - _c: ClassType, - jsonName: string - ): Sourcelike[] | undefined { - if (!this._needAttributes) return undefined; - - const attributes: Sourcelike[] = []; - - const jsonProperty = this._options.dense ? denseJsonPropertyName : "JsonProperty"; - const escapedName = utf16StringEscape(jsonName); - const isNullable = followTargetType(property.type).isNullable; - const isOptional = property.isOptional; - const requiredClass = this._options.dense ? "R" : "Required"; - const nullValueHandlingClass = this._options.dense ? "N" : "NullValueHandling"; - const nullValueHandling = - isOptional && !isNullable ? [", NullValueHandling = ", nullValueHandlingClass, ".Ignore"] : []; - let required: Sourcelike; - if (!this._options.checkRequired || (isOptional && isNullable)) { - required = [nullValueHandling]; - } else if (isOptional && !isNullable) { - required = [", Required = ", requiredClass, ".DisallowNull", nullValueHandling]; - } else if (!isOptional && isNullable) { - required = [", Required = ", requiredClass, ".AllowNull"]; - } else { - required = [", Required = ", requiredClass, ".Always", nullValueHandling]; - } - - attributes.push(["[", jsonProperty, '("', escapedName, '"', required, ")]"]); - - const converter = this.converterForType(property.type); - if (converter !== undefined) { - attributes.push(["[JsonConverter(typeof(", converter, "))]"]); - } - - return attributes; - } - - protected blankLinesBetweenAttributes(): boolean { - return this._needAttributes && !this._options.dense; - } - - // The "this" type can't be `dynamic`, so we have to force it to `object`. - private topLevelResultType(t: Type): Sourcelike { - return t.kind === "any" || t.kind === "none" ? "object" : this.csType(t); - } - - private emitFromJsonForTopLevel(t: Type, name: Name): void { - if (t instanceof EnumType) return; - - let partial: string; - let typeKind: string; - const definedType = this.namedTypeToNameForTopLevel(t); - if (definedType !== undefined) { - partial = "partial "; - typeKind = definedType instanceof ClassType ? "class" : "struct"; - } else { - partial = ""; - typeKind = "class"; - } - - const csType = this.topLevelResultType(t); - this.emitType(undefined, AccessModifier.Public, [partial, typeKind], name, this.baseclassForType(t), () => { - // FIXME: Make FromJson a Named - this.emitExpressionMember( - ["public static ", csType, " FromJson(string json)"], - ["JsonConvert.DeserializeObject<", csType, ">(json, ", this._options.namespace, ".Converter.Settings)"] - ); - }); - } - - private emitDecoderSwitch(emitBody: () => void): void { - this.emitLine("switch (reader.TokenType)"); - this.emitBlock(emitBody); - } - - private emitTokenCase(tokenType: string): void { - this.emitLine("case JsonToken.", tokenType, ":"); - } - - private emitThrow(message: Sourcelike): void { - this.emitLine("throw new Exception(", message, ");"); - } - - private deserializeTypeCode(typeName: Sourcelike): Sourcelike { - return ["serializer.Deserialize<", typeName, ">(reader)"]; - } - - private serializeValueCode(value: Sourcelike): Sourcelike { - return ["serializer.Serialize(writer, ", value, ")"]; - } - - private emitSerializeClass(): void { - // FIXME: Make Serialize a Named - this.emitType(undefined, AccessModifier.Public, "static class", "Serialize", undefined, () => { - // Sometimes multiple top-levels will resolve to the same type, so we have to take care - // not to emit more than one extension method for the same type. - const seenTypes = new Set(); - this.forEachTopLevel("none", t => { - // FIXME: Make ToJson a Named - if (!seenTypes.has(t)) { - seenTypes.add(t); - this.emitExpressionMember( - ["public static string ToJson(this ", this.topLevelResultType(t), " self)"], - ["JsonConvert.SerializeObject(self, ", this._options.namespace, ".Converter.Settings)"] - ); - } - }); - }); - } - - private emitCanConvert(expr: Sourcelike): void { - this.emitExpressionMember("public override bool CanConvert(Type t)", expr); - } - - private emitReadJson(emitBody: () => void): void { - this.emitLine( - "public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)" - ); - this.emitBlock(emitBody); - } - - private emitWriteJson(variable: string, emitBody: () => void): void { - this.emitLine( - "public override void WriteJson(JsonWriter writer, object ", - variable, - ", JsonSerializer serializer)" - ); - this.emitBlock(emitBody); - } - - private converterObject(converterName: Name): Sourcelike { - // FIXME: Get a singleton - return [converterName, ".Singleton"]; - } - - private emitConverterClass(): void { - // FIXME: Make Converter a Named - const converterName: Sourcelike = ["Converter"]; - this.emitType(undefined, AccessModifier.Internal, "static class", converterName, undefined, () => { - this.emitLine("public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings"); - this.emitBlock(() => { - this.emitLine("MetadataPropertyHandling = MetadataPropertyHandling.Ignore,"); - this.emitLine("DateParseHandling = DateParseHandling.None,"); - this.emitLine("Converters ="); - this.emitLine("{"); - this.indent(() => { - for (const [t, converter] of this.typesWithNamedTransformations) { - if (alwaysApplyTransformation(defined(transformationForType(t)))) { - this.emitLine(this.converterObject(converter), ","); - } - } - - this.emitLine("new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }"); - }); - this.emitLine("},"); - }, true); - }); - } - - private emitDecoderTransformerCase( - tokenCases: string[], - variableName: string, - xfer: Transformer | undefined, - targetType: Type, - emitFinish: (value: Sourcelike) => void - ): void { - if (xfer === undefined) return; - - for (const tokenCase of tokenCases) { - this.emitTokenCase(tokenCase); - } - - this.indent(() => { - const allHandled = this.emitDecodeTransformer(xfer, targetType, emitFinish, variableName); - if (!allHandled) { - this.emitLine("break;"); - } - }); - } - - private emitConsume( - value: Sourcelike, - consumer: Transformer | undefined, - targetType: Type, - emitFinish: (variableName: Sourcelike) => void - ): boolean { - if (consumer === undefined) { - emitFinish(value); - return true; - } else { - return this.emitTransformer(value, consumer, targetType, emitFinish); - } - } - - private emitDecodeTransformer( - xfer: Transformer, - targetType: Type, - emitFinish: (value: Sourcelike) => void, - variableName = "value" - ): boolean { - if (xfer instanceof DecodingTransformer) { - const source = xfer.sourceType; - const converter = this.converterForType(targetType); - if (converter !== undefined) { - const typeSource = this.csType(targetType); - this.emitLine("var converter = ", this.converterObject(converter), ";"); - this.emitLine( - "var ", - variableName, - " = (", - typeSource, - ")converter.ReadJson(reader, typeof(", - typeSource, - "), null, serializer);" - ); - } else if (source.kind !== "null") { - let output = targetType.kind === "double" ? targetType : source; - this.emitLine("var ", variableName, " = ", this.deserializeTypeCode(this.csType(output)), ";"); - } - - return this.emitConsume(variableName, xfer.consumer, targetType, emitFinish); - } else if (xfer instanceof ArrayDecodingTransformer) { - // FIXME: Consume StartArray - if (!(targetType instanceof ArrayType)) { - return panic("Array decoding must produce an array type"); - } - - // FIXME: handle EOF - this.emitLine("reader.Read();"); - this.emitLine("var ", variableName, " = new List<", this.csType(targetType.items), ">();"); - this.emitLine("while (reader.TokenType != JsonToken.EndArray)"); - this.emitBlock(() => { - this.emitDecodeTransformer( - xfer.itemTransformer, - xfer.itemTargetType, - v => this.emitLine(variableName, ".Add(", v, ");"), - "arrayItem" - ); - // FIXME: handle EOF - this.emitLine("reader.Read();"); - }); - let result: Sourcelike = variableName; - if (!this._options.useList) { - result = [result, ".ToArray()"]; - } - - emitFinish(result); - return true; - } else if (xfer instanceof DecodingChoiceTransformer) { - this.emitDecoderSwitch(() => { - const nullTransformer = xfer.nullTransformer; - if (nullTransformer !== undefined) { - this.emitTokenCase("Null"); - this.indent(() => { - const allHandled = this.emitDecodeTransformer(nullTransformer, targetType, emitFinish, "null"); - if (!allHandled) { - this.emitLine("break"); - } - }); - } - - this.emitDecoderTransformerCase( - ["Integer"], - "integerValue", - xfer.integerTransformer, - targetType, - emitFinish - ); - this.emitDecoderTransformerCase( - xfer.integerTransformer === undefined ? ["Integer", "Float"] : ["Float"], - "doubleValue", - xfer.doubleTransformer, - targetType, - emitFinish - ); - this.emitDecoderTransformerCase(["Boolean"], "boolValue", xfer.boolTransformer, targetType, emitFinish); - this.emitDecoderTransformerCase( - ["String", "Date"], - "stringValue", - xfer.stringTransformer, - targetType, - emitFinish - ); - this.emitDecoderTransformerCase( - ["StartObject"], - "objectValue", - xfer.objectTransformer, - targetType, - emitFinish - ); - this.emitDecoderTransformerCase( - ["StartArray"], - "arrayValue", - xfer.arrayTransformer, - targetType, - emitFinish - ); - }); - return false; - } else { - return panic("Unknown transformer"); - } - } - - private stringCaseValue(t: Type, stringCase: string): Sourcelike { - if (t.kind === "string") { - return ['"', utf16StringEscape(stringCase), '"']; - } else if (t instanceof EnumType) { - return [this.nameForNamedType(t), ".", this.nameForEnumCase(t, stringCase)]; - } - - return panic(`Type ${t.kind} does not have string cases`); - } - - private emitTransformer( - variable: Sourcelike, - xfer: Transformer, - targetType: Type, - emitFinish: (value: Sourcelike) => void - ): boolean { - function directTargetType(continuation: Transformer | undefined): Type { - if (continuation === undefined) { - return targetType; - } - - return followTargetType(continuation.sourceType); - } - - if (xfer instanceof ChoiceTransformer) { - const caseXfers = xfer.transformers; - if (caseXfers.length > 1 && caseXfers.every(caseXfer => caseXfer instanceof StringMatchTransformer)) { - this.emitLine("switch (", variable, ")"); - this.emitBlock(() => { - for (const caseXfer of caseXfers) { - const matchXfer = caseXfer as StringMatchTransformer; - const value = this.stringCaseValue( - followTargetType(matchXfer.sourceType), - matchXfer.stringCase - ); - this.emitLine("case ", value, ":"); - this.indent(() => { - const allDone = this.emitTransformer( - variable, - matchXfer.transformer, - targetType, - emitFinish - ); - if (!allDone) { - this.emitLine("break;"); - } - }); - } - }); - // FIXME: Can we check for exhaustiveness? For enums it should be easy. - return false; - } else { - for (const caseXfer of caseXfers) { - this.emitTransformer(variable, caseXfer, targetType, emitFinish); - } - } - } else if (xfer instanceof UnionMemberMatchTransformer) { - const memberType = xfer.memberType; - const maybeNullable = nullableFromUnion(xfer.sourceType); - let test: Sourcelike; - let member: Sourcelike; - if (maybeNullable !== null) { - if (memberType.kind === "null") { - test = [variable, " == null"]; - member = "null"; - } else { - test = [variable, " != null"]; - member = variable; - } - } else if (memberType.kind === "null") { - test = [variable, ".IsNull"]; - member = "null"; - } else { - const memberName = this.nameForUnionMember(xfer.sourceType, memberType); - member = [variable, ".", memberName]; - test = [member, " != null"]; - } - - if (memberType.kind !== "null" && isValueType(memberType)) { - member = [member, ".Value"]; - } - - this.emitLine("if (", test, ")"); - this.emitBlock(() => this.emitTransformer(member, xfer.transformer, targetType, emitFinish)); - } else if (xfer instanceof StringMatchTransformer) { - const value = this.stringCaseValue(followTargetType(xfer.sourceType), xfer.stringCase); - this.emitLine("if (", variable, " == ", value, ")"); - this.emitBlock(() => this.emitTransformer(variable, xfer.transformer, targetType, emitFinish)); - } else if (xfer instanceof EncodingTransformer) { - const converter = this.converterForType(xfer.sourceType); - if (converter !== undefined) { - this.emitLine("var converter = ", this.converterObject(converter), ";"); - this.emitLine("converter.WriteJson(writer, ", variable, ", serializer);"); - } else { - this.emitLine(this.serializeValueCode(variable), ";"); - } - - emitFinish([]); - return true; - } else if (xfer instanceof ArrayEncodingTransformer) { - this.emitLine("writer.WriteStartArray();"); - const itemVariable = "arrayItem"; - this.emitLine("foreach (var ", itemVariable, " in ", variable, ")"); - this.emitBlock(() => { - this.emitTransformer(itemVariable, xfer.itemTransformer, xfer.itemTargetType, () => { - return; - }); - }); - this.emitLine("writer.WriteEndArray();"); - emitFinish([]); - return true; - } else if (xfer instanceof ParseStringTransformer) { - const immediateTargetType = xfer.consumer === undefined ? targetType : xfer.consumer.sourceType; - switch (immediateTargetType.kind) { - case "date-time": - this.emitLine("DateTimeOffset dt;"); - this.emitLine("if (DateTimeOffset.TryParse(", variable, ", out dt))"); - this.emitBlock(() => this.emitConsume("dt", xfer.consumer, targetType, emitFinish)); - break; - case "uuid": - this.emitLine("Guid guid;"); - this.emitLine("if (Guid.TryParse(", variable, ", out guid))"); - this.emitBlock(() => this.emitConsume("guid", xfer.consumer, targetType, emitFinish)); - break; - case "uri": - this.emitLine("try"); - this.emitBlock(() => { - this.emitLine("var uri = new Uri(", variable, ");"); - this.emitConsume("uri", xfer.consumer, targetType, emitFinish); - }); - this.emitLine("catch (UriFormatException) {}"); - break; - case "integer": - this.emitLine("long l;"); - this.emitLine("if (Int64.TryParse(", variable, ", out l))"); - this.emitBlock(() => this.emitConsume("l", xfer.consumer, targetType, emitFinish)); - break; - case "bool": - this.emitLine("bool b;"); - this.emitLine("if (Boolean.TryParse(", variable, ", out b))"); - this.emitBlock(() => this.emitConsume("b", xfer.consumer, targetType, emitFinish)); - break; - default: - return panic(`Parsing string to ${immediateTargetType.kind} not supported`); - } - } else if (xfer instanceof StringifyTransformer) { - switch (xfer.sourceType.kind) { - case "date-time": - return this.emitConsume( - [variable, '.ToString("o", System.Globalization.CultureInfo.InvariantCulture)'], - xfer.consumer, - targetType, - emitFinish - ); - case "uuid": - return this.emitConsume( - [variable, '.ToString("D", System.Globalization.CultureInfo.InvariantCulture)'], - xfer.consumer, - targetType, - emitFinish - ); - case "integer": - case "uri": - return this.emitConsume([variable, ".ToString()"], xfer.consumer, targetType, emitFinish); - case "bool": - this.emitLine("var boolString = ", variable, ' ? "true" : "false";'); - return this.emitConsume("boolString", xfer.consumer, targetType, emitFinish); - default: - return panic(`Stringifying ${xfer.sourceType.kind} not supported`); - } - } else if (xfer instanceof StringProducerTransformer) { - const value = this.stringCaseValue(directTargetType(xfer.consumer), xfer.result); - return this.emitConsume(value, xfer.consumer, targetType, emitFinish); - } else if (xfer instanceof MinMaxLengthCheckTransformer) { - const min = xfer.minLength; - const max = xfer.maxLength; - const conditions: Sourcelike[] = []; - - if (min !== undefined) { - conditions.push([variable, ".Length >= ", min.toString()]); - } - - if (max !== undefined) { - conditions.push([variable, ".Length <= ", max.toString()]); - } - - this.emitLine("if (", arrayIntercalate([" && "], conditions), ")"); - this.emitBlock(() => this.emitConsume(variable, xfer.consumer, targetType, emitFinish)); - return false; - } else if (xfer instanceof MinMaxValueTransformer) { - const min = xfer.minimum; - const max = xfer.maximum; - const conditions: Sourcelike[] = []; - - if (min !== undefined) { - conditions.push([variable, " >= ", min.toString()]); - } - - if (max !== undefined) { - conditions.push([variable, " <= ", max.toString()]); - } - - this.emitLine("if (", arrayIntercalate([" && "], conditions), ")"); - this.emitBlock(() => this.emitConsume(variable, xfer.consumer, targetType, emitFinish)); - return false; - } else if (xfer instanceof UnionInstantiationTransformer) { - if (!(targetType instanceof UnionType)) { - return panic("Union instantiation transformer must produce a union type"); - } - - const maybeNullable = nullableFromUnion(targetType); - if (maybeNullable !== null) { - emitFinish(variable); - } else { - const unionName = this.nameForNamedType(targetType); - let initializer: Sourcelike; - if (xfer.sourceType.kind === "null") { - initializer = " "; - } else { - const memberName = this.nameForUnionMember(targetType, xfer.sourceType); - initializer = [" ", memberName, " = ", variable, " "]; - } - - emitFinish(["new ", unionName, " {", initializer, "}"]); - } - - return true; - } else { - return panic("Unknown transformer"); - } - - return false; - } - - private emitTransformation(converterName: Name, t: Type): void { - const xf = defined(transformationForType(t)); - const reverse = xf.reverse; - const targetType = xf.targetType; - const xfer = xf.transformer; - this.emitType(undefined, AccessModifier.Internal, "class", converterName, "JsonConverter", () => { - const csType = this.csType(targetType); - let canConvertExpr: Sourcelike = ["t == typeof(", csType, ")"]; - const haveNullable = isValueType(targetType); - if (haveNullable) { - canConvertExpr = [canConvertExpr, " || t == typeof(", csType, "?)"]; - } - - this.emitCanConvert(canConvertExpr); - this.ensureBlankLine(); - this.emitReadJson(() => { - // FIXME: It's unsatisfying that we need this. The reason is that we not - // only match T, but also T?. If we didn't, then the T in T? would not be - // deserialized with our converter but with the default one. Can we check - // whether the type is a nullable? - // FIXME: This could duplicate one of the cases handled below in - // `emitDecodeTransformer`. - if (haveNullable && !(targetType instanceof UnionType)) { - this.emitLine("if (reader.TokenType == JsonToken.Null) return null;"); - } - - const allHandled = this.emitDecodeTransformer(xfer, targetType, v => this.emitLine("return ", v, ";")); - if (!allHandled) { - this.emitThrow(['"Cannot unmarshal type ', csType, '"']); - } - }); - this.ensureBlankLine(); - this.emitWriteJson("untypedValue", () => { - // FIXME: See above. - if (haveNullable && !(targetType instanceof UnionType)) { - this.emitLine("if (untypedValue == null)"); - this.emitBlock(() => { - this.emitLine("serializer.Serialize(writer, null);"); - this.emitLine("return;"); - }); - } - - this.emitLine("var value = (", csType, ")untypedValue;"); - const allHandled = this.emitTransformer("value", reverse.transformer, reverse.targetType, () => - this.emitLine("return;") - ); - if (!allHandled) { - this.emitThrow(['"Cannot marshal type ', csType, '"']); - } - }); - this.ensureBlankLine(); - this.emitLine("public static readonly ", converterName, " Singleton = new ", converterName, "();"); - }); - } - - protected emitRequiredHelpers(): void { - if (this._needHelpers) { - this.forEachTopLevel("leading-and-interposing", (t, n) => this.emitFromJsonForTopLevel(t, n)); - this.ensureBlankLine(); - this.emitSerializeClass(); - } - - if (this._needHelpers || (this._needAttributes && (this.haveNamedUnions || this.haveEnums))) { - this.ensureBlankLine(); - this.emitConverterClass(); - this.forEachTransformation("leading-and-interposing", (n, t) => this.emitTransformation(n, t)); - } - } - - protected needNamespace(): boolean { - return this._needNamespaces; - } -} - -export const systemTextJsonCSharpOptions = Object.assign({}, cSharpOptions, {}); - -export class SystemTextJsonCSharpRenderer extends CSharpRenderer { - private readonly _enumExtensionsNames = new Map(); - - private readonly _needHelpers: boolean; - - private readonly _needAttributes: boolean; - - private readonly _needNamespaces: boolean; - - public constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - private readonly _options: OptionValues - ) { - super(targetLanguage, renderContext, _options); - this._needHelpers = _options.features.helpers; - this._needAttributes = _options.features.attributes; - this._needNamespaces = _options.features.namespaces; - } - - protected forbiddenNamesForGlobalNamespace(): string[] { - const forbidden = [ - "Converter", - "JsonConverter", - "JsonSerializer", - "JsonWriter", - "JsonToken", - "Serialize", - "JsonSerializerOptions", - // "Newtonsoft", - // "MetadataPropertyHandling", - // "DateParseHandling", - "FromJson", - "Required" - ]; - if (this._options.dense) { - forbidden.push("J", "R", "N"); - } - - if (this._options.baseclass !== undefined) { - forbidden.push(this._options.baseclass); - } - - return super.forbiddenNamesForGlobalNamespace().concat(forbidden); - } - - protected forbiddenForObjectProperties(c: ClassType, className: Name): ForbiddenWordsInfo { - const result = super.forbiddenForObjectProperties(c, className); - result.names = result.names.concat(["ToJson", "FromJson", "Required"]); - return result; - } - - protected makeNameForTransformation(xf: Transformation, typeName: Name | undefined): Name { - if (typeName === undefined) { - let xfer = xf.transformer; - if (xfer instanceof DecodingTransformer && xfer.consumer !== undefined) { - xfer = xfer.consumer; - } - - return new SimpleName([`${xfer.kind}_converter`], namingFunction, inferredNameOrder + 30); - } - - return new DependencyName(namingFunction, typeName.order + 30, lookup => `${lookup(typeName)}_converter`); - } - - protected makeNamedTypeDependencyNames(t: Type, name: Name): DependencyName[] { - if (!(t instanceof EnumType)) return []; - - const extensionsName = new DependencyName( - namingFunction, - name.order + 30, - lookup => `${lookup(name)}_extensions` - ); - this._enumExtensionsNames.set(name, extensionsName); - return [extensionsName]; - } - - protected emitUsings(): void { - // FIXME: We need System.Collections.Generic whenever we have maps or use List. - if (!this._needAttributes && !this._needHelpers) return; - - super.emitUsings(); - this.ensureBlankLine(); - - for (const ns of ["System.Text.Json", "System.Text.Json.Serialization", "System.Globalization"]) { - this.emitUsing(ns); - } - - if (this._options.dense) { - this.emitUsing([denseJsonPropertyName, " = System.Text.Json.Serialization.JsonPropertyNameAttribute"]); - // this.emitUsing([denseRequiredEnumName, " = Newtonsoft.Json.Required"]); - this.emitUsing([denseNullValueHandlingEnumName, " = System.Text.Json.Serialization.JsonIgnoreCondition"]); - } - - if (this._options.baseclass === "EntityData") { - this.emitUsing("Microsoft.Azure.Mobile.Server"); - } - } - - protected baseclassForType(_t: Type): Sourcelike | undefined { - return this._options.baseclass; - } - - protected emitDefaultFollowingComments(): void { - if (!this._needHelpers) return; - - this.emitLine("#pragma warning restore CS8618"); - this.emitLine("#pragma warning restore CS8601"); - this.emitLine("#pragma warning restore CS8603"); - } - - protected emitDefaultLeadingComments(): void { - if (!this._needHelpers) return; - - this.emitLine("// "); - this.emitLine("//"); - this.emitLine( - "// To parse this JSON data, add NuGet 'System.Text.Json' then do", - this.topLevels.size === 1 ? "" : " one of these", - ":" - ); - this.emitLine("//"); - this.emitLine("// using ", this._options.namespace, ";"); - this.emitLine("//"); - this.forEachTopLevel("none", (t, topLevelName) => { - let rhs: Sourcelike; - if (t instanceof EnumType) { - rhs = ["JsonSerializer.Deserialize<", topLevelName, ">(jsonString)"]; - } else { - rhs = [topLevelName, ".FromJson(jsonString)"]; - } - - this.emitLine("// var ", modifySource(camelCase, topLevelName), " = ", rhs, ";"); - }); - - // fix: should this be an option? Or respond to an existing option? - this.emitLine("#nullable enable"); - this.emitLine("#pragma warning disable CS8618"); - this.emitLine("#pragma warning disable CS8601"); - this.emitLine("#pragma warning disable CS8603"); - } - - private converterForType(t: Type): Name | undefined { - let xf = transformationForType(t); - - if (xf === undefined && t instanceof UnionType) { - const maybeNullable = nullableFromUnion(t); - if (maybeNullable !== null) { - t = maybeNullable; - xf = transformationForType(t); - } - } - - if (xf === undefined) return undefined; - - if (alwaysApplyTransformation(xf)) return undefined; - - return defined(this.nameForTransformation(t)); - } - - protected attributesForProperty( - property: ClassProperty, - _name: Name, - _c: ClassType, - jsonName: string - ): Sourcelike[] | undefined { - if (!this._needAttributes) return undefined; - - const attributes: Sourcelike[] = []; - - const jsonPropertyName = this._options.dense ? denseJsonPropertyName : "JsonPropertyName"; - const escapedName = utf16StringEscape(jsonName); - const isNullable = followTargetType(property.type).isNullable; - const isOptional = property.isOptional; - - if (isOptional && !isNullable) { - attributes.push(["[", "JsonIgnore", "(Condition = JsonIgnoreCondition.WhenWritingNull)]"]); - } - - // const requiredClass = this._options.dense ? "R" : "Required"; - // const nullValueHandlingClass = this._options.dense ? "N" : "NullValueHandling"; - // const nullValueHandling = isOptional && !isNullable ? [", NullValueHandling = ", nullValueHandlingClass, ".Ignore"] : []; - // let required: Sourcelike; - // if (!this._options.checkRequired || (isOptional && isNullable)) { - // required = [nullValueHandling]; - // } else if (isOptional && !isNullable) { - // required = [", Required = ", requiredClass, ".DisallowNull", nullValueHandling]; - // } else if (!isOptional && isNullable) { - // required = [", Required = ", requiredClass, ".AllowNull"]; - // } else { - // required = [", Required = ", requiredClass, ".Always", nullValueHandling]; - // } - - attributes.push(["[", jsonPropertyName, '("', escapedName, '")]']); - - const converter = this.converterForType(property.type); - if (converter !== undefined) { - attributes.push(["[JsonConverter(typeof(", converter, "))]"]); - } - - return attributes; - } - - protected blankLinesBetweenAttributes(): boolean { - return this._needAttributes && !this._options.dense; - } - - // The "this" type can't be `dynamic`, so we have to force it to `object`. - private topLevelResultType(t: Type): Sourcelike { - return t.kind === "any" || t.kind === "none" ? "object" : this.csType(t); - } - - private emitFromJsonForTopLevel(t: Type, name: Name): void { - if (t instanceof EnumType) return; - - let partial: string; - let typeKind: string; - const definedType = this.namedTypeToNameForTopLevel(t); - if (definedType !== undefined) { - partial = "partial "; - typeKind = definedType instanceof ClassType ? "class" : "struct"; - } else { - partial = ""; - typeKind = "class"; - } - - const csType = this.topLevelResultType(t); - this.emitType(undefined, AccessModifier.Public, [partial, typeKind], name, this.baseclassForType(t), () => { - // FIXME: Make FromJson a Named - this.emitExpressionMember( - ["public static ", csType, " FromJson(string json)"], - ["JsonSerializer.Deserialize<", csType, ">(json, ", this._options.namespace, ".Converter.Settings)"] - ); - }); - } - - private emitDecoderSwitch(emitBody: () => void): void { - this.emitLine("switch (reader.TokenType)"); - this.emitBlock(emitBody); - } - - private emitTokenCase(tokenType: string): void { - this.emitLine("case JsonTokenType.", tokenType, ":"); - } - - private emitThrow(message: Sourcelike): void { - this.emitLine("throw new Exception(", message, ");"); - } - - private deserializeTypeCode(typeName: Sourcelike): Sourcelike { - switch (typeName) { - case "bool": - return ["reader.GetBoolean()"]; - case "long": - return ["reader.GetInt64()"]; - case "decimal": - return ["reader.GetDecimal()"]; - case "double": - return ["reader.GetDouble()"]; - case "string": - return ["reader.GetString()"]; - default: - return ["JsonSerializer.Deserialize<", typeName, ">(ref reader, options)"]; - } - } - - private serializeValueCode(value: Sourcelike): Sourcelike { - if (value !== "null") return ["JsonSerializer.Serialize(writer, ", value, ", options)"]; - else return ["writer.WriteNullValue()"]; - } - - private emitSerializeClass(): void { - // FIXME: Make Serialize a Named - this.emitType(undefined, AccessModifier.Public, "static class", "Serialize", undefined, () => { - // Sometimes multiple top-levels will resolve to the same type, so we have to take care - // not to emit more than one extension method for the same type. - const seenTypes = new Set(); - this.forEachTopLevel("none", t => { - // FIXME: Make ToJson a Named - if (!seenTypes.has(t)) { - seenTypes.add(t); - this.emitExpressionMember( - ["public static string ToJson(this ", this.topLevelResultType(t), " self)"], - ["JsonSerializer.Serialize(self, ", this._options.namespace, ".Converter.Settings)"] - ); - } - }); - }); - } - - private emitCanConvert(expr: Sourcelike): void { - this.emitExpressionMember("public override bool CanConvert(Type t)", expr); - } - - private emitReadJson(emitBody: () => void, csType: Sourcelike): void { - this.emitLine( - "public override ", - csType, - " Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)" - ); - this.emitBlock(emitBody); - } - - private emitWriteJson(variable: string, emitBody: () => void, csType: Sourcelike): void { - this.emitLine( - "public override void Write(Utf8JsonWriter writer, ", - csType, - " ", - variable, - ", JsonSerializerOptions options)" - ); - this.emitBlock(emitBody); - } - - private converterObject(converterName: Name): Sourcelike { - // FIXME: Get a singleton - return [converterName, ".Singleton"]; - } - - private emitConverterClass(): void { - // FIXME: Make Converter a Named - const converterName: Sourcelike = ["Converter"]; - this.emitType(undefined, AccessModifier.Internal, "static class", converterName, undefined, () => { - // Do not use .Web as defaults. That turns on caseInsensitive property names and will fail the keywords test. - this.emitLine( - "public static readonly JsonSerializerOptions Settings = new(JsonSerializerDefaults.General)" - ); - this.emitBlock(() => { - // this.emitLine("MetadataPropertyHandling = MetadataPropertyHandling.Ignore,"); - // this.emitLine("DateParseHandling = DateParseHandling.None,"); - this.emitLine("Converters ="); - this.emitLine("{"); - this.indent(() => { - for (const [t, converter] of this.typesWithNamedTransformations) { - if (alwaysApplyTransformation(defined(transformationForType(t)))) { - this.emitLine(this.converterObject(converter), ","); - } - } - - this.emitLine("new DateOnlyConverter(),"); - this.emitLine("new TimeOnlyConverter(),"); - this.emitLine("IsoDateTimeOffsetConverter.Singleton"); - // this.emitLine("new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }"); - }); - this.emitLine("},"); - }, true); - }); - } - - private emitDecoderTransformerCase( - tokenCases: string[], - variableName: string, - xfer: Transformer | undefined, - targetType: Type, - emitFinish: (value: Sourcelike) => void - ): void { - if (xfer === undefined) return; - - for (const tokenCase of tokenCases) { - this.emitTokenCase(tokenCase); - } - - this.indent(() => { - const allHandled = this.emitDecodeTransformer(xfer, targetType, emitFinish, variableName); - if (!allHandled) { - this.emitLine("break;"); - } - }); - } - - private emitConsume( - value: Sourcelike, - consumer: Transformer | undefined, - targetType: Type, - emitFinish: (variableName: Sourcelike) => void - ): boolean { - if (consumer === undefined) { - emitFinish(value); - return true; - } else { - return this.emitTransformer(value, consumer, targetType, emitFinish); - } - } - - private emitDecodeTransformer( - xfer: Transformer, - targetType: Type, - emitFinish: (value: Sourcelike) => void, - variableName = "value" - ): boolean { - if (xfer instanceof DecodingTransformer) { - const source = xfer.sourceType; - const converter = this.converterForType(targetType); - if (converter !== undefined) { - const typeSource = this.csType(targetType); - this.emitLine("var converter = ", this.converterObject(converter), ";"); - this.emitLine( - "var ", - variableName, - " = (", - typeSource, - ")converter.ReadJson(reader, typeof(", - typeSource, - "), null, serializer);" - ); - } else if (source.kind !== "null") { - let output = targetType.kind === "double" ? targetType : source; - this.emitLine("var ", variableName, " = ", this.deserializeTypeCode(this.csType(output)), ";"); - } - - return this.emitConsume(variableName, xfer.consumer, targetType, emitFinish); - } else if (xfer instanceof ArrayDecodingTransformer) { - // FIXME: Consume StartArray - if (!(targetType instanceof ArrayType)) { - return panic("Array decoding must produce an array type"); - } - - // FIXME: handle EOF - this.emitLine("reader.Read();"); - this.emitLine("var ", variableName, " = new List<", this.csType(targetType.items), ">();"); - this.emitLine("while (reader.TokenType != JsonToken.EndArray)"); - this.emitBlock(() => { - this.emitDecodeTransformer( - xfer.itemTransformer, - xfer.itemTargetType, - v => this.emitLine(variableName, ".Add(", v, ");"), - "arrayItem" - ); - // FIXME: handle EOF - this.emitLine("reader.Read();"); - }); - let result: Sourcelike = variableName; - if (!this._options.useList) { - result = [result, ".ToArray()"]; - } - - emitFinish(result); - return true; - } else if (xfer instanceof DecodingChoiceTransformer) { - this.emitDecoderSwitch(() => { - const nullTransformer = xfer.nullTransformer; - if (nullTransformer !== undefined) { - this.emitTokenCase("Null"); - this.indent(() => { - const allHandled = this.emitDecodeTransformer(nullTransformer, targetType, emitFinish, "null"); - if (!allHandled) { - this.emitLine("break"); - } - }); - } - - this.emitDecoderTransformerCase( - ["Number"], - "integerValue", - xfer.integerTransformer, - targetType, - emitFinish - ); - this.emitDecoderTransformerCase( - ["Number"], - // xfer.integerTransformer === undefined ? ["Integer", "Float"] : ["Float"], - "doubleValue", - xfer.doubleTransformer, - targetType, - emitFinish - ); - this.emitDecoderTransformerCase( - ["True", "False"], - "boolValue", - xfer.boolTransformer, - targetType, - emitFinish - ); - this.emitDecoderTransformerCase( - // ["String", "Date"], - ["String"], - "stringValue", - xfer.stringTransformer, - targetType, - emitFinish - ); - this.emitDecoderTransformerCase( - ["StartObject"], - "objectValue", - xfer.objectTransformer, - targetType, - emitFinish - ); - this.emitDecoderTransformerCase( - ["StartArray"], - "arrayValue", - xfer.arrayTransformer, - targetType, - emitFinish - ); - }); - return false; - } else { - return panic("Unknown transformer"); - } - } - - private stringCaseValue(t: Type, stringCase: string): Sourcelike { - if (t.kind === "string") { - return ['"', utf16StringEscape(stringCase), '"']; - } else if (t instanceof EnumType) { - return [this.nameForNamedType(t), ".", this.nameForEnumCase(t, stringCase)]; - } - - return panic(`Type ${t.kind} does not have string cases`); - } - - private emitTransformer( - variable: Sourcelike, - xfer: Transformer, - targetType: Type, - emitFinish: (value: Sourcelike) => void - ): boolean { - function directTargetType(continuation: Transformer | undefined): Type { - if (continuation === undefined) { - return targetType; - } - - return followTargetType(continuation.sourceType); - } - - if (xfer instanceof ChoiceTransformer) { - const caseXfers = xfer.transformers; - if (caseXfers.length > 1 && caseXfers.every(caseXfer => caseXfer instanceof StringMatchTransformer)) { - this.emitLine("switch (", variable, ")"); - this.emitBlock(() => { - for (const caseXfer of caseXfers) { - const matchXfer = caseXfer as StringMatchTransformer; - const value = this.stringCaseValue( - followTargetType(matchXfer.sourceType), - matchXfer.stringCase - ); - this.emitLine("case ", value, ":"); - this.indent(() => { - const allDone = this.emitTransformer( - variable, - matchXfer.transformer, - targetType, - emitFinish - ); - if (!allDone) { - this.emitLine("break;"); - } - }); - } - }); - // FIXME: Can we check for exhaustiveness? For enums it should be easy. - return false; - } else { - for (const caseXfer of caseXfers) { - this.emitTransformer(variable, caseXfer, targetType, emitFinish); - } - } - } else if (xfer instanceof UnionMemberMatchTransformer) { - const memberType = xfer.memberType; - const maybeNullable = nullableFromUnion(xfer.sourceType); - let test: Sourcelike; - let member: Sourcelike; - if (maybeNullable !== null) { - if (memberType.kind === "null") { - test = [variable, " == null"]; - member = "null"; - } else { - test = [variable, " != null"]; - member = variable; - } - } else if (memberType.kind === "null") { - test = [variable, ".IsNull"]; - member = "null"; - } else { - const memberName = this.nameForUnionMember(xfer.sourceType, memberType); - member = [variable, ".", memberName]; - test = [member, " != null"]; - } - - if (memberType.kind !== "null" && isValueType(memberType)) { - member = [member, ".Value"]; - } - - this.emitLine("if (", test, ")"); - this.emitBlock(() => this.emitTransformer(member, xfer.transformer, targetType, emitFinish)); - } else if (xfer instanceof StringMatchTransformer) { - const value = this.stringCaseValue(followTargetType(xfer.sourceType), xfer.stringCase); - this.emitLine("if (", variable, " == ", value, ")"); - this.emitBlock(() => this.emitTransformer(variable, xfer.transformer, targetType, emitFinish)); - } else if (xfer instanceof EncodingTransformer) { - const converter = this.converterForType(xfer.sourceType); - if (converter !== undefined) { - this.emitLine("var converter = ", this.converterObject(converter), ";"); - this.emitLine("converter.WriteJson(writer, ", variable, ", serializer);"); - } else { - this.emitLine(this.serializeValueCode(variable), ";"); - } - - emitFinish([]); - return true; - } else if (xfer instanceof ArrayEncodingTransformer) { - this.emitLine("writer.WriteStartArray();"); - const itemVariable = "arrayItem"; - this.emitLine("foreach (var ", itemVariable, " in ", variable, ")"); - this.emitBlock(() => { - this.emitTransformer(itemVariable, xfer.itemTransformer, xfer.itemTargetType, () => { - return; - }); - }); - this.emitLine("writer.WriteEndArray();"); - emitFinish([]); - return true; - } else if (xfer instanceof ParseStringTransformer) { - const immediateTargetType = xfer.consumer === undefined ? targetType : xfer.consumer.sourceType; - switch (immediateTargetType.kind) { - case "date-time": - this.emitLine("DateTimeOffset dt;"); - this.emitLine("if (DateTimeOffset.TryParse(", variable, ", out dt))"); - this.emitBlock(() => this.emitConsume("dt", xfer.consumer, targetType, emitFinish)); - break; - case "uuid": - this.emitLine("Guid guid;"); - this.emitLine("if (Guid.TryParse(", variable, ", out guid))"); - this.emitBlock(() => this.emitConsume("guid", xfer.consumer, targetType, emitFinish)); - break; - case "uri": - this.emitLine("try"); - this.emitBlock(() => { - // this.emitLine("var uri = new Uri(", variable, ");"); - // The default value about:blank should never happen, but this way we avoid a null reference warning. - this.emitLine('var uri = new Uri("about:blank");'); - this.emitLine("if (!string.IsNullOrEmpty(stringValue))"); - this.emitBlock(() => { - this.emitLine("uri = new Uri(", variable, ");"); - }); - this.emitConsume("uri", xfer.consumer, targetType, emitFinish); - }); - this.emitLine("catch (UriFormatException) {}"); - break; - case "integer": - this.emitLine("long l;"); - this.emitLine("if (Int64.TryParse(", variable, ", out l))"); - this.emitBlock(() => this.emitConsume("l", xfer.consumer, targetType, emitFinish)); - break; - case "bool": - this.emitLine("bool b;"); - this.emitLine("if (Boolean.TryParse(", variable, ", out b))"); - this.emitBlock(() => this.emitConsume("b", xfer.consumer, targetType, emitFinish)); - break; - default: - return panic(`Parsing string to ${immediateTargetType.kind} not supported`); - } - } else if (xfer instanceof StringifyTransformer) { - switch (xfer.sourceType.kind) { - case "date-time": - return this.emitConsume( - [variable, '.ToString("o", System.Globalization.CultureInfo.InvariantCulture)'], - xfer.consumer, - targetType, - emitFinish - ); - case "uuid": - return this.emitConsume( - [variable, '.ToString("D", System.Globalization.CultureInfo.InvariantCulture)'], - xfer.consumer, - targetType, - emitFinish - ); - case "integer": - case "uri": - return this.emitConsume([variable, ".ToString()"], xfer.consumer, targetType, emitFinish); - case "bool": - this.emitLine("var boolString = ", variable, ' ? "true" : "false";'); - return this.emitConsume("boolString", xfer.consumer, targetType, emitFinish); - default: - return panic(`Stringifying ${xfer.sourceType.kind} not supported`); - } - } else if (xfer instanceof StringProducerTransformer) { - const value = this.stringCaseValue(directTargetType(xfer.consumer), xfer.result); - return this.emitConsume(value, xfer.consumer, targetType, emitFinish); - } else if (xfer instanceof MinMaxLengthCheckTransformer) { - const min = xfer.minLength; - const max = xfer.maxLength; - const conditions: Sourcelike[] = []; - - if (min !== undefined) { - conditions.push([variable, ".Length >= ", min.toString()]); - } - - if (max !== undefined) { - conditions.push([variable, ".Length <= ", max.toString()]); - } - - this.emitLine("if (", arrayIntercalate([" && "], conditions), ")"); - this.emitBlock(() => this.emitConsume(variable, xfer.consumer, targetType, emitFinish)); - return false; - } else if (xfer instanceof MinMaxValueTransformer) { - const min = xfer.minimum; - const max = xfer.maximum; - const conditions: Sourcelike[] = []; - - if (min !== undefined) { - conditions.push([variable, " >= ", min.toString()]); - } - - if (max !== undefined) { - conditions.push([variable, " <= ", max.toString()]); - } - - this.emitLine("if (", arrayIntercalate([" && "], conditions), ")"); - this.emitBlock(() => this.emitConsume(variable, xfer.consumer, targetType, emitFinish)); - return false; - } else if (xfer instanceof UnionInstantiationTransformer) { - if (!(targetType instanceof UnionType)) { - return panic("Union instantiation transformer must produce a union type"); - } - - const maybeNullable = nullableFromUnion(targetType); - if (maybeNullable !== null) { - emitFinish(variable); - } else { - const unionName = this.nameForNamedType(targetType); - let initializer: Sourcelike; - if (xfer.sourceType.kind === "null") { - initializer = " "; - } else { - const memberName = this.nameForUnionMember(targetType, xfer.sourceType); - initializer = [" ", memberName, " = ", variable, " "]; - } - - emitFinish(["new ", unionName, " {", initializer, "}"]); - } - - return true; - } else { - return panic("Unknown transformer"); - } - - return false; - } - - private emitTransformation(converterName: Name, t: Type): void { - const xf = defined(transformationForType(t)); - const reverse = xf.reverse; - const targetType = xf.targetType; - const xfer = xf.transformer; - const csType = this.csType(targetType); - // const haveNullable = isValueType(targetType); - - // if (haveNullable) { - // converterName = ['Nullable', converterName]; - // csType = [csType, "?"]; - // } - this.emitType( - undefined, - AccessModifier.Internal, - "class", - converterName, - ["JsonConverter<", csType, ">"], - () => { - let canConvertExpr: Sourcelike = ["t == typeof(", csType, ")"]; - this.emitCanConvert(canConvertExpr); - this.ensureBlankLine(); - this.emitReadJson(() => { - // FIXME: It's unsatisfying that we need this. The reason is that we not - // only match T, but also T?. If we didn't, then the T in T? would not be - // deserialized with our converter but with the default one. Can we check - // whether the type is a nullable? - // FIXME: This could duplicate one of the cases handled below in - // `emitDecodeTransformer`. - // if (haveNullable && !(targetType instanceof UnionType)) { - // this.emitLine("if (reader.TokenType == JsonTokenType.Null) return null;"); - // } - - const allHandled = this.emitDecodeTransformer(xfer, targetType, v => - this.emitLine("return ", v, ";") - ); - if (!allHandled) { - this.emitThrow(['"Cannot unmarshal type ', csType, '"']); - } - }, csType); - this.ensureBlankLine(); - this.emitWriteJson( - "value", - () => { - // FIXME: See above. - // if (haveNullable && !(targetType instanceof UnionType)) { - // this.emitLine("if (value == null)"); - // this.emitBlock(() => { - // this.emitLine("writer.WriteNullValue();"); - // this.emitLine("return;"); - // }); - // } - - const allHandled = this.emitTransformer("value", reverse.transformer, reverse.targetType, () => - this.emitLine("return;") - ); - if (!allHandled) { - this.emitThrow(['"Cannot marshal type ', csType, '"']); - } - }, - csType - ); - this.ensureBlankLine(); - this.emitLine("public static readonly ", converterName, " Singleton = new ", converterName, "();"); - } - ); - } - - protected emitRequiredHelpers(): void { - if (this._needHelpers) { - this.forEachTopLevel("leading-and-interposing", (t, n) => this.emitFromJsonForTopLevel(t, n)); - this.ensureBlankLine(); - this.emitSerializeClass(); - } - - if (this._needHelpers || (this._needAttributes && (this.haveNamedUnions || this.haveEnums))) { - this.ensureBlankLine(); - this.emitConverterClass(); - this.forEachTransformation("leading-and-interposing", (n, t) => this.emitTransformation(n, t)); - this.emitMultiline(` -public class DateOnlyConverter : JsonConverter -{ - private readonly string serializationFormat; - public DateOnlyConverter() : this(null) { } - - public DateOnlyConverter(string? serializationFormat) - { - this.serializationFormat = serializationFormat ?? "yyyy-MM-dd"; - } - - public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - var value = reader.GetString(); - return DateOnly.Parse(value!); - } - - public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options) - => writer.WriteStringValue(value.ToString(serializationFormat)); -} - -public class TimeOnlyConverter : JsonConverter -{ - private readonly string serializationFormat; - - public TimeOnlyConverter() : this(null) { } - - public TimeOnlyConverter(string? serializationFormat) - { - this.serializationFormat = serializationFormat ?? "HH:mm:ss.fff"; - } - - public override TimeOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - var value = reader.GetString(); - return TimeOnly.Parse(value!); - } - - public override void Write(Utf8JsonWriter writer, TimeOnly value, JsonSerializerOptions options) - => writer.WriteStringValue(value.ToString(serializationFormat)); -} - -internal class IsoDateTimeOffsetConverter : JsonConverter -{ - public override bool CanConvert(Type t) => t == typeof(DateTimeOffset); - - private const string DefaultDateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; - - private DateTimeStyles _dateTimeStyles = DateTimeStyles.RoundtripKind; - private string? _dateTimeFormat; - private CultureInfo? _culture; - - public DateTimeStyles DateTimeStyles - { - get => _dateTimeStyles; - set => _dateTimeStyles = value; - } - - public string? DateTimeFormat - { - get => _dateTimeFormat ?? string.Empty; - set => _dateTimeFormat = (string.IsNullOrEmpty(value)) ? null : value; - } - - public CultureInfo Culture - { - get => _culture ?? CultureInfo.CurrentCulture; - set => _culture = value; - } - - public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options) - { - string text; - - - if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal - || (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal) - { - value = value.ToUniversalTime(); - } - - text = value.ToString(_dateTimeFormat ?? DefaultDateTimeFormat, Culture); - - writer.WriteStringValue(text); - } - - public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - string? dateText = reader.GetString(); - - if (string.IsNullOrEmpty(dateText) == false) - { - if (!string.IsNullOrEmpty(_dateTimeFormat)) - { - return DateTimeOffset.ParseExact(dateText, _dateTimeFormat, Culture, _dateTimeStyles); - } - else - { - return DateTimeOffset.Parse(dateText, Culture, _dateTimeStyles); - } - } - else - { - return default(DateTimeOffset); - } - } - - - public static readonly IsoDateTimeOffsetConverter Singleton = new IsoDateTimeOffsetConverter(); -}`); - } - } - - protected needNamespace(): boolean { - return this._needNamespaces; - } -} diff --git a/packages/quicktype-core/src/language/CSharp/CSharpRenderer.ts b/packages/quicktype-core/src/language/CSharp/CSharpRenderer.ts new file mode 100644 index 000000000..09cfcc3ca --- /dev/null +++ b/packages/quicktype-core/src/language/CSharp/CSharpRenderer.ts @@ -0,0 +1,390 @@ +import { arrayIntercalate } from "collection-utils"; + +import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../../Annotation"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../../ConvenienceRenderer"; +import { type Name, type Namer } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type Sourcelike, maybeAnnotated } from "../../Source"; +import { assert } from "../../support/Support"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { followTargetType } from "../../Transformers"; +import { type ClassProperty, type ClassType, type EnumType, type Type, type UnionType } from "../../Type"; +import { directlyReachableSingleNamedType, matchType, nullableFromUnion, removeNullFromUnion } from "../../TypeUtils"; + +import { type cSharpOptions } from "./language"; +import { + AccessModifier, + csTypeForTransformedStringType, + isValueType, + namingFunction, + namingFunctionKeep, + noFollow +} from "./utils"; + +export class CSharpRenderer extends ConvenienceRenderer { + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + private readonly _csOptions: OptionValues + ) { + super(targetLanguage, renderContext); + } + + protected forbiddenNamesForGlobalNamespace(): string[] { + return ["QuickType", "Type", "System", "Console", "Exception", "DateTimeOffset", "Guid", "Uri"]; + } + + protected forbiddenForObjectProperties(_: ClassType, classNamed: Name): ForbiddenWordsInfo { + return { + names: [ + classNamed, + "ToString", + "GetHashCode", + "Finalize", + "Equals", + "GetType", + "MemberwiseClone", + "ReferenceEquals" + ], + includeGlobalForbidden: false + }; + } + + protected forbiddenForUnionMembers(_: UnionType, unionNamed: Name): ForbiddenWordsInfo { + return { names: [unionNamed], includeGlobalForbidden: true }; + } + + protected makeNamedTypeNamer(): Namer { + return namingFunction; + } + + protected namerForObjectProperty(): Namer { + return this._csOptions.keepPropertyName ? namingFunctionKeep : namingFunction; + } + + protected makeUnionMemberNamer(): Namer { + return namingFunction; + } + + protected makeEnumCaseNamer(): Namer { + return namingFunction; + } + + protected unionNeedsName(u: UnionType): boolean { + return nullableFromUnion(u) === null; + } + + protected namedTypeToNameForTopLevel(type: Type): Type | undefined { + // If the top-level type doesn't contain any classes or unions + // we have to define a class just for the `FromJson` method, in + // emitFromJsonForTopLevel. + return directlyReachableSingleNamedType(type); + } + + protected emitBlock(f: () => void, semicolon = false): void { + this.emitLine("{"); + this.indent(f); + this.emitLine("}", semicolon ? ";" : ""); + } + + protected get doubleType(): string { + return this._csOptions.useDecimal ? "decimal" : "double"; + } + + protected csType(t: Type, follow: (t: Type) => Type = followTargetType, withIssues = false): Sourcelike { + const actualType = follow(t); + return matchType( + actualType, + _anyType => maybeAnnotated(withIssues, anyTypeIssueAnnotation, this._csOptions.typeForAny), + _nullType => maybeAnnotated(withIssues, nullTypeIssueAnnotation, this._csOptions.typeForAny), + _boolType => "bool", + _integerType => "long", + _doubleType => this.doubleType, + _stringType => "string", + arrayType => { + const itemsType = this.csType(arrayType.items, follow, withIssues); + if (this._csOptions.useList) { + return ["List<", itemsType, ">"]; + } else { + return [itemsType, "[]"]; + } + }, + classType => this.nameForNamedType(classType), + mapType => ["Dictionary"], + enumType => this.nameForNamedType(enumType), + unionType => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) return this.nullableCSType(nullable, noFollow); + return this.nameForNamedType(unionType); + }, + transformedStringType => csTypeForTransformedStringType(transformedStringType) + ); + } + + protected nullableCSType(t: Type, follow: (t: Type) => Type = followTargetType, withIssues = false): Sourcelike { + t = followTargetType(t); + const csType = this.csType(t, follow, withIssues); + if (isValueType(t)) { + return [csType, "?"]; + } else { + return csType; + } + } + + protected baseclassForType(_t: Type): Sourcelike | undefined { + return undefined; + } + + protected emitType( + description: string[] | undefined, + accessModifier: AccessModifier, + declaration: Sourcelike, + name: Sourcelike, + baseclass: Sourcelike | undefined, + emitter: () => void + ): void { + switch (accessModifier) { + case AccessModifier.Public: + declaration = ["public ", declaration]; + break; + case AccessModifier.Internal: + declaration = ["internal ", declaration]; + break; + default: + break; + } + + this.emitDescription(description); + if (baseclass === undefined) { + this.emitLine(declaration, " ", name); + } else { + this.emitLine(declaration, " ", name, " : ", baseclass); + } + + this.emitBlock(emitter); + } + + protected attributesForProperty( + _property: ClassProperty, + _name: Name, + _c: ClassType, + _jsonName: string + ): Sourcelike[] | undefined { + return undefined; + } + + protected propertyDefinition(property: ClassProperty, name: Name, _c: ClassType, _jsonName: string): Sourcelike { + const t = property.type; + const csType = property.isOptional + ? this.nullableCSType(t, followTargetType, true) + : this.csType(t, followTargetType, true); + + const propertyArray = ["public "]; + + if (this._csOptions.virtual) propertyArray.push("virtual "); + + return [...propertyArray, csType, " ", name, " { get; set; }"]; + } + + protected emitDescriptionBlock(lines: Sourcelike[]): void { + const start = "/// "; + if (this._csOptions.dense) { + this.emitLine(start, lines.join("; "), ""); + } else { + this.emitCommentLines(lines, { lineStart: "/// ", beforeComment: start, afterComment: "/// " }); + } + } + + protected blankLinesBetweenAttributes(): boolean { + return false; + } + + private emitClassDefinition(c: ClassType, className: Name): void { + this.emitType( + this.descriptionForType(c), + AccessModifier.Public, + "partial class", + className, + this.baseclassForType(c), + () => { + if (c.getProperties().size === 0) return; + const blankLines = this.blankLinesBetweenAttributes() ? "interposing" : "none"; + let columns: Sourcelike[][] = []; + let isFirstProperty = true; + let previousDescription: string[] | undefined = undefined; + this.forEachClassProperty(c, blankLines, (name, jsonName, p) => { + const attributes = this.attributesForProperty(p, name, c, jsonName); + const description = this.descriptionForClassProperty(c, jsonName); + const property = this.propertyDefinition(p, name, c, jsonName); + if (attributes === undefined) { + if ( + // Descriptions should be preceded by an empty line + (!isFirstProperty && description !== undefined) || + // If the previous property has a description, leave an empty line + previousDescription !== undefined + ) { + this.ensureBlankLine(); + } + + this.emitDescription(description); + this.emitLine(property); + } else if (this._csOptions.dense && attributes.length > 0) { + const comment = description === undefined ? "" : ` // ${description.join("; ")}`; + columns.push([attributes, " ", property, comment]); + } else { + this.emitDescription(description); + for (const attribute of attributes) { + this.emitLine(attribute); + } + + this.emitLine(property); + } + + isFirstProperty = false; + previousDescription = description; + }); + if (columns.length > 0) { + this.emitTable(columns); + } + } + ); + } + + private emitUnionDefinition(u: UnionType, unionName: Name): void { + const nonNulls = removeNullFromUnion(u, true)[1]; + this.emitType( + this.descriptionForType(u), + AccessModifier.Public, + "partial struct", + unionName, + this.baseclassForType(u), + () => { + this.forEachUnionMember(u, nonNulls, "none", null, (fieldName, t) => { + const csType = this.nullableCSType(t); + this.emitLine("public ", csType, " ", fieldName, ";"); + }); + this.ensureBlankLine(); + const nullTests: Sourcelike[] = Array.from(nonNulls).map(t => [ + this.nameForUnionMember(u, t), + " == null" + ]); + this.ensureBlankLine(); + this.forEachUnionMember(u, nonNulls, "none", null, (fieldName, t) => { + const csType = this.csType(t); + this.emitExpressionMember( + ["public static implicit operator ", unionName, "(", csType, " ", fieldName, ")"], + ["new ", unionName, " { ", fieldName, " = ", fieldName, " }"] + ); + }); + if (u.findMember("null") === undefined) return; + this.emitExpressionMember("public bool IsNull", arrayIntercalate(" && ", nullTests), true); + } + ); + } + + private emitEnumDefinition(e: EnumType, enumName: Name): void { + const caseNames: Sourcelike[] = []; + this.forEachEnumCase(e, "none", name => { + if (caseNames.length > 0) caseNames.push(", "); + caseNames.push(name); + }); + this.emitDescription(this.descriptionForType(e)); + this.emitLine("public enum ", enumName, " { ", caseNames, " };"); + } + + protected emitExpressionMember(declare: Sourcelike, define: Sourcelike, isProperty = false): void { + if (this._csOptions.version === 5) { + this.emitLine(declare); + this.emitBlock(() => { + const stmt = ["return ", define, ";"]; + if (isProperty) { + this.emitLine("get"); + this.emitBlock(() => this.emitLine(stmt)); + } else { + this.emitLine(stmt); + } + }); + } else { + this.emitLine(declare, " => ", define, ";"); + } + } + + protected emitTypeSwitch( + types: Iterable, + condition: (t: T) => Sourcelike, + withBlock: boolean, + withReturn: boolean, + f: (t: T) => void + ): void { + assert(!withReturn || withBlock, "Can only have return with block"); + for (const t of types) { + this.emitLine("if (", condition(t), ")"); + if (withBlock) { + this.emitBlock(() => { + f(t); + if (withReturn) { + this.emitLine("return;"); + } + }); + } else { + this.indent(() => f(t)); + } + } + } + + protected emitUsing(ns: Sourcelike): void { + this.emitLine("using ", ns, ";"); + } + + protected emitUsings(): void { + for (const ns of ["System", "System.Collections.Generic"]) { + this.emitUsing(ns); + } + } + + protected emitRequiredHelpers(): void { + return; + } + + private emitTypesAndSupport(): void { + this.forEachObject("leading-and-interposing", (c: ClassType, name: Name) => this.emitClassDefinition(c, name)); + this.forEachEnum("leading-and-interposing", (e, name) => this.emitEnumDefinition(e, name)); + this.forEachUnion("leading-and-interposing", (u, name) => this.emitUnionDefinition(u, name)); + this.emitRequiredHelpers(); + } + + protected emitDefaultLeadingComments(): void { + return; + } + + protected emitDefaultFollowingComments(): void { + return; + } + + protected needNamespace(): boolean { + return true; + } + + protected emitSourceStructure(): void { + if (this.leadingComments !== undefined) { + this.emitComments(this.leadingComments); + } else { + this.emitDefaultLeadingComments(); + } + + this.ensureBlankLine(); + if (this.needNamespace()) { + this.emitLine("namespace ", this._csOptions.namespace); + this.emitBlock(() => { + this.emitUsings(); + this.emitTypesAndSupport(); + }); + } else { + this.emitUsings(); + this.emitTypesAndSupport(); + } + + this.emitDefaultFollowingComments(); + } +} diff --git a/packages/quicktype-core/src/language/CSharp/NewtonSoftCSharpRenderer.ts b/packages/quicktype-core/src/language/CSharp/NewtonSoftCSharpRenderer.ts new file mode 100644 index 000000000..4d6b09da6 --- /dev/null +++ b/packages/quicktype-core/src/language/CSharp/NewtonSoftCSharpRenderer.ts @@ -0,0 +1,803 @@ +import { arrayIntercalate } from "collection-utils"; + +import { type ForbiddenWordsInfo, inferredNameOrder } from "../../ConvenienceRenderer"; +import { DependencyName, type Name, SimpleName } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type Sourcelike, modifySource } from "../../Source"; +import { camelCase, utf16StringEscape } from "../../support/Strings"; +import { defined, panic } from "../../support/Support"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { + ArrayDecodingTransformer, + ArrayEncodingTransformer, + ChoiceTransformer, + DecodingChoiceTransformer, + DecodingTransformer, + EncodingTransformer, + MinMaxLengthCheckTransformer, + MinMaxValueTransformer, + ParseStringTransformer, + StringMatchTransformer, + StringProducerTransformer, + StringifyTransformer, + type Transformation, + type Transformer, + UnionInstantiationTransformer, + UnionMemberMatchTransformer, + followTargetType, + transformationForType +} from "../../Transformers"; +import { ArrayType, type ClassProperty, ClassType, EnumType, type Type, UnionType } from "../../Type"; +import { nullableFromUnion } from "../../TypeUtils"; + +import { CSharpRenderer } from "./CSharpRenderer"; +import { type newtonsoftCSharpOptions } from "./language"; +import { + AccessModifier, + alwaysApplyTransformation, + denseJsonPropertyName, + denseNullValueHandlingEnumName, + denseRequiredEnumName, + isValueType, + namingFunction +} from "./utils"; + +export class NewtonsoftCSharpRenderer extends CSharpRenderer { + private readonly _enumExtensionsNames = new Map(); + + private readonly _needHelpers: boolean; + + private readonly _needAttributes: boolean; + + private readonly _needNamespaces: boolean; + + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + private readonly _options: OptionValues + ) { + super(targetLanguage, renderContext, _options); + this._needHelpers = _options.features.helpers; + this._needAttributes = _options.features.attributes; + this._needNamespaces = _options.features.namespaces; + } + + protected forbiddenNamesForGlobalNamespace(): string[] { + const forbidden = [ + "Converter", + "JsonConverter", + "JsonSerializer", + "JsonWriter", + "JsonToken", + "Serialize", + "Newtonsoft", + "MetadataPropertyHandling", + "DateParseHandling", + "FromJson", + "Required" + ]; + if (this._options.dense) { + forbidden.push("J", "R", "N"); + } + + if (this._options.baseclass !== undefined) { + forbidden.push(this._options.baseclass); + } + + return super.forbiddenNamesForGlobalNamespace().concat(forbidden); + } + + protected forbiddenForObjectProperties(c: ClassType, className: Name): ForbiddenWordsInfo { + const result = super.forbiddenForObjectProperties(c, className); + result.names = result.names.concat(["ToJson", "FromJson", "Required"]); + return result; + } + + protected makeNameForTransformation(xf: Transformation, typeName: Name | undefined): Name { + if (typeName === undefined) { + let xfer = xf.transformer; + if (xfer instanceof DecodingTransformer && xfer.consumer !== undefined) { + xfer = xfer.consumer; + } + + return new SimpleName([`${xfer.kind}_converter`], namingFunction, inferredNameOrder + 30); + } + + return new DependencyName(namingFunction, typeName.order + 30, lookup => `${lookup(typeName)}_converter`); + } + + protected makeNamedTypeDependencyNames(t: Type, name: Name): DependencyName[] { + if (!(t instanceof EnumType)) return []; + + const extensionsName = new DependencyName( + namingFunction, + name.order + 30, + lookup => `${lookup(name)}_extensions` + ); + this._enumExtensionsNames.set(name, extensionsName); + return [extensionsName]; + } + + protected emitUsings(): void { + // FIXME: We need System.Collections.Generic whenever we have maps or use List. + if (!this._needAttributes && !this._needHelpers) return; + + super.emitUsings(); + this.ensureBlankLine(); + + for (const ns of ["System.Globalization", "Newtonsoft.Json", "Newtonsoft.Json.Converters"]) { + this.emitUsing(ns); + } + + if (this._options.dense) { + this.emitUsing([denseJsonPropertyName, " = Newtonsoft.Json.JsonPropertyAttribute"]); + this.emitUsing([denseRequiredEnumName, " = Newtonsoft.Json.Required"]); + this.emitUsing([denseNullValueHandlingEnumName, " = Newtonsoft.Json.NullValueHandling"]); + } + + if (this._options.baseclass === "EntityData") { + this.emitUsing("Microsoft.Azure.Mobile.Server"); + } + } + + protected baseclassForType(_t: Type): Sourcelike | undefined { + return this._options.baseclass; + } + + protected emitDefaultLeadingComments(): void { + if (!this._needHelpers) return; + + this.emitLine("// "); + this.emitLine("//"); + this.emitLine( + "// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do", + this.topLevels.size === 1 ? "" : " one of these", + ":" + ); + this.emitLine("//"); + this.emitLine("// using ", this._options.namespace, ";"); + this.emitLine("//"); + this.forEachTopLevel("none", (t, topLevelName) => { + let rhs: Sourcelike; + if (t instanceof EnumType) { + rhs = ["JsonConvert.DeserializeObject<", topLevelName, ">(jsonString)"]; + } else { + rhs = [topLevelName, ".FromJson(jsonString)"]; + } + + this.emitLine("// var ", modifySource(camelCase, topLevelName), " = ", rhs, ";"); + }); + } + + private converterForType(t: Type): Name | undefined { + let xf = transformationForType(t); + + if (xf === undefined && t instanceof UnionType) { + const maybeNullable = nullableFromUnion(t); + if (maybeNullable !== null) { + t = maybeNullable; + xf = transformationForType(t); + } + } + + if (xf === undefined) return undefined; + + if (alwaysApplyTransformation(xf)) return undefined; + + return defined(this.nameForTransformation(t)); + } + + protected attributesForProperty( + property: ClassProperty, + _name: Name, + _c: ClassType, + jsonName: string + ): Sourcelike[] | undefined { + if (!this._needAttributes) return undefined; + + const attributes: Sourcelike[] = []; + + const jsonProperty = this._options.dense ? denseJsonPropertyName : "JsonProperty"; + const escapedName = utf16StringEscape(jsonName); + const isNullable = followTargetType(property.type).isNullable; + const isOptional = property.isOptional; + const requiredClass = this._options.dense ? "R" : "Required"; + const nullValueHandlingClass = this._options.dense ? "N" : "NullValueHandling"; + const nullValueHandling = + isOptional && !isNullable ? [", NullValueHandling = ", nullValueHandlingClass, ".Ignore"] : []; + let required: Sourcelike; + if (!this._options.checkRequired || (isOptional && isNullable)) { + required = [nullValueHandling]; + } else if (isOptional && !isNullable) { + required = [", Required = ", requiredClass, ".DisallowNull", nullValueHandling]; + } else if (!isOptional && isNullable) { + required = [", Required = ", requiredClass, ".AllowNull"]; + } else { + required = [", Required = ", requiredClass, ".Always", nullValueHandling]; + } + + attributes.push(["[", jsonProperty, '("', escapedName, '"', required, ")]"]); + + const converter = this.converterForType(property.type); + if (converter !== undefined) { + attributes.push(["[JsonConverter(typeof(", converter, "))]"]); + } + + return attributes; + } + + protected blankLinesBetweenAttributes(): boolean { + return this._needAttributes && !this._options.dense; + } + + // The "this" type can't be `dynamic`, so we have to force it to `object`. + private topLevelResultType(t: Type): Sourcelike { + return t.kind === "any" || t.kind === "none" ? "object" : this.csType(t); + } + + private emitFromJsonForTopLevel(t: Type, name: Name): void { + if (t instanceof EnumType) return; + + let partial: string; + let typeKind: string; + const definedType = this.namedTypeToNameForTopLevel(t); + if (definedType !== undefined) { + partial = "partial "; + typeKind = definedType instanceof ClassType ? "class" : "struct"; + } else { + partial = ""; + typeKind = "class"; + } + + const csType = this.topLevelResultType(t); + this.emitType(undefined, AccessModifier.Public, [partial, typeKind], name, this.baseclassForType(t), () => { + // FIXME: Make FromJson a Named + this.emitExpressionMember( + ["public static ", csType, " FromJson(string json)"], + ["JsonConvert.DeserializeObject<", csType, ">(json, ", this._options.namespace, ".Converter.Settings)"] + ); + }); + } + + private emitDecoderSwitch(emitBody: () => void): void { + this.emitLine("switch (reader.TokenType)"); + this.emitBlock(emitBody); + } + + private emitTokenCase(tokenType: string): void { + this.emitLine("case JsonToken.", tokenType, ":"); + } + + private emitThrow(message: Sourcelike): void { + this.emitLine("throw new Exception(", message, ");"); + } + + private deserializeTypeCode(typeName: Sourcelike): Sourcelike { + return ["serializer.Deserialize<", typeName, ">(reader)"]; + } + + private serializeValueCode(value: Sourcelike): Sourcelike { + return ["serializer.Serialize(writer, ", value, ")"]; + } + + private emitSerializeClass(): void { + // FIXME: Make Serialize a Named + this.emitType(undefined, AccessModifier.Public, "static class", "Serialize", undefined, () => { + // Sometimes multiple top-levels will resolve to the same type, so we have to take care + // not to emit more than one extension method for the same type. + const seenTypes = new Set(); + this.forEachTopLevel("none", t => { + // FIXME: Make ToJson a Named + if (!seenTypes.has(t)) { + seenTypes.add(t); + this.emitExpressionMember( + ["public static string ToJson(this ", this.topLevelResultType(t), " self)"], + ["JsonConvert.SerializeObject(self, ", this._options.namespace, ".Converter.Settings)"] + ); + } + }); + }); + } + + private emitCanConvert(expr: Sourcelike): void { + this.emitExpressionMember("public override bool CanConvert(Type t)", expr); + } + + private emitReadJson(emitBody: () => void): void { + this.emitLine( + "public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)" + ); + this.emitBlock(emitBody); + } + + private emitWriteJson(variable: string, emitBody: () => void): void { + this.emitLine( + "public override void WriteJson(JsonWriter writer, object ", + variable, + ", JsonSerializer serializer)" + ); + this.emitBlock(emitBody); + } + + private converterObject(converterName: Name): Sourcelike { + // FIXME: Get a singleton + return [converterName, ".Singleton"]; + } + + private emitConverterClass(): void { + // FIXME: Make Converter a Named + const converterName: Sourcelike = ["Converter"]; + this.emitType(undefined, AccessModifier.Internal, "static class", converterName, undefined, () => { + this.emitLine("public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings"); + this.emitBlock(() => { + this.emitLine("MetadataPropertyHandling = MetadataPropertyHandling.Ignore,"); + this.emitLine("DateParseHandling = DateParseHandling.None,"); + this.emitLine("Converters ="); + this.emitLine("{"); + this.indent(() => { + for (const [t, converter] of this.typesWithNamedTransformations) { + if (alwaysApplyTransformation(defined(transformationForType(t)))) { + this.emitLine(this.converterObject(converter), ","); + } + } + + this.emitLine("new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }"); + }); + this.emitLine("},"); + }, true); + }); + } + + private emitDecoderTransformerCase( + tokenCases: string[], + variableName: string, + xfer: Transformer | undefined, + targetType: Type, + emitFinish: (value: Sourcelike) => void + ): void { + if (xfer === undefined) return; + + for (const tokenCase of tokenCases) { + this.emitTokenCase(tokenCase); + } + + this.indent(() => { + const allHandled = this.emitDecodeTransformer(xfer, targetType, emitFinish, variableName); + if (!allHandled) { + this.emitLine("break;"); + } + }); + } + + private emitConsume( + value: Sourcelike, + consumer: Transformer | undefined, + targetType: Type, + emitFinish: (variableName: Sourcelike) => void + ): boolean { + if (consumer === undefined) { + emitFinish(value); + return true; + } else { + return this.emitTransformer(value, consumer, targetType, emitFinish); + } + } + + private emitDecodeTransformer( + xfer: Transformer, + targetType: Type, + emitFinish: (value: Sourcelike) => void, + variableName = "value" + ): boolean { + if (xfer instanceof DecodingTransformer) { + const source = xfer.sourceType; + const converter = this.converterForType(targetType); + if (converter !== undefined) { + const typeSource = this.csType(targetType); + this.emitLine("var converter = ", this.converterObject(converter), ";"); + this.emitLine( + "var ", + variableName, + " = (", + typeSource, + ")converter.ReadJson(reader, typeof(", + typeSource, + "), null, serializer);" + ); + } else if (source.kind !== "null") { + let output = targetType.kind === "double" ? targetType : source; + this.emitLine("var ", variableName, " = ", this.deserializeTypeCode(this.csType(output)), ";"); + } + + return this.emitConsume(variableName, xfer.consumer, targetType, emitFinish); + } else if (xfer instanceof ArrayDecodingTransformer) { + // FIXME: Consume StartArray + if (!(targetType instanceof ArrayType)) { + return panic("Array decoding must produce an array type"); + } + + // FIXME: handle EOF + this.emitLine("reader.Read();"); + this.emitLine("var ", variableName, " = new List<", this.csType(targetType.items), ">();"); + this.emitLine("while (reader.TokenType != JsonToken.EndArray)"); + this.emitBlock(() => { + this.emitDecodeTransformer( + xfer.itemTransformer, + xfer.itemTargetType, + v => this.emitLine(variableName, ".Add(", v, ");"), + "arrayItem" + ); + // FIXME: handle EOF + this.emitLine("reader.Read();"); + }); + let result: Sourcelike = variableName; + if (!this._options.useList) { + result = [result, ".ToArray()"]; + } + + emitFinish(result); + return true; + } else if (xfer instanceof DecodingChoiceTransformer) { + this.emitDecoderSwitch(() => { + const nullTransformer = xfer.nullTransformer; + if (nullTransformer !== undefined) { + this.emitTokenCase("Null"); + this.indent(() => { + const allHandled = this.emitDecodeTransformer(nullTransformer, targetType, emitFinish, "null"); + if (!allHandled) { + this.emitLine("break"); + } + }); + } + + this.emitDecoderTransformerCase( + ["Integer"], + "integerValue", + xfer.integerTransformer, + targetType, + emitFinish + ); + this.emitDecoderTransformerCase( + xfer.integerTransformer === undefined ? ["Integer", "Float"] : ["Float"], + "doubleValue", + xfer.doubleTransformer, + targetType, + emitFinish + ); + this.emitDecoderTransformerCase(["Boolean"], "boolValue", xfer.boolTransformer, targetType, emitFinish); + this.emitDecoderTransformerCase( + ["String", "Date"], + "stringValue", + xfer.stringTransformer, + targetType, + emitFinish + ); + this.emitDecoderTransformerCase( + ["StartObject"], + "objectValue", + xfer.objectTransformer, + targetType, + emitFinish + ); + this.emitDecoderTransformerCase( + ["StartArray"], + "arrayValue", + xfer.arrayTransformer, + targetType, + emitFinish + ); + }); + return false; + } else { + return panic("Unknown transformer"); + } + } + + private stringCaseValue(t: Type, stringCase: string): Sourcelike { + if (t.kind === "string") { + return ['"', utf16StringEscape(stringCase), '"']; + } else if (t instanceof EnumType) { + return [this.nameForNamedType(t), ".", this.nameForEnumCase(t, stringCase)]; + } + + return panic(`Type ${t.kind} does not have string cases`); + } + + private emitTransformer( + variable: Sourcelike, + xfer: Transformer, + targetType: Type, + emitFinish: (value: Sourcelike) => void + ): boolean { + function directTargetType(continuation: Transformer | undefined): Type { + if (continuation === undefined) { + return targetType; + } + + return followTargetType(continuation.sourceType); + } + + if (xfer instanceof ChoiceTransformer) { + const caseXfers = xfer.transformers; + if (caseXfers.length > 1 && caseXfers.every(caseXfer => caseXfer instanceof StringMatchTransformer)) { + this.emitLine("switch (", variable, ")"); + this.emitBlock(() => { + for (const caseXfer of caseXfers) { + const matchXfer = caseXfer as StringMatchTransformer; + const value = this.stringCaseValue( + followTargetType(matchXfer.sourceType), + matchXfer.stringCase + ); + this.emitLine("case ", value, ":"); + this.indent(() => { + const allDone = this.emitTransformer( + variable, + matchXfer.transformer, + targetType, + emitFinish + ); + if (!allDone) { + this.emitLine("break;"); + } + }); + } + }); + // FIXME: Can we check for exhaustiveness? For enums it should be easy. + return false; + } else { + for (const caseXfer of caseXfers) { + this.emitTransformer(variable, caseXfer, targetType, emitFinish); + } + } + } else if (xfer instanceof UnionMemberMatchTransformer) { + const memberType = xfer.memberType; + const maybeNullable = nullableFromUnion(xfer.sourceType); + let test: Sourcelike; + let member: Sourcelike; + if (maybeNullable !== null) { + if (memberType.kind === "null") { + test = [variable, " == null"]; + member = "null"; + } else { + test = [variable, " != null"]; + member = variable; + } + } else if (memberType.kind === "null") { + test = [variable, ".IsNull"]; + member = "null"; + } else { + const memberName = this.nameForUnionMember(xfer.sourceType, memberType); + member = [variable, ".", memberName]; + test = [member, " != null"]; + } + + if (memberType.kind !== "null" && isValueType(memberType)) { + member = [member, ".Value"]; + } + + this.emitLine("if (", test, ")"); + this.emitBlock(() => this.emitTransformer(member, xfer.transformer, targetType, emitFinish)); + } else if (xfer instanceof StringMatchTransformer) { + const value = this.stringCaseValue(followTargetType(xfer.sourceType), xfer.stringCase); + this.emitLine("if (", variable, " == ", value, ")"); + this.emitBlock(() => this.emitTransformer(variable, xfer.transformer, targetType, emitFinish)); + } else if (xfer instanceof EncodingTransformer) { + const converter = this.converterForType(xfer.sourceType); + if (converter !== undefined) { + this.emitLine("var converter = ", this.converterObject(converter), ";"); + this.emitLine("converter.WriteJson(writer, ", variable, ", serializer);"); + } else { + this.emitLine(this.serializeValueCode(variable), ";"); + } + + emitFinish([]); + return true; + } else if (xfer instanceof ArrayEncodingTransformer) { + this.emitLine("writer.WriteStartArray();"); + const itemVariable = "arrayItem"; + this.emitLine("foreach (var ", itemVariable, " in ", variable, ")"); + this.emitBlock(() => { + this.emitTransformer(itemVariable, xfer.itemTransformer, xfer.itemTargetType, () => { + return; + }); + }); + this.emitLine("writer.WriteEndArray();"); + emitFinish([]); + return true; + } else if (xfer instanceof ParseStringTransformer) { + const immediateTargetType = xfer.consumer === undefined ? targetType : xfer.consumer.sourceType; + switch (immediateTargetType.kind) { + case "date-time": + this.emitLine("DateTimeOffset dt;"); + this.emitLine("if (DateTimeOffset.TryParse(", variable, ", out dt))"); + this.emitBlock(() => this.emitConsume("dt", xfer.consumer, targetType, emitFinish)); + break; + case "uuid": + this.emitLine("Guid guid;"); + this.emitLine("if (Guid.TryParse(", variable, ", out guid))"); + this.emitBlock(() => this.emitConsume("guid", xfer.consumer, targetType, emitFinish)); + break; + case "uri": + this.emitLine("try"); + this.emitBlock(() => { + this.emitLine("var uri = new Uri(", variable, ");"); + this.emitConsume("uri", xfer.consumer, targetType, emitFinish); + }); + this.emitLine("catch (UriFormatException) {}"); + break; + case "integer": + this.emitLine("long l;"); + this.emitLine("if (Int64.TryParse(", variable, ", out l))"); + this.emitBlock(() => this.emitConsume("l", xfer.consumer, targetType, emitFinish)); + break; + case "bool": + this.emitLine("bool b;"); + this.emitLine("if (Boolean.TryParse(", variable, ", out b))"); + this.emitBlock(() => this.emitConsume("b", xfer.consumer, targetType, emitFinish)); + break; + default: + return panic(`Parsing string to ${immediateTargetType.kind} not supported`); + } + } else if (xfer instanceof StringifyTransformer) { + switch (xfer.sourceType.kind) { + case "date-time": + return this.emitConsume( + [variable, '.ToString("o", System.Globalization.CultureInfo.InvariantCulture)'], + xfer.consumer, + targetType, + emitFinish + ); + case "uuid": + return this.emitConsume( + [variable, '.ToString("D", System.Globalization.CultureInfo.InvariantCulture)'], + xfer.consumer, + targetType, + emitFinish + ); + case "integer": + case "uri": + return this.emitConsume([variable, ".ToString()"], xfer.consumer, targetType, emitFinish); + case "bool": + this.emitLine("var boolString = ", variable, ' ? "true" : "false";'); + return this.emitConsume("boolString", xfer.consumer, targetType, emitFinish); + default: + return panic(`Stringifying ${xfer.sourceType.kind} not supported`); + } + } else if (xfer instanceof StringProducerTransformer) { + const value = this.stringCaseValue(directTargetType(xfer.consumer), xfer.result); + return this.emitConsume(value, xfer.consumer, targetType, emitFinish); + } else if (xfer instanceof MinMaxLengthCheckTransformer) { + const min = xfer.minLength; + const max = xfer.maxLength; + const conditions: Sourcelike[] = []; + + if (min !== undefined) { + conditions.push([variable, ".Length >= ", min.toString()]); + } + + if (max !== undefined) { + conditions.push([variable, ".Length <= ", max.toString()]); + } + + this.emitLine("if (", arrayIntercalate([" && "], conditions), ")"); + this.emitBlock(() => this.emitConsume(variable, xfer.consumer, targetType, emitFinish)); + return false; + } else if (xfer instanceof MinMaxValueTransformer) { + const min = xfer.minimum; + const max = xfer.maximum; + const conditions: Sourcelike[] = []; + + if (min !== undefined) { + conditions.push([variable, " >= ", min.toString()]); + } + + if (max !== undefined) { + conditions.push([variable, " <= ", max.toString()]); + } + + this.emitLine("if (", arrayIntercalate([" && "], conditions), ")"); + this.emitBlock(() => this.emitConsume(variable, xfer.consumer, targetType, emitFinish)); + return false; + } else if (xfer instanceof UnionInstantiationTransformer) { + if (!(targetType instanceof UnionType)) { + return panic("Union instantiation transformer must produce a union type"); + } + + const maybeNullable = nullableFromUnion(targetType); + if (maybeNullable !== null) { + emitFinish(variable); + } else { + const unionName = this.nameForNamedType(targetType); + let initializer: Sourcelike; + if (xfer.sourceType.kind === "null") { + initializer = " "; + } else { + const memberName = this.nameForUnionMember(targetType, xfer.sourceType); + initializer = [" ", memberName, " = ", variable, " "]; + } + + emitFinish(["new ", unionName, " {", initializer, "}"]); + } + + return true; + } else { + return panic("Unknown transformer"); + } + + return false; + } + + private emitTransformation(converterName: Name, t: Type): void { + const xf = defined(transformationForType(t)); + const reverse = xf.reverse; + const targetType = xf.targetType; + const xfer = xf.transformer; + this.emitType(undefined, AccessModifier.Internal, "class", converterName, "JsonConverter", () => { + const csType = this.csType(targetType); + let canConvertExpr: Sourcelike = ["t == typeof(", csType, ")"]; + const haveNullable = isValueType(targetType); + if (haveNullable) { + canConvertExpr = [canConvertExpr, " || t == typeof(", csType, "?)"]; + } + + this.emitCanConvert(canConvertExpr); + this.ensureBlankLine(); + this.emitReadJson(() => { + // FIXME: It's unsatisfying that we need this. The reason is that we not + // only match T, but also T?. If we didn't, then the T in T? would not be + // deserialized with our converter but with the default one. Can we check + // whether the type is a nullable? + // FIXME: This could duplicate one of the cases handled below in + // `emitDecodeTransformer`. + if (haveNullable && !(targetType instanceof UnionType)) { + this.emitLine("if (reader.TokenType == JsonToken.Null) return null;"); + } + + const allHandled = this.emitDecodeTransformer(xfer, targetType, v => this.emitLine("return ", v, ";")); + if (!allHandled) { + this.emitThrow(['"Cannot unmarshal type ', csType, '"']); + } + }); + this.ensureBlankLine(); + this.emitWriteJson("untypedValue", () => { + // FIXME: See above. + if (haveNullable && !(targetType instanceof UnionType)) { + this.emitLine("if (untypedValue == null)"); + this.emitBlock(() => { + this.emitLine("serializer.Serialize(writer, null);"); + this.emitLine("return;"); + }); + } + + this.emitLine("var value = (", csType, ")untypedValue;"); + const allHandled = this.emitTransformer("value", reverse.transformer, reverse.targetType, () => + this.emitLine("return;") + ); + if (!allHandled) { + this.emitThrow(['"Cannot marshal type ', csType, '"']); + } + }); + this.ensureBlankLine(); + this.emitLine("public static readonly ", converterName, " Singleton = new ", converterName, "();"); + }); + } + + protected emitRequiredHelpers(): void { + if (this._needHelpers) { + this.forEachTopLevel("leading-and-interposing", (t, n) => this.emitFromJsonForTopLevel(t, n)); + this.ensureBlankLine(); + this.emitSerializeClass(); + } + + if (this._needHelpers || (this._needAttributes && (this.haveNamedUnions || this.haveEnums))) { + this.ensureBlankLine(); + this.emitConverterClass(); + this.forEachTransformation("leading-and-interposing", (n, t) => this.emitTransformation(n, t)); + } + } + + protected needNamespace(): boolean { + return this._needNamespaces; + } +} diff --git a/packages/quicktype-core/src/language/CSharp/SystemTextJsonCSharpRenderer.ts b/packages/quicktype-core/src/language/CSharp/SystemTextJsonCSharpRenderer.ts new file mode 100644 index 000000000..77afed6da --- /dev/null +++ b/packages/quicktype-core/src/language/CSharp/SystemTextJsonCSharpRenderer.ts @@ -0,0 +1,982 @@ +import { arrayIntercalate } from "collection-utils"; + +import { type ForbiddenWordsInfo, inferredNameOrder } from "../../ConvenienceRenderer"; +import { DependencyName, type Name, SimpleName } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type Sourcelike, modifySource } from "../../Source"; +import { camelCase, utf16StringEscape } from "../../support/Strings"; +import { defined, panic } from "../../support/Support"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { + ArrayDecodingTransformer, + ArrayEncodingTransformer, + ChoiceTransformer, + DecodingChoiceTransformer, + DecodingTransformer, + EncodingTransformer, + MinMaxLengthCheckTransformer, + MinMaxValueTransformer, + ParseStringTransformer, + StringMatchTransformer, + StringProducerTransformer, + StringifyTransformer, + type Transformation, + type Transformer, + UnionInstantiationTransformer, + UnionMemberMatchTransformer, + followTargetType, + transformationForType +} from "../../Transformers"; +import { ArrayType, type ClassProperty, ClassType, EnumType, type Type, UnionType } from "../../Type"; +import { nullableFromUnion } from "../../TypeUtils"; + +import { CSharpRenderer } from "./CSharpRenderer"; +import { type systemTextJsonCSharpOptions } from "./language"; +import { + AccessModifier, + alwaysApplyTransformation, + denseJsonPropertyName, + denseNullValueHandlingEnumName, + isValueType, + namingFunction +} from "./utils"; + +export class SystemTextJsonCSharpRenderer extends CSharpRenderer { + private readonly _enumExtensionsNames = new Map(); + + private readonly _needHelpers: boolean; + + private readonly _needAttributes: boolean; + + private readonly _needNamespaces: boolean; + + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + private readonly _options: OptionValues + ) { + super(targetLanguage, renderContext, _options); + this._needHelpers = _options.features.helpers; + this._needAttributes = _options.features.attributes; + this._needNamespaces = _options.features.namespaces; + } + + protected forbiddenNamesForGlobalNamespace(): string[] { + const forbidden = [ + "Converter", + "JsonConverter", + "JsonSerializer", + "JsonWriter", + "JsonToken", + "Serialize", + "JsonSerializerOptions", + // "Newtonsoft", + // "MetadataPropertyHandling", + // "DateParseHandling", + "FromJson", + "Required" + ]; + if (this._options.dense) { + forbidden.push("J", "R", "N"); + } + + if (this._options.baseclass !== undefined) { + forbidden.push(this._options.baseclass); + } + + return super.forbiddenNamesForGlobalNamespace().concat(forbidden); + } + + protected forbiddenForObjectProperties(c: ClassType, className: Name): ForbiddenWordsInfo { + const result = super.forbiddenForObjectProperties(c, className); + result.names = result.names.concat(["ToJson", "FromJson", "Required"]); + return result; + } + + protected makeNameForTransformation(xf: Transformation, typeName: Name | undefined): Name { + if (typeName === undefined) { + let xfer = xf.transformer; + if (xfer instanceof DecodingTransformer && xfer.consumer !== undefined) { + xfer = xfer.consumer; + } + + return new SimpleName([`${xfer.kind}_converter`], namingFunction, inferredNameOrder + 30); + } + + return new DependencyName(namingFunction, typeName.order + 30, lookup => `${lookup(typeName)}_converter`); + } + + protected makeNamedTypeDependencyNames(t: Type, name: Name): DependencyName[] { + if (!(t instanceof EnumType)) return []; + + const extensionsName = new DependencyName( + namingFunction, + name.order + 30, + lookup => `${lookup(name)}_extensions` + ); + this._enumExtensionsNames.set(name, extensionsName); + return [extensionsName]; + } + + protected emitUsings(): void { + // FIXME: We need System.Collections.Generic whenever we have maps or use List. + if (!this._needAttributes && !this._needHelpers) return; + + super.emitUsings(); + this.ensureBlankLine(); + + for (const ns of ["System.Text.Json", "System.Text.Json.Serialization", "System.Globalization"]) { + this.emitUsing(ns); + } + + if (this._options.dense) { + this.emitUsing([denseJsonPropertyName, " = System.Text.Json.Serialization.JsonPropertyNameAttribute"]); + // this.emitUsing([denseRequiredEnumName, " = Newtonsoft.Json.Required"]); + this.emitUsing([denseNullValueHandlingEnumName, " = System.Text.Json.Serialization.JsonIgnoreCondition"]); + } + + if (this._options.baseclass === "EntityData") { + this.emitUsing("Microsoft.Azure.Mobile.Server"); + } + } + + protected baseclassForType(_t: Type): Sourcelike | undefined { + return this._options.baseclass; + } + + protected emitDefaultFollowingComments(): void { + if (!this._needHelpers) return; + + this.emitLine("#pragma warning restore CS8618"); + this.emitLine("#pragma warning restore CS8601"); + this.emitLine("#pragma warning restore CS8603"); + } + + protected emitDefaultLeadingComments(): void { + if (!this._needHelpers) return; + + this.emitLine("// "); + this.emitLine("//"); + this.emitLine( + "// To parse this JSON data, add NuGet 'System.Text.Json' then do", + this.topLevels.size === 1 ? "" : " one of these", + ":" + ); + this.emitLine("//"); + this.emitLine("// using ", this._options.namespace, ";"); + this.emitLine("//"); + this.forEachTopLevel("none", (t, topLevelName) => { + let rhs: Sourcelike; + if (t instanceof EnumType) { + rhs = ["JsonSerializer.Deserialize<", topLevelName, ">(jsonString)"]; + } else { + rhs = [topLevelName, ".FromJson(jsonString)"]; + } + + this.emitLine("// var ", modifySource(camelCase, topLevelName), " = ", rhs, ";"); + }); + + // fix: should this be an option? Or respond to an existing option? + this.emitLine("#nullable enable"); + this.emitLine("#pragma warning disable CS8618"); + this.emitLine("#pragma warning disable CS8601"); + this.emitLine("#pragma warning disable CS8603"); + } + + private converterForType(t: Type): Name | undefined { + let xf = transformationForType(t); + + if (xf === undefined && t instanceof UnionType) { + const maybeNullable = nullableFromUnion(t); + if (maybeNullable !== null) { + t = maybeNullable; + xf = transformationForType(t); + } + } + + if (xf === undefined) return undefined; + + if (alwaysApplyTransformation(xf)) return undefined; + + return defined(this.nameForTransformation(t)); + } + + protected attributesForProperty( + property: ClassProperty, + _name: Name, + _c: ClassType, + jsonName: string + ): Sourcelike[] | undefined { + if (!this._needAttributes) return undefined; + + const attributes: Sourcelike[] = []; + + const jsonPropertyName = this._options.dense ? denseJsonPropertyName : "JsonPropertyName"; + const escapedName = utf16StringEscape(jsonName); + const isNullable = followTargetType(property.type).isNullable; + const isOptional = property.isOptional; + + if (isOptional && !isNullable) { + attributes.push(["[", "JsonIgnore", "(Condition = JsonIgnoreCondition.WhenWritingNull)]"]); + } + + // const requiredClass = this._options.dense ? "R" : "Required"; + // const nullValueHandlingClass = this._options.dense ? "N" : "NullValueHandling"; + // const nullValueHandling = isOptional && !isNullable ? [", NullValueHandling = ", nullValueHandlingClass, ".Ignore"] : []; + // let required: Sourcelike; + // if (!this._options.checkRequired || (isOptional && isNullable)) { + // required = [nullValueHandling]; + // } else if (isOptional && !isNullable) { + // required = [", Required = ", requiredClass, ".DisallowNull", nullValueHandling]; + // } else if (!isOptional && isNullable) { + // required = [", Required = ", requiredClass, ".AllowNull"]; + // } else { + // required = [", Required = ", requiredClass, ".Always", nullValueHandling]; + // } + + attributes.push(["[", jsonPropertyName, '("', escapedName, '")]']); + + const converter = this.converterForType(property.type); + if (converter !== undefined) { + attributes.push(["[JsonConverter(typeof(", converter, "))]"]); + } + + return attributes; + } + + protected blankLinesBetweenAttributes(): boolean { + return this._needAttributes && !this._options.dense; + } + + // The "this" type can't be `dynamic`, so we have to force it to `object`. + private topLevelResultType(t: Type): Sourcelike { + return t.kind === "any" || t.kind === "none" ? "object" : this.csType(t); + } + + private emitFromJsonForTopLevel(t: Type, name: Name): void { + if (t instanceof EnumType) return; + + let partial: string; + let typeKind: string; + const definedType = this.namedTypeToNameForTopLevel(t); + if (definedType !== undefined) { + partial = "partial "; + typeKind = definedType instanceof ClassType ? "class" : "struct"; + } else { + partial = ""; + typeKind = "class"; + } + + const csType = this.topLevelResultType(t); + this.emitType(undefined, AccessModifier.Public, [partial, typeKind], name, this.baseclassForType(t), () => { + // FIXME: Make FromJson a Named + this.emitExpressionMember( + ["public static ", csType, " FromJson(string json)"], + ["JsonSerializer.Deserialize<", csType, ">(json, ", this._options.namespace, ".Converter.Settings)"] + ); + }); + } + + private emitDecoderSwitch(emitBody: () => void): void { + this.emitLine("switch (reader.TokenType)"); + this.emitBlock(emitBody); + } + + private emitTokenCase(tokenType: string): void { + this.emitLine("case JsonTokenType.", tokenType, ":"); + } + + private emitThrow(message: Sourcelike): void { + this.emitLine("throw new Exception(", message, ");"); + } + + private deserializeTypeCode(typeName: Sourcelike): Sourcelike { + switch (typeName) { + case "bool": + return ["reader.GetBoolean()"]; + case "long": + return ["reader.GetInt64()"]; + case "decimal": + return ["reader.GetDecimal()"]; + case "double": + return ["reader.GetDouble()"]; + case "string": + return ["reader.GetString()"]; + default: + return ["JsonSerializer.Deserialize<", typeName, ">(ref reader, options)"]; + } + } + + private serializeValueCode(value: Sourcelike): Sourcelike { + if (value !== "null") return ["JsonSerializer.Serialize(writer, ", value, ", options)"]; + else return ["writer.WriteNullValue()"]; + } + + private emitSerializeClass(): void { + // FIXME: Make Serialize a Named + this.emitType(undefined, AccessModifier.Public, "static class", "Serialize", undefined, () => { + // Sometimes multiple top-levels will resolve to the same type, so we have to take care + // not to emit more than one extension method for the same type. + const seenTypes = new Set(); + this.forEachTopLevel("none", t => { + // FIXME: Make ToJson a Named + if (!seenTypes.has(t)) { + seenTypes.add(t); + this.emitExpressionMember( + ["public static string ToJson(this ", this.topLevelResultType(t), " self)"], + ["JsonSerializer.Serialize(self, ", this._options.namespace, ".Converter.Settings)"] + ); + } + }); + }); + } + + private emitCanConvert(expr: Sourcelike): void { + this.emitExpressionMember("public override bool CanConvert(Type t)", expr); + } + + private emitReadJson(emitBody: () => void, csType: Sourcelike): void { + this.emitLine( + "public override ", + csType, + " Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)" + ); + this.emitBlock(emitBody); + } + + private emitWriteJson(variable: string, emitBody: () => void, csType: Sourcelike): void { + this.emitLine( + "public override void Write(Utf8JsonWriter writer, ", + csType, + " ", + variable, + ", JsonSerializerOptions options)" + ); + this.emitBlock(emitBody); + } + + private converterObject(converterName: Name): Sourcelike { + // FIXME: Get a singleton + return [converterName, ".Singleton"]; + } + + private emitConverterClass(): void { + // FIXME: Make Converter a Named + const converterName: Sourcelike = ["Converter"]; + this.emitType(undefined, AccessModifier.Internal, "static class", converterName, undefined, () => { + // Do not use .Web as defaults. That turns on caseInsensitive property names and will fail the keywords test. + this.emitLine( + "public static readonly JsonSerializerOptions Settings = new(JsonSerializerDefaults.General)" + ); + this.emitBlock(() => { + // this.emitLine("MetadataPropertyHandling = MetadataPropertyHandling.Ignore,"); + // this.emitLine("DateParseHandling = DateParseHandling.None,"); + this.emitLine("Converters ="); + this.emitLine("{"); + this.indent(() => { + for (const [t, converter] of this.typesWithNamedTransformations) { + if (alwaysApplyTransformation(defined(transformationForType(t)))) { + this.emitLine(this.converterObject(converter), ","); + } + } + + this.emitLine("new DateOnlyConverter(),"); + this.emitLine("new TimeOnlyConverter(),"); + this.emitLine("IsoDateTimeOffsetConverter.Singleton"); + // this.emitLine("new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }"); + }); + this.emitLine("},"); + }, true); + }); + } + + private emitDecoderTransformerCase( + tokenCases: string[], + variableName: string, + xfer: Transformer | undefined, + targetType: Type, + emitFinish: (value: Sourcelike) => void + ): void { + if (xfer === undefined) return; + + for (const tokenCase of tokenCases) { + this.emitTokenCase(tokenCase); + } + + this.indent(() => { + const allHandled = this.emitDecodeTransformer(xfer, targetType, emitFinish, variableName); + if (!allHandled) { + this.emitLine("break;"); + } + }); + } + + private emitConsume( + value: Sourcelike, + consumer: Transformer | undefined, + targetType: Type, + emitFinish: (variableName: Sourcelike) => void + ): boolean { + if (consumer === undefined) { + emitFinish(value); + return true; + } else { + return this.emitTransformer(value, consumer, targetType, emitFinish); + } + } + + private emitDecodeTransformer( + xfer: Transformer, + targetType: Type, + emitFinish: (value: Sourcelike) => void, + variableName = "value" + ): boolean { + if (xfer instanceof DecodingTransformer) { + const source = xfer.sourceType; + const converter = this.converterForType(targetType); + if (converter !== undefined) { + const typeSource = this.csType(targetType); + this.emitLine("var converter = ", this.converterObject(converter), ";"); + this.emitLine( + "var ", + variableName, + " = (", + typeSource, + ")converter.ReadJson(reader, typeof(", + typeSource, + "), null, serializer);" + ); + } else if (source.kind !== "null") { + let output = targetType.kind === "double" ? targetType : source; + this.emitLine("var ", variableName, " = ", this.deserializeTypeCode(this.csType(output)), ";"); + } + + return this.emitConsume(variableName, xfer.consumer, targetType, emitFinish); + } else if (xfer instanceof ArrayDecodingTransformer) { + // FIXME: Consume StartArray + if (!(targetType instanceof ArrayType)) { + return panic("Array decoding must produce an array type"); + } + + // FIXME: handle EOF + this.emitLine("reader.Read();"); + this.emitLine("var ", variableName, " = new List<", this.csType(targetType.items), ">();"); + this.emitLine("while (reader.TokenType != JsonToken.EndArray)"); + this.emitBlock(() => { + this.emitDecodeTransformer( + xfer.itemTransformer, + xfer.itemTargetType, + v => this.emitLine(variableName, ".Add(", v, ");"), + "arrayItem" + ); + // FIXME: handle EOF + this.emitLine("reader.Read();"); + }); + let result: Sourcelike = variableName; + if (!this._options.useList) { + result = [result, ".ToArray()"]; + } + + emitFinish(result); + return true; + } else if (xfer instanceof DecodingChoiceTransformer) { + this.emitDecoderSwitch(() => { + const nullTransformer = xfer.nullTransformer; + if (nullTransformer !== undefined) { + this.emitTokenCase("Null"); + this.indent(() => { + const allHandled = this.emitDecodeTransformer(nullTransformer, targetType, emitFinish, "null"); + if (!allHandled) { + this.emitLine("break"); + } + }); + } + + this.emitDecoderTransformerCase( + ["Number"], + "integerValue", + xfer.integerTransformer, + targetType, + emitFinish + ); + this.emitDecoderTransformerCase( + ["Number"], + // xfer.integerTransformer === undefined ? ["Integer", "Float"] : ["Float"], + "doubleValue", + xfer.doubleTransformer, + targetType, + emitFinish + ); + this.emitDecoderTransformerCase( + ["True", "False"], + "boolValue", + xfer.boolTransformer, + targetType, + emitFinish + ); + this.emitDecoderTransformerCase( + // ["String", "Date"], + ["String"], + "stringValue", + xfer.stringTransformer, + targetType, + emitFinish + ); + this.emitDecoderTransformerCase( + ["StartObject"], + "objectValue", + xfer.objectTransformer, + targetType, + emitFinish + ); + this.emitDecoderTransformerCase( + ["StartArray"], + "arrayValue", + xfer.arrayTransformer, + targetType, + emitFinish + ); + }); + return false; + } else { + return panic("Unknown transformer"); + } + } + + private stringCaseValue(t: Type, stringCase: string): Sourcelike { + if (t.kind === "string") { + return ['"', utf16StringEscape(stringCase), '"']; + } else if (t instanceof EnumType) { + return [this.nameForNamedType(t), ".", this.nameForEnumCase(t, stringCase)]; + } + + return panic(`Type ${t.kind} does not have string cases`); + } + + private emitTransformer( + variable: Sourcelike, + xfer: Transformer, + targetType: Type, + emitFinish: (value: Sourcelike) => void + ): boolean { + function directTargetType(continuation: Transformer | undefined): Type { + if (continuation === undefined) { + return targetType; + } + + return followTargetType(continuation.sourceType); + } + + if (xfer instanceof ChoiceTransformer) { + const caseXfers = xfer.transformers; + if (caseXfers.length > 1 && caseXfers.every(caseXfer => caseXfer instanceof StringMatchTransformer)) { + this.emitLine("switch (", variable, ")"); + this.emitBlock(() => { + for (const caseXfer of caseXfers) { + const matchXfer = caseXfer as StringMatchTransformer; + const value = this.stringCaseValue( + followTargetType(matchXfer.sourceType), + matchXfer.stringCase + ); + this.emitLine("case ", value, ":"); + this.indent(() => { + const allDone = this.emitTransformer( + variable, + matchXfer.transformer, + targetType, + emitFinish + ); + if (!allDone) { + this.emitLine("break;"); + } + }); + } + }); + // FIXME: Can we check for exhaustiveness? For enums it should be easy. + return false; + } else { + for (const caseXfer of caseXfers) { + this.emitTransformer(variable, caseXfer, targetType, emitFinish); + } + } + } else if (xfer instanceof UnionMemberMatchTransformer) { + const memberType = xfer.memberType; + const maybeNullable = nullableFromUnion(xfer.sourceType); + let test: Sourcelike; + let member: Sourcelike; + if (maybeNullable !== null) { + if (memberType.kind === "null") { + test = [variable, " == null"]; + member = "null"; + } else { + test = [variable, " != null"]; + member = variable; + } + } else if (memberType.kind === "null") { + test = [variable, ".IsNull"]; + member = "null"; + } else { + const memberName = this.nameForUnionMember(xfer.sourceType, memberType); + member = [variable, ".", memberName]; + test = [member, " != null"]; + } + + if (memberType.kind !== "null" && isValueType(memberType)) { + member = [member, ".Value"]; + } + + this.emitLine("if (", test, ")"); + this.emitBlock(() => this.emitTransformer(member, xfer.transformer, targetType, emitFinish)); + } else if (xfer instanceof StringMatchTransformer) { + const value = this.stringCaseValue(followTargetType(xfer.sourceType), xfer.stringCase); + this.emitLine("if (", variable, " == ", value, ")"); + this.emitBlock(() => this.emitTransformer(variable, xfer.transformer, targetType, emitFinish)); + } else if (xfer instanceof EncodingTransformer) { + const converter = this.converterForType(xfer.sourceType); + if (converter !== undefined) { + this.emitLine("var converter = ", this.converterObject(converter), ";"); + this.emitLine("converter.WriteJson(writer, ", variable, ", serializer);"); + } else { + this.emitLine(this.serializeValueCode(variable), ";"); + } + + emitFinish([]); + return true; + } else if (xfer instanceof ArrayEncodingTransformer) { + this.emitLine("writer.WriteStartArray();"); + const itemVariable = "arrayItem"; + this.emitLine("foreach (var ", itemVariable, " in ", variable, ")"); + this.emitBlock(() => { + this.emitTransformer(itemVariable, xfer.itemTransformer, xfer.itemTargetType, () => { + return; + }); + }); + this.emitLine("writer.WriteEndArray();"); + emitFinish([]); + return true; + } else if (xfer instanceof ParseStringTransformer) { + const immediateTargetType = xfer.consumer === undefined ? targetType : xfer.consumer.sourceType; + switch (immediateTargetType.kind) { + case "date-time": + this.emitLine("DateTimeOffset dt;"); + this.emitLine("if (DateTimeOffset.TryParse(", variable, ", out dt))"); + this.emitBlock(() => this.emitConsume("dt", xfer.consumer, targetType, emitFinish)); + break; + case "uuid": + this.emitLine("Guid guid;"); + this.emitLine("if (Guid.TryParse(", variable, ", out guid))"); + this.emitBlock(() => this.emitConsume("guid", xfer.consumer, targetType, emitFinish)); + break; + case "uri": + this.emitLine("try"); + this.emitBlock(() => { + // this.emitLine("var uri = new Uri(", variable, ");"); + // The default value about:blank should never happen, but this way we avoid a null reference warning. + this.emitLine('var uri = new Uri("about:blank");'); + this.emitLine("if (!string.IsNullOrEmpty(stringValue))"); + this.emitBlock(() => { + this.emitLine("uri = new Uri(", variable, ");"); + }); + this.emitConsume("uri", xfer.consumer, targetType, emitFinish); + }); + this.emitLine("catch (UriFormatException) {}"); + break; + case "integer": + this.emitLine("long l;"); + this.emitLine("if (Int64.TryParse(", variable, ", out l))"); + this.emitBlock(() => this.emitConsume("l", xfer.consumer, targetType, emitFinish)); + break; + case "bool": + this.emitLine("bool b;"); + this.emitLine("if (Boolean.TryParse(", variable, ", out b))"); + this.emitBlock(() => this.emitConsume("b", xfer.consumer, targetType, emitFinish)); + break; + default: + return panic(`Parsing string to ${immediateTargetType.kind} not supported`); + } + } else if (xfer instanceof StringifyTransformer) { + switch (xfer.sourceType.kind) { + case "date-time": + return this.emitConsume( + [variable, '.ToString("o", System.Globalization.CultureInfo.InvariantCulture)'], + xfer.consumer, + targetType, + emitFinish + ); + case "uuid": + return this.emitConsume( + [variable, '.ToString("D", System.Globalization.CultureInfo.InvariantCulture)'], + xfer.consumer, + targetType, + emitFinish + ); + case "integer": + case "uri": + return this.emitConsume([variable, ".ToString()"], xfer.consumer, targetType, emitFinish); + case "bool": + this.emitLine("var boolString = ", variable, ' ? "true" : "false";'); + return this.emitConsume("boolString", xfer.consumer, targetType, emitFinish); + default: + return panic(`Stringifying ${xfer.sourceType.kind} not supported`); + } + } else if (xfer instanceof StringProducerTransformer) { + const value = this.stringCaseValue(directTargetType(xfer.consumer), xfer.result); + return this.emitConsume(value, xfer.consumer, targetType, emitFinish); + } else if (xfer instanceof MinMaxLengthCheckTransformer) { + const min = xfer.minLength; + const max = xfer.maxLength; + const conditions: Sourcelike[] = []; + + if (min !== undefined) { + conditions.push([variable, ".Length >= ", min.toString()]); + } + + if (max !== undefined) { + conditions.push([variable, ".Length <= ", max.toString()]); + } + + this.emitLine("if (", arrayIntercalate([" && "], conditions), ")"); + this.emitBlock(() => this.emitConsume(variable, xfer.consumer, targetType, emitFinish)); + return false; + } else if (xfer instanceof MinMaxValueTransformer) { + const min = xfer.minimum; + const max = xfer.maximum; + const conditions: Sourcelike[] = []; + + if (min !== undefined) { + conditions.push([variable, " >= ", min.toString()]); + } + + if (max !== undefined) { + conditions.push([variable, " <= ", max.toString()]); + } + + this.emitLine("if (", arrayIntercalate([" && "], conditions), ")"); + this.emitBlock(() => this.emitConsume(variable, xfer.consumer, targetType, emitFinish)); + return false; + } else if (xfer instanceof UnionInstantiationTransformer) { + if (!(targetType instanceof UnionType)) { + return panic("Union instantiation transformer must produce a union type"); + } + + const maybeNullable = nullableFromUnion(targetType); + if (maybeNullable !== null) { + emitFinish(variable); + } else { + const unionName = this.nameForNamedType(targetType); + let initializer: Sourcelike; + if (xfer.sourceType.kind === "null") { + initializer = " "; + } else { + const memberName = this.nameForUnionMember(targetType, xfer.sourceType); + initializer = [" ", memberName, " = ", variable, " "]; + } + + emitFinish(["new ", unionName, " {", initializer, "}"]); + } + + return true; + } else { + return panic("Unknown transformer"); + } + + return false; + } + + private emitTransformation(converterName: Name, t: Type): void { + const xf = defined(transformationForType(t)); + const reverse = xf.reverse; + const targetType = xf.targetType; + const xfer = xf.transformer; + const csType = this.csType(targetType); + // const haveNullable = isValueType(targetType); + + // if (haveNullable) { + // converterName = ['Nullable', converterName]; + // csType = [csType, "?"]; + // } + this.emitType( + undefined, + AccessModifier.Internal, + "class", + converterName, + ["JsonConverter<", csType, ">"], + () => { + let canConvertExpr: Sourcelike = ["t == typeof(", csType, ")"]; + this.emitCanConvert(canConvertExpr); + this.ensureBlankLine(); + this.emitReadJson(() => { + // FIXME: It's unsatisfying that we need this. The reason is that we not + // only match T, but also T?. If we didn't, then the T in T? would not be + // deserialized with our converter but with the default one. Can we check + // whether the type is a nullable? + // FIXME: This could duplicate one of the cases handled below in + // `emitDecodeTransformer`. + // if (haveNullable && !(targetType instanceof UnionType)) { + // this.emitLine("if (reader.TokenType == JsonTokenType.Null) return null;"); + // } + + const allHandled = this.emitDecodeTransformer(xfer, targetType, v => + this.emitLine("return ", v, ";") + ); + if (!allHandled) { + this.emitThrow(['"Cannot unmarshal type ', csType, '"']); + } + }, csType); + this.ensureBlankLine(); + this.emitWriteJson( + "value", + () => { + // FIXME: See above. + // if (haveNullable && !(targetType instanceof UnionType)) { + // this.emitLine("if (value == null)"); + // this.emitBlock(() => { + // this.emitLine("writer.WriteNullValue();"); + // this.emitLine("return;"); + // }); + // } + + const allHandled = this.emitTransformer("value", reverse.transformer, reverse.targetType, () => + this.emitLine("return;") + ); + if (!allHandled) { + this.emitThrow(['"Cannot marshal type ', csType, '"']); + } + }, + csType + ); + this.ensureBlankLine(); + this.emitLine("public static readonly ", converterName, " Singleton = new ", converterName, "();"); + } + ); + } + + protected emitRequiredHelpers(): void { + if (this._needHelpers) { + this.forEachTopLevel("leading-and-interposing", (t, n) => this.emitFromJsonForTopLevel(t, n)); + this.ensureBlankLine(); + this.emitSerializeClass(); + } + + if (this._needHelpers || (this._needAttributes && (this.haveNamedUnions || this.haveEnums))) { + this.ensureBlankLine(); + this.emitConverterClass(); + this.forEachTransformation("leading-and-interposing", (n, t) => this.emitTransformation(n, t)); + this.emitMultiline(` +public class DateOnlyConverter : JsonConverter +{ + private readonly string serializationFormat; + public DateOnlyConverter() : this(null) { } + + public DateOnlyConverter(string? serializationFormat) + { + this.serializationFormat = serializationFormat ?? "yyyy-MM-dd"; + } + + public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var value = reader.GetString(); + return DateOnly.Parse(value!); + } + + public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options) + => writer.WriteStringValue(value.ToString(serializationFormat)); +} + +public class TimeOnlyConverter : JsonConverter +{ + private readonly string serializationFormat; + + public TimeOnlyConverter() : this(null) { } + + public TimeOnlyConverter(string? serializationFormat) + { + this.serializationFormat = serializationFormat ?? "HH:mm:ss.fff"; + } + + public override TimeOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var value = reader.GetString(); + return TimeOnly.Parse(value!); + } + + public override void Write(Utf8JsonWriter writer, TimeOnly value, JsonSerializerOptions options) + => writer.WriteStringValue(value.ToString(serializationFormat)); +} + +internal class IsoDateTimeOffsetConverter : JsonConverter +{ + public override bool CanConvert(Type t) => t == typeof(DateTimeOffset); + + private const string DefaultDateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; + + private DateTimeStyles _dateTimeStyles = DateTimeStyles.RoundtripKind; + private string? _dateTimeFormat; + private CultureInfo? _culture; + + public DateTimeStyles DateTimeStyles + { + get => _dateTimeStyles; + set => _dateTimeStyles = value; + } + + public string? DateTimeFormat + { + get => _dateTimeFormat ?? string.Empty; + set => _dateTimeFormat = (string.IsNullOrEmpty(value)) ? null : value; + } + + public CultureInfo Culture + { + get => _culture ?? CultureInfo.CurrentCulture; + set => _culture = value; + } + + public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options) + { + string text; + + + if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal + || (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal) + { + value = value.ToUniversalTime(); + } + + text = value.ToString(_dateTimeFormat ?? DefaultDateTimeFormat, Culture); + + writer.WriteStringValue(text); + } + + public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + string? dateText = reader.GetString(); + + if (string.IsNullOrEmpty(dateText) == false) + { + if (!string.IsNullOrEmpty(_dateTimeFormat)) + { + return DateTimeOffset.ParseExact(dateText, _dateTimeFormat, Culture, _dateTimeStyles); + } + else + { + return DateTimeOffset.Parse(dateText, Culture, _dateTimeStyles); + } + } + else + { + return default(DateTimeOffset); + } + } + + + public static readonly IsoDateTimeOffsetConverter Singleton = new IsoDateTimeOffsetConverter(); +}`); + } + } + + protected needNamespace(): boolean { + return this._needNamespaces; + } +} diff --git a/packages/quicktype-core/src/language/CSharp/constants.ts b/packages/quicktype-core/src/language/CSharp/constants.ts new file mode 100644 index 000000000..bbe7f3dfb --- /dev/null +++ b/packages/quicktype-core/src/language/CSharp/constants.ts @@ -0,0 +1,79 @@ +export const keywords = [ + "abstract", + "as", + "base", + "bool", + "break", + "byte", + "case", + "catch", + "char", + "checked", + "class", + "const", + "continue", + "decimal", + "default", + "delegate", + "do", + "double", + "else", + "enum", + "event", + "explicit", + "extern", + "false", + "finally", + "fixed", + "float", + "for", + "foreach", + "goto", + "if", + "implicit", + "in", + "int", + "interface", + "internal", + "is", + "lock", + "long", + "namespace", + "new", + "null", + "object", + "operator", + "out", + "override", + "params", + "private", + "protected", + "public", + "readonly", + "ref", + "return", + "sbyte", + "sealed", + "short", + "sizeof", + "stackalloc", + "static", + "string", + "struct", + "switch", + "this", + "throw", + "true", + "try", + "typeof", + "uint", + "ulong", + "unchecked", + "unsafe", + "ushort", + "using", + "virtual", + "void", + "volatile", + "while" +] as const; diff --git a/packages/quicktype-core/src/language/CSharp/index.ts b/packages/quicktype-core/src/language/CSharp/index.ts new file mode 100644 index 000000000..c9f7c6d8c --- /dev/null +++ b/packages/quicktype-core/src/language/CSharp/index.ts @@ -0,0 +1,4 @@ +export { CSharpTargetLanguage, cSharpOptions, newtonsoftCSharpOptions, systemTextJsonCSharpOptions } from "./language"; +export { CSharpRenderer } from "./CSharpRenderer"; +export { NewtonsoftCSharpRenderer } from "./NewtonSoftCSharpRenderer"; +export { SystemTextJsonCSharpRenderer } from "./SystemTextJsonCSharpRenderer"; diff --git a/packages/quicktype-core/src/language/CSharp/language.ts b/packages/quicktype-core/src/language/CSharp/language.ts new file mode 100644 index 000000000..e2b460582 --- /dev/null +++ b/packages/quicktype-core/src/language/CSharp/language.ts @@ -0,0 +1,175 @@ +import { type ConvenienceRenderer } from "../../ConvenienceRenderer"; +import { type RenderContext } from "../../Renderer"; +import { BooleanOption, EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { assertNever } from "../../support/Support"; +import { TargetLanguage } from "../../TargetLanguage"; +import { type PrimitiveStringTypeKind, type TransformedStringTypeKind, type Type } from "../../Type"; +import { type StringTypeMapping } from "../../TypeBuilder"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; + +import { NewtonsoftCSharpRenderer } from "./NewtonSoftCSharpRenderer"; +import { SystemTextJsonCSharpRenderer } from "./SystemTextJsonCSharpRenderer"; +import { needTransformerForType } from "./utils"; + +export enum Framework { + Newtonsoft = "Newtonsoft", + SystemTextJson = "SystemTextJson" +} + +export type Version = 5 | 6; +export interface OutputFeatures { + attributes: boolean; + helpers: boolean; +} + +export type CSharpTypeForAny = "object" | "dynamic"; + +export const cSharpOptions = { + framework: new EnumOption( + "framework", + "Serialization framework", + [ + ["NewtonSoft", Framework.Newtonsoft], + ["SystemTextJson", Framework.SystemTextJson] + ], + "NewtonSoft" + ), + useList: new EnumOption("array-type", "Use T[] or List", [ + ["array", false], + ["list", true] + ]), + dense: new EnumOption( + "density", + "Property density", + [ + ["normal", false], + ["dense", true] + ], + "normal", + "secondary" + ), + // FIXME: Do this via a configurable named eventually. + namespace: new StringOption("namespace", "Generated namespace", "NAME", "QuickType"), + version: new EnumOption( + "csharp-version", + "C# version", + [ + ["5", 5], + ["6", 6] + ], + "6", + "secondary" + ), + virtual: new BooleanOption("virtual", "Generate virtual properties", false), + typeForAny: new EnumOption( + "any-type", + 'Type to use for "any"', + [ + ["object", "object"], + ["dynamic", "dynamic"] + ], + "object", + "secondary" + ), + useDecimal: new EnumOption( + "number-type", + "Type to use for numbers", + [ + ["double", false], + ["decimal", true] + ], + "double", + "secondary" + ), + features: new EnumOption("features", "Output features", [ + ["complete", { namespaces: true, helpers: true, attributes: true }], + ["attributes-only", { namespaces: true, helpers: false, attributes: true }], + ["just-types-and-namespace", { namespaces: true, helpers: false, attributes: false }], + ["just-types", { namespaces: true, helpers: false, attributes: false }] + ]), + baseclass: new EnumOption( + "base-class", + "Base class", + [ + ["EntityData", "EntityData"], + ["Object", undefined] + ], + "Object", + "secondary" + ), + checkRequired: new BooleanOption("check-required", "Fail if required properties are missing", false), + keepPropertyName: new BooleanOption("keep-property-name", "Keep original field name generate", false) +}; + +export const newtonsoftCSharpOptions = Object.assign({}, cSharpOptions, {}); + +export const systemTextJsonCSharpOptions = Object.assign({}, cSharpOptions, {}); + +export class CSharpTargetLanguage extends TargetLanguage { + public constructor() { + super("C#", ["cs", "csharp"], "cs"); + } + + protected getOptions(): Array> { + return [ + cSharpOptions.framework, + cSharpOptions.namespace, + cSharpOptions.version, + cSharpOptions.dense, + cSharpOptions.useList, + cSharpOptions.useDecimal, + cSharpOptions.typeForAny, + cSharpOptions.virtual, + cSharpOptions.features, + cSharpOptions.baseclass, + cSharpOptions.checkRequired, + cSharpOptions.keepPropertyName + ]; + } + + public get stringTypeMapping(): StringTypeMapping { + const mapping: Map = new Map(); + mapping.set("date", "date-time"); + mapping.set("time", "date-time"); + mapping.set("date-time", "date-time"); + mapping.set("uuid", "uuid"); + mapping.set("uri", "uri"); + mapping.set("integer-string", "integer-string"); + mapping.set("bool-string", "bool-string"); + return mapping; + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + public needsTransformerForType(t: Type): boolean { + const need = needTransformerForType(t); + return need !== "none" && need !== "nullable"; + } + + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): ConvenienceRenderer { + const options = getOptionValues(cSharpOptions, untypedOptionValues); + + switch (options.framework) { + case Framework.Newtonsoft: + return new NewtonsoftCSharpRenderer( + this, + renderContext, + getOptionValues(newtonsoftCSharpOptions, untypedOptionValues) + ); + case Framework.SystemTextJson: + return new SystemTextJsonCSharpRenderer( + this, + renderContext, + getOptionValues(systemTextJsonCSharpOptions, untypedOptionValues) + ); + default: + return assertNever(options.framework); + } + } +} diff --git a/packages/quicktype-core/src/language/CSharp/utils.ts b/packages/quicktype-core/src/language/CSharp/utils.ts new file mode 100644 index 000000000..856de95ca --- /dev/null +++ b/packages/quicktype-core/src/language/CSharp/utils.ts @@ -0,0 +1,147 @@ +import unicode from "unicode-properties"; + +import { minMaxLengthForType, minMaxValueForType } from "../../attributes/Constraints"; +import { funPrefixNamer } from "../../Naming"; +import { type Sourcelike } from "../../Source"; +import { + type WordInName, + combineWords, + firstUpperWordStyle, + splitIntoWords, + utf16LegalizeCharacters +} from "../../support/Strings"; +import { panic } from "../../support/Support"; +import { type Transformation } from "../../Transformers"; +import { ArrayType, EnumType, type PrimitiveType, type Type, UnionType } from "../../Type"; +import { nullableFromUnion } from "../../TypeUtils"; + +import { keywords } from "./constants"; + +export enum AccessModifier { + None = "None", + Public = "Public", + Internal = "Internal" +} + +export function noFollow(t: Type): Type { + return t; +} + +export function needTransformerForType(t: Type): "automatic" | "manual" | "nullable" | "none" { + if (t instanceof UnionType) { + const maybeNullable = nullableFromUnion(t); + if (maybeNullable === null) return "automatic"; + if (needTransformerForType(maybeNullable) === "manual") return "nullable"; + return "none"; + } + + if (t instanceof ArrayType) { + const itemsNeed = needTransformerForType(t.items); + if (itemsNeed === "manual" || itemsNeed === "nullable") return "automatic"; + return "none"; + } + + if (t instanceof EnumType) return "automatic"; + if (t.kind === "double") return minMaxValueForType(t) !== undefined ? "manual" : "none"; + if (t.kind === "integer-string" || t.kind === "bool-string") return "manual"; + if (t.kind === "string") { + return minMaxLengthForType(t) !== undefined ? "manual" : "none"; + } + + return "none"; +} + +export function alwaysApplyTransformation(xf: Transformation): boolean { + const t = xf.targetType; + if (t instanceof EnumType) return true; + if (t instanceof UnionType) return nullableFromUnion(t) === null; + return false; +} + +/** + * The C# type for a given transformed string type. + */ +export function csTypeForTransformedStringType(t: PrimitiveType): Sourcelike { + switch (t.kind) { + case "date-time": + return "DateTimeOffset"; + case "uuid": + return "Guid"; + case "uri": + return "Uri"; + default: + return panic(`Transformed string type ${t.kind} not supported`); + } +} + +export const namingFunction = funPrefixNamer("namer", csNameStyle); +export const namingFunctionKeep = funPrefixNamer("namerKeep", csNameStyleKeep); + +// FIXME: Make a Named? +export const denseJsonPropertyName = "J"; +export const denseRequiredEnumName = "R"; +export const denseNullValueHandlingEnumName = "N"; + +export function isStartCharacter(utf16Unit: number): boolean { + if (unicode.isAlphabetic(utf16Unit)) { + return true; + } + + return utf16Unit === 0x5f; // underscore +} + +function isPartCharacter(utf16Unit: number): boolean { + const category: string = unicode.getCategory(utf16Unit); + if (["Nd", "Pc", "Mn", "Mc"].includes(category)) { + return true; + } + + return isStartCharacter(utf16Unit); +} + +const legalizeName = utf16LegalizeCharacters(isPartCharacter); + +export function csNameStyle(original: string): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + firstUpperWordStyle, + firstUpperWordStyle, + firstUpperWordStyle, + firstUpperWordStyle, + "", + isStartCharacter + ); +} + +function csNameStyleKeep(original: string): string { + const words: WordInName[] = [ + { + word: original, + isAcronym: false + } + ]; + + const result = combineWords( + words, + legalizeName, + x => x, + x => x, + x => x, + x => x, + "", + isStartCharacter + ); + + // @ts-expect-error needs strong type + return keywords.includes(result) ? "@" + result : result; +} + +export function isValueType(t: Type): boolean { + if (t instanceof UnionType) { + return nullableFromUnion(t) === null; + } + + return ["integer", "double", "bool", "enum", "date-time", "uuid"].includes(t.kind); +} diff --git a/packages/quicktype-core/src/language/Crystal.ts b/packages/quicktype-core/src/language/Crystal/CrystalRenderer.ts similarity index 56% rename from packages/quicktype-core/src/language/Crystal.ts rename to packages/quicktype-core/src/language/Crystal/CrystalRenderer.ts index 9816191bc..e699b9b9b 100644 --- a/packages/quicktype-core/src/language/Crystal.ts +++ b/packages/quicktype-core/src/language/Crystal/CrystalRenderer.ts @@ -1,234 +1,14 @@ -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { type Name, type Namer, funPrefixNamer } from "../Naming"; -import { type RenderContext } from "../Renderer"; -import { type Option } from "../RendererOptions"; -import { type Sourcelike, maybeAnnotated } from "../Source"; -import { - allLowerWordStyle, - combineWords, - escapeNonPrintableMapper, - firstUpperWordStyle, - intToHex, - isAscii, - isLetterOrUnderscore, - isLetterOrUnderscoreOrDigit, - isPrintable, - legalizeCharacters, - splitIntoWords, - utf32ConcatMap -} from "../support/Strings"; -import { TargetLanguage } from "../TargetLanguage"; -import { type ClassType, type EnumType, type Type, type UnionType } from "../Type"; -import { type FixMeOptionsAnyType } from "../types"; -import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; - -export class CrystalTargetLanguage extends TargetLanguage { - protected makeRenderer(renderContext: RenderContext): CrystalRenderer { - return new CrystalRenderer(this, renderContext); - } - - public constructor() { - super("Crystal", ["crystal", "cr", "crystallang"], "cr"); - } - - protected get defaultIndentation(): string { - return " "; - } - - protected getOptions(): Array> { - return []; - } -} - -const keywords = [ - "Any", - "Array", - "Atomic", - "Bool", - "Channel", - "Char", - "Class", - "Enum", - "Enumerable", - "Event", - "Extern", - "Exception", - "File", - "Float", - "Float32", - "Float64", - "GC", - "GZip", - "Hash", - "HTML", - "HTTP", - "Int", - "Int128", - "Int16", - "Int32", - "Int64", - "Int8", - "Iterable", - "Link", - "Logger", - "Math", - "Mutex", - "Nil", - "Number", - "JSON", - "IO", - "Object", - "Pointer", - "Proc", - "Process", - "Range", - "Random", - "Regex", - "Reference", - "Set", - "Signal", - "Slice", - "Spec", - "StaticArray", - "String", - "Struct", - "Symbol", - "System", - "TCPServer", - "TCPSocket", - "Socket", - "Tempfile", - "Termios", - "Time", - "Tuple", - "ThreadLocal", - "UDPSocket", - "UInt128", - "UInt16", - "UInt32", - "UInt64", - "UInt8", - "Union", - "UNIXServer", - "UNIXSocket", - "UUID", - "URI", - "VaList", - "Value", - "Void", - "WeakRef", - "XML", - "YAML", - "Zip", - "Zlib", - "abstract", - "alias", - "as", - "as?", - "asm", - "begin", - "break", - "case", - "class", - "def", - "do", - "else", - "elsif", - "end", - "ensure", - "enum", - "extend", - "false", - "for", - "fun", - "if", - "in", - "include", - "instance_sizeof", - "is_a?", - "lib", - "macro", - "module", - "next", - "nil", - "nil?", - "of", - "out", - "pointerof", - "private", - "protected", - "require", - "rescue", - "return", - "select", - "self", - "sizeof", - "struct", - "super", - "then", - "true", - "type", - "typeof", - "uninitialized", - "union", - "unless", - "until", - "when", - "while", - "with", - "yield" -]; - -function isAsciiLetterOrUnderscoreOrDigit(codePoint: number): boolean { - if (!isAscii(codePoint)) { - return false; - } - - return isLetterOrUnderscoreOrDigit(codePoint); -} - -function isAsciiLetterOrUnderscore(codePoint: number): boolean { - if (!isAscii(codePoint)) { - return false; - } - - return isLetterOrUnderscore(codePoint); -} - -const legalizeName = legalizeCharacters(isAsciiLetterOrUnderscoreOrDigit); - -function crystalStyle(original: string, isSnakeCase: boolean): string { - const words = splitIntoWords(original); - - const wordStyle = isSnakeCase ? allLowerWordStyle : firstUpperWordStyle; - - const combined = combineWords( - words, - legalizeName, - wordStyle, - wordStyle, - wordStyle, - wordStyle, - isSnakeCase ? "_" : "", - isAsciiLetterOrUnderscore - ); - - return combined === "_" ? "_underscore" : combined; -} - -const snakeNamingFunction = funPrefixNamer("default", (original: string) => crystalStyle(original, true)); -const camelNamingFunction = funPrefixNamer("camel", (original: string) => crystalStyle(original, false)); - -function standardUnicodeCrystalEscape(codePoint: number): string { - if (codePoint <= 0xffff) { - return "\\u{" + intToHex(codePoint, 4) + "}"; - } else { - return "\\u{" + intToHex(codePoint, 6) + "}"; - } -} - -const crystalStringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, standardUnicodeCrystalEscape)); +import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../../Annotation"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../../ConvenienceRenderer"; +import { type Name, type Namer } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type Sourcelike, maybeAnnotated } from "../../Source"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { type ClassType, type EnumType, type Type, type UnionType } from "../../Type"; +import { matchType, nullableFromUnion, removeNullFromUnion } from "../../TypeUtils"; + +import { keywords } from "./constants"; +import { camelNamingFunction, crystalStringEscape, snakeNamingFunction } from "./utils"; export class CrystalRenderer extends ConvenienceRenderer { public constructor(targetLanguage: TargetLanguage, renderContext: RenderContext) { @@ -251,7 +31,7 @@ export class CrystalRenderer extends ConvenienceRenderer { return camelNamingFunction; } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace(): readonly string[] { return keywords; } diff --git a/packages/quicktype-core/src/language/Crystal/constants.ts b/packages/quicktype-core/src/language/Crystal/constants.ts new file mode 100644 index 000000000..9f9f99c5b --- /dev/null +++ b/packages/quicktype-core/src/language/Crystal/constants.ts @@ -0,0 +1,138 @@ +export const keywords = [ + "Any", + "Array", + "Atomic", + "Bool", + "Channel", + "Char", + "Class", + "Enum", + "Enumerable", + "Event", + "Extern", + "Exception", + "File", + "Float", + "Float32", + "Float64", + "GC", + "GZip", + "Hash", + "HTML", + "HTTP", + "Int", + "Int128", + "Int16", + "Int32", + "Int64", + "Int8", + "Iterable", + "Link", + "Logger", + "Math", + "Mutex", + "Nil", + "Number", + "JSON", + "IO", + "Object", + "Pointer", + "Proc", + "Process", + "Range", + "Random", + "Regex", + "Reference", + "Set", + "Signal", + "Slice", + "Spec", + "StaticArray", + "String", + "Struct", + "Symbol", + "System", + "TCPServer", + "TCPSocket", + "Socket", + "Tempfile", + "Termios", + "Time", + "Tuple", + "ThreadLocal", + "UDPSocket", + "UInt128", + "UInt16", + "UInt32", + "UInt64", + "UInt8", + "Union", + "UNIXServer", + "UNIXSocket", + "UUID", + "URI", + "VaList", + "Value", + "Void", + "WeakRef", + "XML", + "YAML", + "Zip", + "Zlib", + "abstract", + "alias", + "as", + "as?", + "asm", + "begin", + "break", + "case", + "class", + "def", + "do", + "else", + "elsif", + "end", + "ensure", + "enum", + "extend", + "false", + "for", + "fun", + "if", + "in", + "include", + "instance_sizeof", + "is_a?", + "lib", + "macro", + "module", + "next", + "nil", + "nil?", + "of", + "out", + "pointerof", + "private", + "protected", + "require", + "rescue", + "return", + "select", + "self", + "sizeof", + "struct", + "super", + "then", + "true", + "type", + "typeof", + "uninitialized", + "union", + "unless", + "until", + "when", + "while", + "with", + "yield" +] as const; diff --git a/packages/quicktype-core/src/language/Crystal/index.ts b/packages/quicktype-core/src/language/Crystal/index.ts new file mode 100644 index 000000000..d6b0ce5bc --- /dev/null +++ b/packages/quicktype-core/src/language/Crystal/index.ts @@ -0,0 +1,2 @@ +export { CrystalTargetLanguage } from "./language"; +export { CrystalRenderer } from "./CrystalRenderer"; diff --git a/packages/quicktype-core/src/language/Crystal/language.ts b/packages/quicktype-core/src/language/Crystal/language.ts new file mode 100644 index 000000000..ba8c81c67 --- /dev/null +++ b/packages/quicktype-core/src/language/Crystal/language.ts @@ -0,0 +1,24 @@ +import { type RenderContext } from "../../Renderer"; +import { type Option } from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import { type FixMeOptionsAnyType } from "../../types"; + +import { CrystalRenderer } from "./CrystalRenderer"; + +export class CrystalTargetLanguage extends TargetLanguage { + protected makeRenderer(renderContext: RenderContext): CrystalRenderer { + return new CrystalRenderer(this, renderContext); + } + + public constructor() { + super("Crystal", ["crystal", "cr", "crystallang"], "cr"); + } + + protected get defaultIndentation(): string { + return " "; + } + + protected getOptions(): Array> { + return []; + } +} diff --git a/packages/quicktype-core/src/language/Crystal/utils.ts b/packages/quicktype-core/src/language/Crystal/utils.ts new file mode 100644 index 000000000..a4d95da50 --- /dev/null +++ b/packages/quicktype-core/src/language/Crystal/utils.ts @@ -0,0 +1,65 @@ +import { funPrefixNamer } from "../../Naming"; +import { + allLowerWordStyle, + combineWords, + escapeNonPrintableMapper, + firstUpperWordStyle, + intToHex, + isAscii, + isLetterOrUnderscore, + isLetterOrUnderscoreOrDigit, + isPrintable, + legalizeCharacters, + splitIntoWords, + utf32ConcatMap +} from "../../support/Strings"; + +function isAsciiLetterOrUnderscoreOrDigit(codePoint: number): boolean { + if (!isAscii(codePoint)) { + return false; + } + + return isLetterOrUnderscoreOrDigit(codePoint); +} + +function isAsciiLetterOrUnderscore(codePoint: number): boolean { + if (!isAscii(codePoint)) { + return false; + } + + return isLetterOrUnderscore(codePoint); +} + +const legalizeName = legalizeCharacters(isAsciiLetterOrUnderscoreOrDigit); + +function crystalStyle(original: string, isSnakeCase: boolean): string { + const words = splitIntoWords(original); + + const wordStyle = isSnakeCase ? allLowerWordStyle : firstUpperWordStyle; + + const combined = combineWords( + words, + legalizeName, + wordStyle, + wordStyle, + wordStyle, + wordStyle, + isSnakeCase ? "_" : "", + isAsciiLetterOrUnderscore + ); + + return combined === "_" ? "_underscore" : combined; +} + +export const snakeNamingFunction = funPrefixNamer("default", (original: string) => crystalStyle(original, true)); +export const camelNamingFunction = funPrefixNamer("camel", (original: string) => crystalStyle(original, false)); + +function standardUnicodeCrystalEscape(codePoint: number): string { + if (codePoint <= 0xffff) { + return "\\u{" + intToHex(codePoint, 4) + "}"; + } else { + return "\\u{" + intToHex(codePoint, 6) + "}"; + } +} + +export const crystalStringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, standardUnicodeCrystalEscape)); diff --git a/packages/quicktype-core/src/language/Dart.ts b/packages/quicktype-core/src/language/Dart/DartRenderer.ts similarity index 80% rename from packages/quicktype-core/src/language/Dart.ts rename to packages/quicktype-core/src/language/Dart/DartRenderer.ts index d8d471ec9..75508c7b8 100644 --- a/packages/quicktype-core/src/language/Dart.ts +++ b/packages/quicktype-core/src/language/Dart/DartRenderer.ts @@ -1,218 +1,18 @@ -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { DependencyName, type Name, type Namer, funPrefixNamer } from "../Naming"; -import { type RenderContext } from "../Renderer"; -import { BooleanOption, type Option, type OptionValues, StringOption, getOptionValues } from "../RendererOptions"; -import { type Sourcelike, maybeAnnotated, modifySource } from "../Source"; -import { - allLowerWordStyle, - allUpperWordStyle, - combineWords, - decapitalize, - escapeNonPrintableMapper, - firstUpperWordStyle, - isAscii, - isDigit, - isLetter, - isPrintable, - snakeCase, - splitIntoWords, - standardUnicodeHexEscape, - utf16ConcatMap, - utf16LegalizeCharacters -} from "../support/Strings"; -import { defined } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; -import { - type ClassProperty, - type ClassType, - EnumType, - type PrimitiveStringTypeKind, - type TransformedStringTypeKind, - type Type, - type UnionType -} from "../Type"; -import { type StringTypeMapping } from "../TypeBuilder"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; -import { directlyReachableSingleNamedType, matchType, nullableFromUnion } from "../TypeUtils"; - -export const dartOptions = { - nullSafety: new BooleanOption("null-safety", "Null Safety", true), - justTypes: new BooleanOption("just-types", "Types only", false), - codersInClass: new BooleanOption("coders-in-class", "Put encoder & decoder in Class", false), - methodNamesWithMap: new BooleanOption("from-map", "Use method names fromMap() & toMap()", false, "secondary"), - requiredProperties: new BooleanOption("required-props", "Make all properties required", false), - finalProperties: new BooleanOption("final-props", "Make all properties final", false), - generateCopyWith: new BooleanOption("copy-with", "Generate CopyWith method", false), - useFreezed: new BooleanOption( - "use-freezed", - "Generate class definitions with @freezed compatibility", - false, - "secondary" - ), - useHive: new BooleanOption("use-hive", "Generate annotations for Hive type adapters", false, "secondary"), - useJsonAnnotation: new BooleanOption( - "use-json-annotation", - "Generate annotations for json_serializable", - false, - "secondary" - ), - partName: new StringOption("part-name", "Use this name in `part` directive", "NAME", "", "secondary") -}; - -export class DartTargetLanguage extends TargetLanguage { - public constructor() { - super("Dart", ["dart"], "dart"); - } - - protected getOptions(): Array> { - return [ - dartOptions.nullSafety, - dartOptions.justTypes, - dartOptions.codersInClass, - dartOptions.methodNamesWithMap, - dartOptions.requiredProperties, - dartOptions.finalProperties, - dartOptions.generateCopyWith, - dartOptions.useFreezed, - dartOptions.useHive, - dartOptions.useJsonAnnotation, - dartOptions.partName - ]; - } - - public get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - public get stringTypeMapping(): StringTypeMapping { - const mapping: Map = new Map(); - mapping.set("date", "date"); - mapping.set("date-time", "date-time"); - return mapping; - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): DartRenderer { - const options = getOptionValues(dartOptions, untypedOptionValues); - return new DartRenderer(this, renderContext, options); - } -} - -const keywords = [ - "abstract", - "do", - "import", - "super", - "as", - "dynamic", - "in", - "switch", - "assert", - "else", - "interface", - "sync*", - "async", - "enum", - "is", - "this", - "async*", - "export", - "library", - "throw", - "await", - "external", - "mixin", - "true", - "break", - "extends", - "new", - "try", - "case", - "factory", - "null", - "typedef", - "catch", - "false", - "operator", - "var", - "class", - "final", - "part", - "void", - "const", - "finally", - "rethrow", - "while", - "continue", - "for", - "return", - "with", - "covariant", - "get", - "set", - "yield", - "default", - "if", - "static", - "yield*", - "deferred", - "implements", - "int", - "double", - "bool", - "Map", - "List", - "String", - "File", - "fromJson", - "toJson", - "fromMap", - "toMap" -]; - -const typeNamingFunction = funPrefixNamer("types", n => dartNameStyle(true, false, n)); -const propertyNamingFunction = funPrefixNamer("properties", n => dartNameStyle(false, false, n)); -const enumCaseNamingFunction = funPrefixNamer("enum-cases", n => dartNameStyle(true, true, n)); - -// Escape the dollar sign, which is used in string interpolation -const stringEscape = utf16ConcatMap( - escapeNonPrintableMapper(cp => isPrintable(cp) && cp !== 0x24, standardUnicodeHexEscape) -); - -function isStartCharacter(codePoint: number): boolean { - if (codePoint === 0x5f) return false; // underscore - return isAscii(codePoint) && isLetter(codePoint); -} - -function isPartCharacter(codePoint: number): boolean { - return isStartCharacter(codePoint) || (isAscii(codePoint) && isDigit(codePoint)); -} - -const legalizeName = utf16LegalizeCharacters(isPartCharacter); - -// FIXME: Handle acronyms consistently. In particular, that means that -// we have to use namers to produce the getter and setter names - we can't -// just capitalize and concatenate. -// https://stackoverflow.com/questions/8277355/naming-convention-for-upper-case-abbreviations -function dartNameStyle(startWithUpper: boolean, upperUnderscore: boolean, original: string): string { - const words = splitIntoWords(original); - const firstWordStyle = upperUnderscore - ? allUpperWordStyle - : startWithUpper - ? firstUpperWordStyle - : allLowerWordStyle; - const restWordStyle = upperUnderscore ? allUpperWordStyle : firstUpperWordStyle; - return combineWords( - words, - legalizeName, - firstWordStyle, - restWordStyle, - firstWordStyle, - restWordStyle, - upperUnderscore ? "_" : "", - isStartCharacter - ); -} +import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../../Annotation"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../../ConvenienceRenderer"; +import { DependencyName, type Name, type Namer } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type Sourcelike, maybeAnnotated, modifySource } from "../../Source"; +import { decapitalize, snakeCase } from "../../support/Strings"; +import { defined } from "../../support/Support"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { type ClassProperty, type ClassType, EnumType, type Type, type UnionType } from "../../Type"; +import { directlyReachableSingleNamedType, matchType, nullableFromUnion } from "../../TypeUtils"; + +import { keywords } from "./constants"; +import { type dartOptions } from "./language"; +import { enumCaseNamingFunction, propertyNamingFunction, stringEscape, typeNamingFunction } from "./utils"; interface TopLevelDependents { decoder: Name; @@ -240,7 +40,7 @@ export class DartRenderer extends ConvenienceRenderer { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace(): readonly string[] { return keywords; } @@ -879,15 +679,15 @@ export class DartRenderer extends ConvenienceRenderer { protected emitEnumValues(): void { this.ensureBlankLine(); this.emitMultiline(`class EnumValues { - Map map; - late Map reverseMap; + Map map; + late Map reverseMap; - EnumValues(this.map); + EnumValues(this.map); - Map get reverse { - reverseMap = map.map((k, v) => MapEntry(v, k)); - return reverseMap; - } + Map get reverse { + reverseMap = map.map((k, v) => MapEntry(v, k)); + return reverseMap; + } }`); } diff --git a/packages/quicktype-core/src/language/Dart/constants.ts b/packages/quicktype-core/src/language/Dart/constants.ts new file mode 100644 index 000000000..1251a6d8e --- /dev/null +++ b/packages/quicktype-core/src/language/Dart/constants.ts @@ -0,0 +1,71 @@ +export const keywords = [ + "abstract", + "do", + "import", + "super", + "as", + "dynamic", + "in", + "switch", + "assert", + "else", + "interface", + "sync*", + "async", + "enum", + "is", + "this", + "async*", + "export", + "library", + "throw", + "await", + "external", + "mixin", + "true", + "break", + "extends", + "new", + "try", + "case", + "factory", + "null", + "typedef", + "catch", + "false", + "operator", + "var", + "class", + "final", + "part", + "void", + "const", + "finally", + "rethrow", + "while", + "continue", + "for", + "return", + "with", + "covariant", + "get", + "set", + "yield", + "default", + "if", + "static", + "yield*", + "deferred", + "implements", + "int", + "double", + "bool", + "Map", + "List", + "String", + "File", + "fromJson", + "toJson", + "fromMap", + "toMap" +] as const; diff --git a/packages/quicktype-core/src/language/Dart/index.ts b/packages/quicktype-core/src/language/Dart/index.ts new file mode 100644 index 000000000..3820d5ad9 --- /dev/null +++ b/packages/quicktype-core/src/language/Dart/index.ts @@ -0,0 +1,2 @@ +export { DartTargetLanguage, dartOptions } from "./language"; +export { DartRenderer } from "./DartRenderer"; diff --git a/packages/quicktype-core/src/language/Dart/language.ts b/packages/quicktype-core/src/language/Dart/language.ts new file mode 100644 index 000000000..4598079f9 --- /dev/null +++ b/packages/quicktype-core/src/language/Dart/language.ts @@ -0,0 +1,70 @@ +import { type RenderContext } from "../../Renderer"; +import { BooleanOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import { type PrimitiveStringTypeKind, type TransformedStringTypeKind } from "../../Type"; +import { type StringTypeMapping } from "../../TypeBuilder"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; + +import { DartRenderer } from "./DartRenderer"; + +export const dartOptions = { + nullSafety: new BooleanOption("null-safety", "Null Safety", true), + justTypes: new BooleanOption("just-types", "Types only", false), + codersInClass: new BooleanOption("coders-in-class", "Put encoder & decoder in Class", false), + methodNamesWithMap: new BooleanOption("from-map", "Use method names fromMap() & toMap()", false, "secondary"), + requiredProperties: new BooleanOption("required-props", "Make all properties required", false), + finalProperties: new BooleanOption("final-props", "Make all properties final", false), + generateCopyWith: new BooleanOption("copy-with", "Generate CopyWith method", false), + useFreezed: new BooleanOption( + "use-freezed", + "Generate class definitions with @freezed compatibility", + false, + "secondary" + ), + useHive: new BooleanOption("use-hive", "Generate annotations for Hive type adapters", false, "secondary"), + useJsonAnnotation: new BooleanOption( + "use-json-annotation", + "Generate annotations for json_serializable", + false, + "secondary" + ), + partName: new StringOption("part-name", "Use this name in `part` directive", "NAME", "", "secondary") +}; + +export class DartTargetLanguage extends TargetLanguage { + public constructor() { + super("Dart", ["dart"], "dart"); + } + + protected getOptions(): Array> { + return [ + dartOptions.nullSafety, + dartOptions.justTypes, + dartOptions.codersInClass, + dartOptions.methodNamesWithMap, + dartOptions.requiredProperties, + dartOptions.finalProperties, + dartOptions.generateCopyWith, + dartOptions.useFreezed, + dartOptions.useHive, + dartOptions.useJsonAnnotation, + dartOptions.partName + ]; + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + public get stringTypeMapping(): StringTypeMapping { + const mapping: Map = new Map(); + mapping.set("date", "date"); + mapping.set("date-time", "date-time"); + return mapping; + } + + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): DartRenderer { + const options = getOptionValues(dartOptions, untypedOptionValues); + return new DartRenderer(this, renderContext, options); + } +} diff --git a/packages/quicktype-core/src/language/Dart/utils.ts b/packages/quicktype-core/src/language/Dart/utils.ts new file mode 100644 index 000000000..2fb4a783d --- /dev/null +++ b/packages/quicktype-core/src/language/Dart/utils.ts @@ -0,0 +1,60 @@ +import { funPrefixNamer } from "../../Naming"; +import { + allLowerWordStyle, + allUpperWordStyle, + combineWords, + escapeNonPrintableMapper, + firstUpperWordStyle, + isAscii, + isDigit, + isLetter, + isPrintable, + splitIntoWords, + standardUnicodeHexEscape, + utf16ConcatMap, + utf16LegalizeCharacters +} from "../../support/Strings"; + +export const typeNamingFunction = funPrefixNamer("types", n => dartNameStyle(true, false, n)); +export const propertyNamingFunction = funPrefixNamer("properties", n => dartNameStyle(false, false, n)); +export const enumCaseNamingFunction = funPrefixNamer("enum-cases", n => dartNameStyle(true, true, n)); + +// Escape the dollar sign, which is used in string interpolation +export const stringEscape = utf16ConcatMap( + escapeNonPrintableMapper(cp => isPrintable(cp) && cp !== 0x24, standardUnicodeHexEscape) +); + +function isStartCharacter(codePoint: number): boolean { + if (codePoint === 0x5f) return false; // underscore + return isAscii(codePoint) && isLetter(codePoint); +} + +function isPartCharacter(codePoint: number): boolean { + return isStartCharacter(codePoint) || (isAscii(codePoint) && isDigit(codePoint)); +} + +const legalizeName = utf16LegalizeCharacters(isPartCharacter); + +// FIXME: Handle acronyms consistently. In particular, that means that +// we have to use namers to produce the getter and setter names - we can't +// just capitalize and concatenate. +// https://stackoverflow.com/questions/8277355/naming-convention-for-upper-case-abbreviations +export function dartNameStyle(startWithUpper: boolean, upperUnderscore: boolean, original: string): string { + const words = splitIntoWords(original); + const firstWordStyle = upperUnderscore + ? allUpperWordStyle + : startWithUpper + ? firstUpperWordStyle + : allLowerWordStyle; + const restWordStyle = upperUnderscore ? allUpperWordStyle : firstUpperWordStyle; + return combineWords( + words, + legalizeName, + firstWordStyle, + restWordStyle, + firstWordStyle, + restWordStyle, + upperUnderscore ? "_" : "", + isStartCharacter + ); +} diff --git a/packages/quicktype-core/src/language/Elixir.ts b/packages/quicktype-core/src/language/Elixir/ElixirRenderer.ts similarity index 85% rename from packages/quicktype-core/src/language/Elixir.ts rename to packages/quicktype-core/src/language/Elixir/ElixirRenderer.ts index 3762dae7e..3665836a5 100644 --- a/packages/quicktype-core/src/language/Elixir.ts +++ b/packages/quicktype-core/src/language/Elixir/ElixirRenderer.ts @@ -1,214 +1,22 @@ -import * as unicode from "unicode-properties"; - -import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { type Name, Namer } from "../Naming"; -import { type RenderContext } from "../Renderer"; -import { BooleanOption, type Option, type OptionValues, StringOption, getOptionValues } from "../RendererOptions"; -import { type Sourcelike } from "../Source"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../../ConvenienceRenderer"; +import { type Name, Namer } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type Sourcelike } from "../../Source"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { ArrayType, ClassType, EnumType, MapType, PrimitiveType, type Type, UnionType } from "../../Type"; +import { matchType, nullableFromUnion } from "../../TypeUtils"; + +import { forbiddenModuleNames, reservedWords } from "./constants"; +import { type elixirOptions } from "./language"; import { - allLowerWordStyle, - allUpperWordStyle, - combineWords, - escapeNonPrintableMapper, - firstUpperWordStyle, - intToHex, - isLetterOrUnderscore, - isPrintable, - legalizeCharacters, - splitIntoWords, - utf32ConcatMap -} from "../support/Strings"; -import { TargetLanguage } from "../TargetLanguage"; -import { ArrayType, ClassType, EnumType, MapType, PrimitiveType, type Type, UnionType } from "../Type"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; -import { matchType, nullableFromUnion } from "../TypeUtils"; - -const forbiddenModuleNames = [ - "Access", - "Agent", - "Any", - "Application", - "ArgumentError", - "ArithmeticError", - "Atom", - "BadArityError", - "BadBooleanError", - "BadFunctionError", - "BadMapError", - "BadStructError", - "Base", - "Behaviour", - "Bitwise", - "Calendar", - "CaseClauseError", - "Code", - "Collectable", - "CondClauseError", - "Config", - "Date", - "DateTime", - "Dict", - "DynamicSupervisor", - "Enum", - "ErlangError", - "Exception", - "File", - "Float", - "Function", - "FunctionClauseError", - "GenEvent", - "GenServer", - "HashDict", - "HashSet", - "IO", - "Inspect", - "Integer", - "Kernel", - "KeyError", - "Keyword", - "List", - "Macro", - "Map", - "MapSet", - "MatchError", - "Module", - "Node", - "OptionParser", - "Path", - "Port", - "Process", - "Protocol", - "Range", - "Record", - "Regex", - "Registry", - "RuntimeError", - "Set", - "Stream", - "String", - "StringIO", - "Supervisor", - "SyntaxError", - "System", - "SystemLimitError", - "Task", - "Time", - "TokenMissingError", - "Tuple", - "URI", - "UndefinedFunctionError", - "UnicodeConversionError", - "Version", - "WithClauseError" -]; -const reservedWords = [ - "def", - "defmodule", - "use", - "import", - "alias", - "true", - "false", - "nil", - "when", - "and", - "or", - "not", - "in", - "fn", - "do", - "end", - "catch", - "rescue", - "after", - "else" -]; - -function unicodeEscape(codePoint: number): string { - return `\\u{${intToHex(codePoint, 0)}}`; -} - -function capitalizeFirstLetter(str: string): string { - return str.charAt(0).toUpperCase() + str.slice(1); -} - -const stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, unicodeEscape)); - -function escapeDoubleQuotes(str: string): string { - return str.replace(/"/g, '\\"'); -} - -function escapeNewLines(str: string): string { - return str.replace(/\n/g, "\\n"); -} - -export const elixirOptions = { - justTypes: new BooleanOption("just-types", "Plain types only", false), - namespace: new StringOption("namespace", "Specify a module namespace", "NAME", "") -}; - -export class ElixirTargetLanguage extends TargetLanguage { - public constructor() { - super("Elixir", ["elixir"], "ex"); - } - - protected getOptions(): Array> { - return [elixirOptions.justTypes, elixirOptions.namespace]; - } - - public get supportsOptionalClassProperties(): boolean { - return true; - } - - protected get defaultIndentation(): string { - return " "; - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): ElixirRenderer { - return new ElixirRenderer(this, renderContext, getOptionValues(elixirOptions, untypedOptionValues)); - } -} - -const isStartCharacter = isLetterOrUnderscore; - -function isPartCharacter(utf16Unit: number): boolean { - const category: string = unicode.getCategory(utf16Unit); - return ["Nd", "Pc", "Mn", "Mc"].includes(category) || isStartCharacter(utf16Unit); -} - -const legalizeName = legalizeCharacters(isPartCharacter); - -function simpleNameStyle(original: string, uppercase: boolean): string { - if (/^[0-9]+$/.test(original)) { - original = `${original}N`; - } - - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - uppercase ? firstUpperWordStyle : allLowerWordStyle, - uppercase ? firstUpperWordStyle : allLowerWordStyle, - allUpperWordStyle, - allUpperWordStyle, - "", - isStartCharacter - ); -} - -function memberNameStyle(original: string): string { - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - allLowerWordStyle, - allLowerWordStyle, - allLowerWordStyle, - allLowerWordStyle, - "_", - isStartCharacter - ); -} + capitalizeFirstLetter, + escapeDoubleQuotes, + escapeNewLines, + memberNameStyle, + simpleNameStyle, + stringEscape +} from "./utils"; export class ElixirRenderer extends ConvenienceRenderer { public constructor( @@ -236,7 +44,7 @@ export class ElixirRenderer extends ConvenienceRenderer { } protected forbiddenForObjectProperties(_c: ClassType, _classNamed: Name): ForbiddenWordsInfo { - return { names: reservedWords, includeGlobalForbidden: true }; + return { names: reservedWords as unknown as string[], includeGlobalForbidden: true }; } protected makeNamedTypeNamer(): Namer { @@ -890,8 +698,8 @@ export class ElixirRenderer extends ConvenienceRenderer { this.ensureBlankLine(); this.emitBlock("def from_json(json) do", () => { this.emitMultiline(`json - |> Jason.decode!() - |> from_map()`); + |> Jason.decode!() + |> from_map()`); }); this.ensureBlankLine(); this.emitBlock([`def to_map(${isEmpty ? "_" : ""}struct) do`], () => { @@ -907,8 +715,8 @@ export class ElixirRenderer extends ConvenienceRenderer { this.ensureBlankLine(); this.emitBlock("def to_json(struct) do", () => { this.emitMultiline(`struct - |> to_map() - |> Jason.encode!()`); + |> to_map() + |> Jason.encode!()`); }); }); } @@ -963,40 +771,40 @@ export class ElixirRenderer extends ConvenienceRenderer { this.emitMultiline(`def valid_atom?(value), do: value in @valid_enum_members def valid_atom_string?(value) do - try do - atom = String.to_existing_atom(value) - atom in @valid_enum_members - rescue - ArgumentError -> false - end + try do + atom = String.to_existing_atom(value) + atom in @valid_enum_members + rescue + ArgumentError -> false + end end def encode(value) do - if valid_atom?(value) do - Atom.to_string(value) - else - {:error, "Unexpected value when encoding atom: #{inspect(value)}"} - end + if valid_atom?(value) do + Atom.to_string(value) + else + {:error, "Unexpected value when encoding atom: #{inspect(value)}"} + end end def decode(value) do - if valid_atom_string?(value) do - String.to_existing_atom(value) - else - {:error, "Unexpected value when decoding atom: #{inspect(value)}"} - end + if valid_atom_string?(value) do + String.to_existing_atom(value) + else + {:error, "Unexpected value when decoding atom: #{inspect(value)}"} + end end def from_json(json) do - json - |> Jason.decode!() - |> decode() + json + |> Jason.decode!() + |> decode() end def to_json(data) do - data - |> encode() - |> Jason.encode!() + data + |> encode() + |> Jason.encode!() end`); }); } diff --git a/packages/quicktype-core/src/language/Elixir/constants.ts b/packages/quicktype-core/src/language/Elixir/constants.ts new file mode 100644 index 000000000..89866c9f5 --- /dev/null +++ b/packages/quicktype-core/src/language/Elixir/constants.ts @@ -0,0 +1,101 @@ +export const forbiddenModuleNames = [ + "Access", + "Agent", + "Any", + "Application", + "ArgumentError", + "ArithmeticError", + "Atom", + "BadArityError", + "BadBooleanError", + "BadFunctionError", + "BadMapError", + "BadStructError", + "Base", + "Behaviour", + "Bitwise", + "Calendar", + "CaseClauseError", + "Code", + "Collectable", + "CondClauseError", + "Config", + "Date", + "DateTime", + "Dict", + "DynamicSupervisor", + "Enum", + "ErlangError", + "Exception", + "File", + "Float", + "Function", + "FunctionClauseError", + "GenEvent", + "GenServer", + "HashDict", + "HashSet", + "IO", + "Inspect", + "Integer", + "Kernel", + "KeyError", + "Keyword", + "List", + "Macro", + "Map", + "MapSet", + "MatchError", + "Module", + "Node", + "OptionParser", + "Path", + "Port", + "Process", + "Protocol", + "Range", + "Record", + "Regex", + "Registry", + "RuntimeError", + "Set", + "Stream", + "String", + "StringIO", + "Supervisor", + "SyntaxError", + "System", + "SystemLimitError", + "Task", + "Time", + "TokenMissingError", + "Tuple", + "URI", + "UndefinedFunctionError", + "UnicodeConversionError", + "Version", + "WithClauseError" +] as const; + +export const reservedWords = [ + "def", + "defmodule", + "use", + "import", + "alias", + "true", + "false", + "nil", + "when", + "and", + "or", + "not", + "in", + "fn", + "do", + "end", + "catch", + "rescue", + "after", + "else" +] as const; diff --git a/packages/quicktype-core/src/language/Elixir/index.ts b/packages/quicktype-core/src/language/Elixir/index.ts new file mode 100644 index 000000000..59a6f6eb3 --- /dev/null +++ b/packages/quicktype-core/src/language/Elixir/index.ts @@ -0,0 +1,2 @@ +export { ElixirTargetLanguage, elixirOptions } from "./language"; +export { ElixirRenderer } from "./ElixirRenderer"; diff --git a/packages/quicktype-core/src/language/Elixir/language.ts b/packages/quicktype-core/src/language/Elixir/language.ts new file mode 100644 index 000000000..fceaa7063 --- /dev/null +++ b/packages/quicktype-core/src/language/Elixir/language.ts @@ -0,0 +1,33 @@ +import { type RenderContext } from "../../Renderer"; +import { BooleanOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; + +import { ElixirRenderer } from "./ElixirRenderer"; + +export const elixirOptions = { + justTypes: new BooleanOption("just-types", "Plain types only", false), + namespace: new StringOption("namespace", "Specify a module namespace", "NAME", "") +}; + +export class ElixirTargetLanguage extends TargetLanguage { + public constructor() { + super("Elixir", ["elixir"], "ex"); + } + + protected getOptions(): Array> { + return [elixirOptions.justTypes, elixirOptions.namespace]; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + protected get defaultIndentation(): string { + return " "; + } + + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): ElixirRenderer { + return new ElixirRenderer(this, renderContext, getOptionValues(elixirOptions, untypedOptionValues)); + } +} diff --git a/packages/quicktype-core/src/language/Elixir/utils.ts b/packages/quicktype-core/src/language/Elixir/utils.ts new file mode 100644 index 000000000..4e81841fe --- /dev/null +++ b/packages/quicktype-core/src/language/Elixir/utils.ts @@ -0,0 +1,74 @@ +import unicode from "unicode-properties"; + +import { + allLowerWordStyle, + allUpperWordStyle, + combineWords, + escapeNonPrintableMapper, + firstUpperWordStyle, + intToHex, + isLetterOrUnderscore, + isPrintable, + legalizeCharacters, + splitIntoWords, + utf32ConcatMap +} from "../../support/Strings"; + +function unicodeEscape(codePoint: number): string { + return `\\u{${intToHex(codePoint, 0)}}`; +} + +export function capitalizeFirstLetter(str: string): string { + return str.charAt(0).toUpperCase() + str.slice(1); +} + +export const stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, unicodeEscape)); + +export function escapeDoubleQuotes(str: string): string { + return str.replace(/"/g, '\\"'); +} + +export function escapeNewLines(str: string): string { + return str.replace(/\n/g, "\\n"); +} + +const isStartCharacter = isLetterOrUnderscore; + +function isPartCharacter(utf16Unit: number): boolean { + const category: string = unicode.getCategory(utf16Unit); + return ["Nd", "Pc", "Mn", "Mc"].includes(category) || isStartCharacter(utf16Unit); +} + +const legalizeName = legalizeCharacters(isPartCharacter); + +export function simpleNameStyle(original: string, uppercase: boolean): string { + if (/^[0-9]+$/.test(original)) { + original = `${original}N`; + } + + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + uppercase ? firstUpperWordStyle : allLowerWordStyle, + uppercase ? firstUpperWordStyle : allLowerWordStyle, + allUpperWordStyle, + allUpperWordStyle, + "", + isStartCharacter + ); +} + +export function memberNameStyle(original: string): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + allLowerWordStyle, + allLowerWordStyle, + allLowerWordStyle, + allLowerWordStyle, + "_", + isStartCharacter + ); +} diff --git a/packages/quicktype-core/src/language/Elm.ts b/packages/quicktype-core/src/language/Elm/ElmRenderer.ts similarity index 84% rename from packages/quicktype-core/src/language/Elm.ts rename to packages/quicktype-core/src/language/Elm/ElmRenderer.ts index ced7837b4..8ae5a9d70 100644 --- a/packages/quicktype-core/src/language/Elm.ts +++ b/packages/quicktype-core/src/language/Elm/ElmRenderer.ts @@ -1,150 +1,20 @@ import { arrayIntercalate, mapContains } from "collection-utils"; -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { DependencyName, type Name, type Namer, funPrefixNamer } from "../Naming"; -import { type RenderContext } from "../Renderer"; -import { - BooleanOption, - EnumOption, - type Option, - type OptionValues, - StringOption, - getOptionValues -} from "../RendererOptions"; -import { type MultiWord, type Sourcelike, annotated, multiWord, parenIfNeeded, singleWord } from "../Source"; -import { - allLowerWordStyle, - allUpperWordStyle, - combineWords, - decapitalize, - firstUpperWordStyle, - isAscii, - isLetterOrUnderscore, - isLetterOrUnderscoreOrDigit, - legalizeCharacters, - splitIntoWords, - stringEscape -} from "../support/Strings"; -import { defined } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; -import { type ClassProperty, type ClassType, type EnumType, type Type, UnionType } from "../Type"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; -import { matchType, nullableFromUnion } from "../TypeUtils"; - -export const elmOptions = { - justTypes: new BooleanOption("just-types", "Plain types only", false), - useList: new EnumOption("array-type", "Use Array or List", [ - ["array", false], - ["list", true] - ]), - // FIXME: Do this via a configurable named eventually. - moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType") -}; - -export class ElmTargetLanguage extends TargetLanguage { - public constructor() { - super("Elm", ["elm"], "elm"); - } - - protected getOptions(): Array> { - return [elmOptions.justTypes, elmOptions.moduleName, elmOptions.useList]; - } - - public get supportsOptionalClassProperties(): boolean { - return true; - } - - public get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): ElmRenderer { - return new ElmRenderer(this, renderContext, getOptionValues(elmOptions, untypedOptionValues)); - } -} - -const forbiddenNames = [ - "if", - "then", - "else", - "case", - "of", - "let", - "in", - "infix", - "type", - "module", - "where", - "import", - "exposing", - "as", - "port", - "int", - "float", - "bool", - "string", - "Jenc", - "Jdec", - "Jpipe", - "always", - "identity", - "Array", - "List", - "Dict", - "Maybe", - "map", - "toList", - "makeArrayEncoder", - "makeDictEncoder", - "makeNullableEncoder", - "Int", - "True", - "False", - "String", - "Float" -]; - -const legalizeName = legalizeCharacters(cp => isAscii(cp) && isLetterOrUnderscoreOrDigit(cp)); - -function elmNameStyle(original: string, upper: boolean): string { - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - upper ? firstUpperWordStyle : allLowerWordStyle, - firstUpperWordStyle, - upper ? allUpperWordStyle : allLowerWordStyle, - allUpperWordStyle, - "", - isLetterOrUnderscore - ); -} - -const upperNamingFunction = funPrefixNamer("upper", n => elmNameStyle(n, true)); -const lowerNamingFunction = funPrefixNamer("lower", n => elmNameStyle(n, false)); - -interface RequiredOrOptional { - fallback: string; - reqOrOpt: string; -} - -function requiredOrOptional(p: ClassProperty): RequiredOrOptional { - function optional(fallback: string): RequiredOrOptional { - return { reqOrOpt: "Jpipe.optional", fallback }; - } - - const t = p.type; - if (p.isOptional || (t instanceof UnionType && nullableFromUnion(t) !== null)) { - return optional(" Nothing"); - } - - if (t.kind === "null") { - return optional(" ()"); - } - - return { reqOrOpt: "Jpipe.required", fallback: "" }; -} +import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../../Annotation"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../../ConvenienceRenderer"; +import { DependencyName, type Name, type Namer } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type MultiWord, type Sourcelike, annotated, multiWord, parenIfNeeded, singleWord } from "../../Source"; +import { decapitalize, stringEscape } from "../../support/Strings"; +import { defined } from "../../support/Support"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { type ClassProperty, type ClassType, type EnumType, type Type, type UnionType } from "../../Type"; +import { matchType, nullableFromUnion } from "../../TypeUtils"; + +import { forbiddenNames } from "./constants"; +import { type elmOptions } from "./language"; +import { lowerNamingFunction, requiredOrOptional, upperNamingFunction } from "./utils"; interface TopLevelDependent { decoder?: Name; @@ -169,7 +39,7 @@ export class ElmRenderer extends ConvenienceRenderer { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace(): readonly string[] { return forbiddenNames; } @@ -690,12 +560,12 @@ import Dict exposing (Dict, map, toList)`); this.ensureBlankLine(); this.emitMultiline(`makeDictEncoder : (a -> Jenc.Value) -> Dict String a -> Jenc.Value makeDictEncoder f dict = - Jenc.object (toList (Dict.map (\\k -> f) dict)) + Jenc.object (toList (Dict.map (\\k -> f) dict)) makeNullableEncoder : (a -> Jenc.Value) -> Maybe a -> Jenc.Value makeNullableEncoder f m = - case m of - Just x -> f x - Nothing -> Jenc.null`); + case m of + Just x -> f x + Nothing -> Jenc.null`); } } diff --git a/packages/quicktype-core/src/language/Elm/constants.ts b/packages/quicktype-core/src/language/Elm/constants.ts new file mode 100644 index 000000000..e7a331f86 --- /dev/null +++ b/packages/quicktype-core/src/language/Elm/constants.ts @@ -0,0 +1,40 @@ +export const forbiddenNames = [ + "if", + "then", + "else", + "case", + "of", + "let", + "in", + "infix", + "type", + "module", + "where", + "import", + "exposing", + "as", + "port", + "int", + "float", + "bool", + "string", + "Jenc", + "Jdec", + "Jpipe", + "always", + "identity", + "Array", + "List", + "Dict", + "Maybe", + "map", + "toList", + "makeArrayEncoder", + "makeDictEncoder", + "makeNullableEncoder", + "Int", + "True", + "False", + "String", + "Float" +] as const; diff --git a/packages/quicktype-core/src/language/Elm/index.ts b/packages/quicktype-core/src/language/Elm/index.ts new file mode 100644 index 000000000..9dcf263d0 --- /dev/null +++ b/packages/quicktype-core/src/language/Elm/index.ts @@ -0,0 +1,2 @@ +export { ElmTargetLanguage, elmOptions } from "./language"; +export { ElmRenderer } from "./ElmRenderer"; diff --git a/packages/quicktype-core/src/language/Elm/language.ts b/packages/quicktype-core/src/language/Elm/language.ts new file mode 100644 index 000000000..6a193fbae --- /dev/null +++ b/packages/quicktype-core/src/language/Elm/language.ts @@ -0,0 +1,38 @@ +import { type RenderContext } from "../../Renderer"; +import { BooleanOption, EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; + +import { ElmRenderer } from "./ElmRenderer"; + +export const elmOptions = { + justTypes: new BooleanOption("just-types", "Plain types only", false), + useList: new EnumOption("array-type", "Use Array or List", [ + ["array", false], + ["list", true] + ]), + // FIXME: Do this via a configurable named eventually. + moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType") +}; + +export class ElmTargetLanguage extends TargetLanguage { + public constructor() { + super("Elm", ["elm"], "elm"); + } + + protected getOptions(): Array> { + return [elmOptions.justTypes, elmOptions.moduleName, elmOptions.useList]; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): ElmRenderer { + return new ElmRenderer(this, renderContext, getOptionValues(elmOptions, untypedOptionValues)); + } +} diff --git a/packages/quicktype-core/src/language/Elm/utils.ts b/packages/quicktype-core/src/language/Elm/utils.ts new file mode 100644 index 000000000..2b09265cf --- /dev/null +++ b/packages/quicktype-core/src/language/Elm/utils.ts @@ -0,0 +1,55 @@ +import { funPrefixNamer } from "../../Naming"; +import { + allLowerWordStyle, + allUpperWordStyle, + combineWords, + firstUpperWordStyle, + isAscii, + isLetterOrUnderscore, + isLetterOrUnderscoreOrDigit, + legalizeCharacters, + splitIntoWords +} from "../../support/Strings"; +import { type ClassProperty, UnionType } from "../../Type"; +import { nullableFromUnion } from "../../TypeUtils"; + +const legalizeName = legalizeCharacters(cp => isAscii(cp) && isLetterOrUnderscoreOrDigit(cp)); + +function elmNameStyle(original: string, upper: boolean): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + upper ? firstUpperWordStyle : allLowerWordStyle, + firstUpperWordStyle, + upper ? allUpperWordStyle : allLowerWordStyle, + allUpperWordStyle, + "", + isLetterOrUnderscore + ); +} + +export const upperNamingFunction = funPrefixNamer("upper", n => elmNameStyle(n, true)); +export const lowerNamingFunction = funPrefixNamer("lower", n => elmNameStyle(n, false)); + +interface RequiredOrOptional { + fallback: string; + reqOrOpt: string; +} + +export function requiredOrOptional(p: ClassProperty): RequiredOrOptional { + function optional(fallback: string): RequiredOrOptional { + return { reqOrOpt: "Jpipe.optional", fallback }; + } + + const t = p.type; + if (p.isOptional || (t instanceof UnionType && nullableFromUnion(t) !== null)) { + return optional(" Nothing"); + } + + if (t.kind === "null") { + return optional(" ()"); + } + + return { reqOrOpt: "Jpipe.required", fallback: "" }; +} diff --git a/packages/quicktype-core/src/language/Golang.ts b/packages/quicktype-core/src/language/Golang/GolangRenderer.ts similarity index 73% rename from packages/quicktype-core/src/language/Golang.ts rename to packages/quicktype-core/src/language/Golang/GolangRenderer.ts index 9a2081af6..708666452 100644 --- a/packages/quicktype-core/src/language/Golang.ts +++ b/packages/quicktype-core/src/language/Golang/GolangRenderer.ts @@ -1,111 +1,17 @@ -import { type PrimitiveStringTypeKind, type StringTypeMapping, type TransformedStringTypeKind } from ".."; -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { DependencyName, type Name, type Namer, funPrefixNamer } from "../Naming"; -import { type RenderContext } from "../Renderer"; -import { BooleanOption, type Option, type OptionValues, StringOption, getOptionValues } from "../RendererOptions"; -import { type Sourcelike, maybeAnnotated, modifySource } from "../Source"; -import { - allUpperWordStyle, - camelCase, - combineWords, - firstUpperWordStyle, - isLetterOrUnderscore, - isLetterOrUnderscoreOrDigit, - legalizeCharacters, - splitIntoWords, - stringEscape -} from "../support/Strings"; -import { assert, defined } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; -import { type ClassProperty, type ClassType, type EnumType, type Type, type TypeKind, UnionType } from "../Type"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; -import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; - -export const goOptions = { - justTypes: new BooleanOption("just-types", "Plain types only", false), - justTypesAndPackage: new BooleanOption("just-types-and-package", "Plain types with package only", false), - packageName: new StringOption("package", "Generated package name", "NAME", "main"), - multiFileOutput: new BooleanOption("multi-file-output", "Renders each top-level object in its own Go file", false), - fieldTags: new StringOption("field-tags", "list of tags which should be generated for fields", "TAGS", "json"), - omitEmpty: new BooleanOption( - "omit-empty", - 'If set, all non-required objects will be tagged with ",omitempty"', - false - ) -}; - -export class GoTargetLanguage extends TargetLanguage { - public constructor() { - super("Go", ["go", "golang"], "go"); - } - - protected getOptions(): Array> { - return [ - goOptions.justTypes, - goOptions.justTypesAndPackage, - goOptions.packageName, - goOptions.multiFileOutput, - goOptions.fieldTags, - goOptions.omitEmpty - ]; - } - - public get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - public get stringTypeMapping(): StringTypeMapping { - const mapping: Map = new Map(); - mapping.set("date-time", "date-time"); - return mapping; - } - - public get supportsOptionalClassProperties(): boolean { - return true; - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): GoRenderer { - return new GoRenderer(this, renderContext, getOptionValues(goOptions, untypedOptionValues)); - } - - protected get defaultIndentation(): string { - return "\t"; - } -} - -const namingFunction = funPrefixNamer("namer", goNameStyle); - -const legalizeName = legalizeCharacters(isLetterOrUnderscoreOrDigit); - -function goNameStyle(original: string): string { - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - firstUpperWordStyle, - firstUpperWordStyle, - allUpperWordStyle, - allUpperWordStyle, - "", - isLetterOrUnderscore - ); -} - -const primitiveValueTypeKinds: TypeKind[] = ["integer", "double", "bool", "string"]; -const compoundTypeKinds: TypeKind[] = ["array", "class", "map", "enum"]; - -function isValueType(t: Type): boolean { - const kind = t.kind; - return primitiveValueTypeKinds.includes(kind) || kind === "class" || kind === "enum" || kind === "date-time"; -} - -function canOmitEmpty(cp: ClassProperty, omitEmptyOption: boolean): boolean { - if (!cp.isOptional) return false; - if (omitEmptyOption) return true; - const t = cp.type; - return !["union", "null", "any"].includes(t.kind); -} +import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../../Annotation"; +import { ConvenienceRenderer } from "../../ConvenienceRenderer"; +import { DependencyName, type Name, type Namer } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type Sourcelike, maybeAnnotated, modifySource } from "../../Source"; +import { camelCase, stringEscape } from "../../support/Strings"; +import { assert, defined } from "../../support/Support"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { type ClassProperty, type ClassType, type EnumType, type Type, type TypeKind, UnionType } from "../../Type"; +import { matchType, nullableFromUnion, removeNullFromUnion } from "../../TypeUtils"; + +import { type goOptions } from "./language"; +import { canOmitEmpty, compoundTypeKinds, isValueType, namingFunction, primitiveValueTypeKinds } from "./utils"; export class GoRenderer extends ConvenienceRenderer { private readonly _topLevelUnmarshalNames = new Map(); @@ -495,117 +401,117 @@ export class GoRenderer extends ConvenienceRenderer { this.ensureBlankLine(); this .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) { - if pi != nil { - *pi = nil - } - if pf != nil { - *pf = nil - } - if pb != nil { - *pb = nil - } - if ps != nil { - *ps = nil - } - - dec := json.NewDecoder(bytes.NewReader(data)) - dec.UseNumber() - tok, err := dec.Token() - if err != nil { - return false, err - } - - switch v := tok.(type) { - case json.Number: - if pi != nil { - i, err := v.Int64() - if err == nil { - *pi = &i - return false, nil - } - } - if pf != nil { - f, err := v.Float64() - if err == nil { - *pf = &f - return false, nil - } - return false, errors.New("Unparsable number") - } - return false, errors.New("Union does not contain number") - case float64: - return false, errors.New("Decoder should not return float64") - case bool: - if pb != nil { - *pb = &v - return false, nil - } - return false, errors.New("Union does not contain bool") - case string: - if haveEnum { - return false, json.Unmarshal(data, pe) - } - if ps != nil { - *ps = &v - return false, nil - } - return false, errors.New("Union does not contain string") - case nil: - if nullable { - return false, nil - } - return false, errors.New("Union does not contain null") - case json.Delim: - if v == '{' { - if haveObject { - return true, json.Unmarshal(data, pc) - } - if haveMap { - return false, json.Unmarshal(data, pm) - } - return false, errors.New("Union does not contain object") - } - if v == '[' { - if haveArray { - return false, json.Unmarshal(data, pa) - } - return false, errors.New("Union does not contain array") - } - return false, errors.New("Cannot handle delimiter") - } - return false, errors.New("Cannot unmarshal union") + if pi != nil { + *pi = nil + } + if pf != nil { + *pf = nil + } + if pb != nil { + *pb = nil + } + if ps != nil { + *ps = nil + } + + dec := json.NewDecoder(bytes.NewReader(data)) + dec.UseNumber() + tok, err := dec.Token() + if err != nil { + return false, err + } + + switch v := tok.(type) { + case json.Number: + if pi != nil { + i, err := v.Int64() + if err == nil { + *pi = &i + return false, nil + } + } + if pf != nil { + f, err := v.Float64() + if err == nil { + *pf = &f + return false, nil + } + return false, errors.New("Unparsable number") + } + return false, errors.New("Union does not contain number") + case float64: + return false, errors.New("Decoder should not return float64") + case bool: + if pb != nil { + *pb = &v + return false, nil + } + return false, errors.New("Union does not contain bool") + case string: + if haveEnum { + return false, json.Unmarshal(data, pe) + } + if ps != nil { + *ps = &v + return false, nil + } + return false, errors.New("Union does not contain string") + case nil: + if nullable { + return false, nil + } + return false, errors.New("Union does not contain null") + case json.Delim: + if v == '{' { + if haveObject { + return true, json.Unmarshal(data, pc) + } + if haveMap { + return false, json.Unmarshal(data, pm) + } + return false, errors.New("Union does not contain object") + } + if v == '[' { + if haveArray { + return false, json.Unmarshal(data, pa) + } + return false, errors.New("Union does not contain array") + } + return false, errors.New("Cannot handle delimiter") + } + return false, errors.New("Cannot unmarshal union") } func marshalUnion(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) ([]byte, error) { - if pi != nil { - return json.Marshal(*pi) - } - if pf != nil { - return json.Marshal(*pf) - } - if pb != nil { - return json.Marshal(*pb) - } - if ps != nil { - return json.Marshal(*ps) - } - if haveArray { - return json.Marshal(pa) - } - if haveObject { - return json.Marshal(pc) - } - if haveMap { - return json.Marshal(pm) - } - if haveEnum { - return json.Marshal(pe) - } - if nullable { - return json.Marshal(nil) - } - return nil, errors.New("Union must not be null") + if pi != nil { + return json.Marshal(*pi) + } + if pf != nil { + return json.Marshal(*pf) + } + if pb != nil { + return json.Marshal(*pb) + } + if ps != nil { + return json.Marshal(*ps) + } + if haveArray { + return json.Marshal(pa) + } + if haveObject { + return json.Marshal(pc) + } + if haveMap { + return json.Marshal(pm) + } + if haveEnum { + return json.Marshal(pe) + } + if nullable { + return json.Marshal(nil) + } + return nil, errors.New("Union must not be null") }`); this.endFile(); } diff --git a/packages/quicktype-core/src/language/Golang/index.ts b/packages/quicktype-core/src/language/Golang/index.ts new file mode 100644 index 000000000..04d294d43 --- /dev/null +++ b/packages/quicktype-core/src/language/Golang/index.ts @@ -0,0 +1,2 @@ +export { GoTargetLanguage, goOptions } from "./language"; +export { GoRenderer } from "./GolangRenderer"; diff --git a/packages/quicktype-core/src/language/Golang/language.ts b/packages/quicktype-core/src/language/Golang/language.ts new file mode 100644 index 000000000..f38edff15 --- /dev/null +++ b/packages/quicktype-core/src/language/Golang/language.ts @@ -0,0 +1,60 @@ +import { type RenderContext } from "../../Renderer"; +import { BooleanOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import { type PrimitiveStringTypeKind, type TransformedStringTypeKind } from "../../Type"; +import { type StringTypeMapping } from "../../TypeBuilder"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; + +import { GoRenderer } from "./GolangRenderer"; + +export const goOptions = { + justTypes: new BooleanOption("just-types", "Plain types only", false), + justTypesAndPackage: new BooleanOption("just-types-and-package", "Plain types with package only", false), + packageName: new StringOption("package", "Generated package name", "NAME", "main"), + multiFileOutput: new BooleanOption("multi-file-output", "Renders each top-level object in its own Go file", false), + fieldTags: new StringOption("field-tags", "list of tags which should be generated for fields", "TAGS", "json"), + omitEmpty: new BooleanOption( + "omit-empty", + 'If set, all non-required objects will be tagged with ",omitempty"', + false + ) +}; + +export class GoTargetLanguage extends TargetLanguage { + public constructor() { + super("Go", ["go", "golang"], "go"); + } + + protected getOptions(): Array> { + return [ + goOptions.justTypes, + goOptions.justTypesAndPackage, + goOptions.packageName, + goOptions.multiFileOutput, + goOptions.fieldTags, + goOptions.omitEmpty + ]; + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + public get stringTypeMapping(): StringTypeMapping { + const mapping: Map = new Map(); + mapping.set("date-time", "date-time"); + return mapping; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): GoRenderer { + return new GoRenderer(this, renderContext, getOptionValues(goOptions, untypedOptionValues)); + } + + protected get defaultIndentation(): string { + return "\t"; + } +} diff --git a/packages/quicktype-core/src/language/Golang/utils.ts b/packages/quicktype-core/src/language/Golang/utils.ts new file mode 100644 index 000000000..ce67443af --- /dev/null +++ b/packages/quicktype-core/src/language/Golang/utils.ts @@ -0,0 +1,44 @@ +import { funPrefixNamer } from "../../Naming"; +import { + allUpperWordStyle, + combineWords, + firstUpperWordStyle, + isLetterOrUnderscore, + isLetterOrUnderscoreOrDigit, + legalizeCharacters, + splitIntoWords +} from "../../support/Strings"; +import { type ClassProperty, type Type, type TypeKind } from "../../Type"; + +export const namingFunction = funPrefixNamer("namer", goNameStyle); + +const legalizeName = legalizeCharacters(isLetterOrUnderscoreOrDigit); + +function goNameStyle(original: string): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + firstUpperWordStyle, + firstUpperWordStyle, + allUpperWordStyle, + allUpperWordStyle, + "", + isLetterOrUnderscore + ); +} + +export const primitiveValueTypeKinds: TypeKind[] = ["integer", "double", "bool", "string"]; +export const compoundTypeKinds: TypeKind[] = ["array", "class", "map", "enum"]; + +export function isValueType(t: Type): boolean { + const kind = t.kind; + return primitiveValueTypeKinds.includes(kind) || kind === "class" || kind === "enum" || kind === "date-time"; +} + +export function canOmitEmpty(cp: ClassProperty, omitEmptyOption: boolean): boolean { + if (!cp.isOptional) return false; + if (omitEmptyOption) return true; + const t = cp.type; + return !["union", "null", "any"].includes(t.kind); +} diff --git a/packages/quicktype-core/src/language/Haskell.ts b/packages/quicktype-core/src/language/Haskell/HaskellRenderer.ts similarity index 82% rename from packages/quicktype-core/src/language/Haskell.ts rename to packages/quicktype-core/src/language/Haskell/HaskellRenderer.ts index 16cd16a35..b5a2143b4 100644 --- a/packages/quicktype-core/src/language/Haskell.ts +++ b/packages/quicktype-core/src/language/Haskell/HaskellRenderer.ts @@ -1,138 +1,18 @@ import { mapContains } from "collection-utils"; -import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { type Name, type Namer, funPrefixNamer } from "../Naming"; -import { type RenderContext } from "../Renderer"; -import { - BooleanOption, - EnumOption, - type Option, - type OptionValues, - StringOption, - getOptionValues -} from "../RendererOptions"; -import { type MultiWord, type Sourcelike, multiWord, parenIfNeeded, singleWord } from "../Source"; -import { - allLowerWordStyle, - allUpperWordStyle, - combineWords, - firstUpperWordStyle, - isAscii, - isLetterOrUnderscore, - isLetterOrUnderscoreOrDigit, - legalizeCharacters, - splitIntoWords, - stringEscape -} from "../support/Strings"; -import { TargetLanguage } from "../TargetLanguage"; -import { type ClassProperty, type ClassType, type EnumType, type Type, type UnionType } from "../Type"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; -import { matchType, nullableFromUnion } from "../TypeUtils"; - -export const haskellOptions = { - justTypes: new BooleanOption("just-types", "Plain types only", false), - useList: new EnumOption("array-type", "Use Array or List", [ - ["array", false], - ["list", true] - ]), - moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType") -}; - -export class HaskellTargetLanguage extends TargetLanguage { - public constructor() { - super("Haskell", ["haskell"], "haskell"); - } - - protected getOptions(): Array> { - return [haskellOptions.justTypes, haskellOptions.moduleName, haskellOptions.useList]; - } - - public get supportsOptionalClassProperties(): boolean { - return true; - } - - public get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): HaskellRenderer { - return new HaskellRenderer(this, renderContext, getOptionValues(haskellOptions, untypedOptionValues)); - } -} - -const forbiddenNames = [ - // reserved keywords - "as", - "case", - "class", - "data", - "default", - "deriving", - "do", - "else", - "family", - "forall", - "foreign", - "hiding", - "if", - "import", - "in", - "infix", - "infixl", - "infixr", - "instance", - "let", - "of", - "mdo", - "module", - "newtype", - "proc", - "qualified", - "rec", - "then", - "type", - "where", - // in Prelude keywords ... - "id", - "Array", - "HashMap", - "Map", - "Maybe", - "Bool", - "Int", - "True", - "False", - "Enum", - // Aeson types - "encode", - "decode", - "text", - "Text", - "Value", - "Object", - "Result", - "Series", - "Error" -]; - -const legalizeName = legalizeCharacters(cp => isAscii(cp) && isLetterOrUnderscoreOrDigit(cp)); - -function haskellNameStyle(original: string, upper: boolean): string { - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - upper ? firstUpperWordStyle : allLowerWordStyle, - firstUpperWordStyle, - upper ? allUpperWordStyle : allLowerWordStyle, - allUpperWordStyle, - "", - isLetterOrUnderscore - ); -} - -const upperNamingFunction = funPrefixNamer("upper", n => haskellNameStyle(n, true)); -const lowerNamingFunction = funPrefixNamer("lower", n => haskellNameStyle(n, false)); +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../../ConvenienceRenderer"; +import { type Name, type Namer } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type MultiWord, type Sourcelike, multiWord, parenIfNeeded, singleWord } from "../../Source"; +import { stringEscape } from "../../support/Strings"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { type ClassProperty, type ClassType, type EnumType, type Type, type UnionType } from "../../Type"; +import { matchType, nullableFromUnion } from "../../TypeUtils"; + +import { forbiddenNames } from "./constants"; +import { type haskellOptions } from "./language"; +import { lowerNamingFunction, upperNamingFunction } from "./utils"; export class HaskellRenderer extends ConvenienceRenderer { public constructor( @@ -143,7 +23,7 @@ export class HaskellRenderer extends ConvenienceRenderer { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace(): readonly string[] { return forbiddenNames; } diff --git a/packages/quicktype-core/src/language/Haskell/constants.ts b/packages/quicktype-core/src/language/Haskell/constants.ts new file mode 100644 index 000000000..5e09e6702 --- /dev/null +++ b/packages/quicktype-core/src/language/Haskell/constants.ts @@ -0,0 +1,54 @@ +export const forbiddenNames = [ + // reserved keywords + "as", + "case", + "class", + "data", + "default", + "deriving", + "do", + "else", + "family", + "forall", + "foreign", + "hiding", + "if", + "import", + "in", + "infix", + "infixl", + "infixr", + "instance", + "let", + "of", + "mdo", + "module", + "newtype", + "proc", + "qualified", + "rec", + "then", + "type", + "where", + // in Prelude keywords ... + "id", + "Array", + "HashMap", + "Map", + "Maybe", + "Bool", + "Int", + "True", + "False", + "Enum", + // Aeson types + "encode", + "decode", + "text", + "Text", + "Value", + "Object", + "Result", + "Series", + "Error" +] as const; diff --git a/packages/quicktype-core/src/language/Haskell/index.ts b/packages/quicktype-core/src/language/Haskell/index.ts new file mode 100644 index 000000000..9658076f0 --- /dev/null +++ b/packages/quicktype-core/src/language/Haskell/index.ts @@ -0,0 +1,2 @@ +export { HaskellTargetLanguage, haskellOptions } from "./language"; +export { HaskellRenderer } from "./HaskellRenderer"; diff --git a/packages/quicktype-core/src/language/Haskell/language.ts b/packages/quicktype-core/src/language/Haskell/language.ts new file mode 100644 index 000000000..84ad167f3 --- /dev/null +++ b/packages/quicktype-core/src/language/Haskell/language.ts @@ -0,0 +1,37 @@ +import { type RenderContext } from "../../Renderer"; +import { BooleanOption, EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; + +import { HaskellRenderer } from "./HaskellRenderer"; + +export const haskellOptions = { + justTypes: new BooleanOption("just-types", "Plain types only", false), + useList: new EnumOption("array-type", "Use Array or List", [ + ["array", false], + ["list", true] + ]), + moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType") +}; + +export class HaskellTargetLanguage extends TargetLanguage { + public constructor() { + super("Haskell", ["haskell"], "haskell"); + } + + protected getOptions(): Array> { + return [haskellOptions.justTypes, haskellOptions.moduleName, haskellOptions.useList]; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): HaskellRenderer { + return new HaskellRenderer(this, renderContext, getOptionValues(haskellOptions, untypedOptionValues)); + } +} diff --git a/packages/quicktype-core/src/language/Haskell/utils.ts b/packages/quicktype-core/src/language/Haskell/utils.ts new file mode 100644 index 000000000..3f4b1357f --- /dev/null +++ b/packages/quicktype-core/src/language/Haskell/utils.ts @@ -0,0 +1,31 @@ +import { funPrefixNamer } from "../../Naming"; +import { + allLowerWordStyle, + allUpperWordStyle, + combineWords, + firstUpperWordStyle, + isAscii, + isLetterOrUnderscore, + isLetterOrUnderscoreOrDigit, + legalizeCharacters, + splitIntoWords +} from "../../support/Strings"; + +const legalizeName = legalizeCharacters(cp => isAscii(cp) && isLetterOrUnderscoreOrDigit(cp)); + +function haskellNameStyle(original: string, upper: boolean): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + upper ? firstUpperWordStyle : allLowerWordStyle, + firstUpperWordStyle, + upper ? allUpperWordStyle : allLowerWordStyle, + allUpperWordStyle, + "", + isLetterOrUnderscore + ); +} + +export const upperNamingFunction = funPrefixNamer("upper", n => haskellNameStyle(n, true)); +export const lowerNamingFunction = funPrefixNamer("lower", n => haskellNameStyle(n, false)); diff --git a/packages/quicktype-core/src/language/JSONSchema.ts b/packages/quicktype-core/src/language/JSONSchema/JSONSchemaRenderer.ts similarity index 75% rename from packages/quicktype-core/src/language/JSONSchema.ts rename to packages/quicktype-core/src/language/JSONSchema/JSONSchemaRenderer.ts index 978906075..9b24306fa 100644 --- a/packages/quicktype-core/src/language/JSONSchema.ts +++ b/packages/quicktype-core/src/language/JSONSchema/JSONSchemaRenderer.ts @@ -1,73 +1,19 @@ import { iterableFirst, mapFirst } from "collection-utils"; -import { addDescriptionToSchema } from "../attributes/Description"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Name, type Namer, funPrefixNamer } from "../Naming"; -import { type RenderContext } from "../Renderer"; -import { type Option } from "../RendererOptions"; -import { - allUpperWordStyle, - combineWords, - firstUpperWordStyle, - legalizeCharacters, - splitIntoWords -} from "../support/Strings"; -import { defined, panic } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; +import { addDescriptionToSchema } from "../../attributes/Description"; +import { ConvenienceRenderer } from "../../ConvenienceRenderer"; +import { type Name, type Namer } from "../../Naming"; +import { defined, panic } from "../../support/Support"; import { type EnumType, type ObjectType, type Type, type UnionType, transformedStringTypeTargetTypeKindsMap -} from "../Type"; -import { type StringTypeMapping, getNoStringTypeMapping } from "../TypeBuilder"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; -import { matchTypeExhaustive } from "../TypeUtils"; - -export class JSONSchemaTargetLanguage extends TargetLanguage { - public constructor() { - super("JSON Schema", ["schema", "json-schema"], "schema"); - } - - protected getOptions(): Array> { - return []; - } - - public get stringTypeMapping(): StringTypeMapping { - return getNoStringTypeMapping(); - } - - public get supportsOptionalClassProperties(): boolean { - return true; - } - - public get supportsFullObjectType(): boolean { - return true; - } +} from "../../Type"; +import { matchTypeExhaustive } from "../../TypeUtils"; - protected makeRenderer(renderContext: RenderContext, _untypedOptionValues: FixMeOptionsType): JSONSchemaRenderer { - return new JSONSchemaRenderer(this, renderContext); - } -} - -const namingFunction = funPrefixNamer("namer", jsonNameStyle); - -const legalizeName = legalizeCharacters(cp => cp >= 32 && cp < 128 && cp !== 0x2f /* slash */); - -function jsonNameStyle(original: string): string { - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - firstUpperWordStyle, - firstUpperWordStyle, - allUpperWordStyle, - allUpperWordStyle, - "", - _ => true - ); -} +import { namingFunction } from "./utils"; interface Schema { // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/packages/quicktype-core/src/language/JSONSchema/index.ts b/packages/quicktype-core/src/language/JSONSchema/index.ts new file mode 100644 index 000000000..6cb0b7958 --- /dev/null +++ b/packages/quicktype-core/src/language/JSONSchema/index.ts @@ -0,0 +1,2 @@ +export { JSONSchemaTargetLanguage } from "./language"; +export { JSONSchemaRenderer } from "./JSONSchemaRenderer"; diff --git a/packages/quicktype-core/src/language/JSONSchema/language.ts b/packages/quicktype-core/src/language/JSONSchema/language.ts new file mode 100644 index 000000000..7ada4a1e0 --- /dev/null +++ b/packages/quicktype-core/src/language/JSONSchema/language.ts @@ -0,0 +1,33 @@ +import { type RenderContext } from "../../Renderer"; +import { type Option } from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import { type StringTypeMapping, getNoStringTypeMapping } from "../../TypeBuilder"; +import { type FixMeOptionsAnyType } from "../../types"; + +import { JSONSchemaRenderer } from "./JSONSchemaRenderer"; + +export class JSONSchemaTargetLanguage extends TargetLanguage { + public constructor() { + super("JSON Schema", ["schema", "json-schema"], "schema"); + } + + protected getOptions(): Array> { + return []; + } + + public get stringTypeMapping(): StringTypeMapping { + return getNoStringTypeMapping(); + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + public get supportsFullObjectType(): boolean { + return true; + } + + protected makeRenderer(renderContext: RenderContext, _untypedOptionValues: FixMeOptionsType): JSONSchemaRenderer { + return new JSONSchemaRenderer(this, renderContext); + } +} diff --git a/packages/quicktype-core/src/language/JSONSchema/utils.ts b/packages/quicktype-core/src/language/JSONSchema/utils.ts new file mode 100644 index 000000000..5c3a10e48 --- /dev/null +++ b/packages/quicktype-core/src/language/JSONSchema/utils.ts @@ -0,0 +1,26 @@ +import { funPrefixNamer } from "../../Naming"; +import { + allUpperWordStyle, + combineWords, + firstUpperWordStyle, + legalizeCharacters, + splitIntoWords +} from "../../support/Strings"; + +export const namingFunction = funPrefixNamer("namer", jsonNameStyle); + +const legalizeName = legalizeCharacters(cp => cp >= 32 && cp < 128 && cp !== 0x2f /* slash */); + +function jsonNameStyle(original: string): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + firstUpperWordStyle, + firstUpperWordStyle, + allUpperWordStyle, + allUpperWordStyle, + "", + _ => true + ); +} diff --git a/packages/quicktype-core/src/language/Java/DateTimeProvider.ts b/packages/quicktype-core/src/language/Java/DateTimeProvider.ts new file mode 100644 index 000000000..78228db01 --- /dev/null +++ b/packages/quicktype-core/src/language/Java/DateTimeProvider.ts @@ -0,0 +1,261 @@ +import { type Sourcelike } from "../../Source"; + +import { type JavaRenderer } from "./JavaRenderer"; + +export abstract class JavaDateTimeProvider { + public constructor( + protected readonly _renderer: JavaRenderer, + protected readonly _className: string + ) {} + + public abstract keywords: string[]; + + public abstract dateTimeImports: string[]; + + public abstract dateImports: string[]; + + public abstract timeImports: string[]; + + public abstract converterImports: string[]; + + public abstract dateTimeType: string; + + public abstract dateType: string; + + public abstract timeType: string; + + public abstract dateTimeJacksonAnnotations: string[]; + + public abstract dateJacksonAnnotations: string[]; + + public abstract timeJacksonAnnotations: string[]; + + public abstract emitDateTimeConverters(): void; + + public shouldEmitDateTimeConverter = true; + + public shouldEmitTimeConverter = true; + + public shouldEmitDateConverter = true; + + public abstract convertStringToDateTime(variable: Sourcelike): Sourcelike; + public abstract convertStringToTime(variable: Sourcelike): Sourcelike; + public abstract convertStringToDate(variable: Sourcelike): Sourcelike; + + public abstract convertDateTimeToString(variable: Sourcelike): Sourcelike; + public abstract convertTimeToString(variable: Sourcelike): Sourcelike; + public abstract convertDateToString(variable: Sourcelike): Sourcelike; +} + +export class Java8DateTimeProvider extends JavaDateTimeProvider { + public keywords = [ + "LocalDate", + "OffsetDateTime", + "OffsetTime", + "ZoneOffset", + "ZonedDateTime", + "DateTimeFormatter", + "DateTimeFormatterBuilder", + "ChronoField" + ]; + + public dateTimeImports: string[] = ["java.time.OffsetDateTime"]; + + public dateImports: string[] = ["java.time.LocalDate"]; + + public timeImports: string[] = ["java.time.OffsetTime"]; + + public converterImports: string[] = [ + "java.time.LocalDate", + "java.time.OffsetDateTime", + "java.time.OffsetTime", + "java.time.ZoneOffset", + "java.time.ZonedDateTime", + "java.time.format.DateTimeFormatter", + "java.time.format.DateTimeFormatterBuilder", + "java.time.temporal.ChronoField" + ]; + + public dateTimeType = "OffsetDateTime"; + + public dateType = "LocalDate"; + + public timeType = "OffsetTime"; + + public dateTimeJacksonAnnotations: string[] = []; + + public dateJacksonAnnotations: string[] = []; + + public timeJacksonAnnotations: string[] = []; + + public emitDateTimeConverters(): void { + this._renderer.ensureBlankLine(); + this._renderer.emitLine( + "private static final DateTimeFormatter DATE_TIME_FORMATTER = new DateTimeFormatterBuilder()" + ); + this._renderer.indent(() => + this._renderer.indent(() => { + this._renderer.emitLine(".appendOptional(DateTimeFormatter.ISO_DATE_TIME)"); + this._renderer.emitLine(".appendOptional(DateTimeFormatter.ISO_OFFSET_DATE_TIME)"); + this._renderer.emitLine(".appendOptional(DateTimeFormatter.ISO_INSTANT)"); + this._renderer.emitLine('.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SX"))'); + this._renderer.emitLine('.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ssX"))'); + this._renderer.emitLine('.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))'); + this._renderer.emitLine(".toFormatter()"); + this._renderer.emitLine(".withZone(ZoneOffset.UTC);"); + }) + ); + this._renderer.ensureBlankLine(); + this._renderer.emitBlock("public static OffsetDateTime parseDateTimeString(String str)", () => { + this._renderer.emitLine( + "return ZonedDateTime.from(Converter.DATE_TIME_FORMATTER.parse(str)).toOffsetDateTime();" + ); + }); + + this._renderer.ensureBlankLine(); + this._renderer.emitLine( + "private static final DateTimeFormatter TIME_FORMATTER = new DateTimeFormatterBuilder()" + ); + this._renderer.indent(() => + this._renderer.indent(() => { + this._renderer.emitLine(".appendOptional(DateTimeFormatter.ISO_TIME)"); + this._renderer.emitLine(".appendOptional(DateTimeFormatter.ISO_OFFSET_TIME)"); + this._renderer.emitLine(".parseDefaulting(ChronoField.YEAR, 2020)"); + this._renderer.emitLine(".parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)"); + this._renderer.emitLine(".parseDefaulting(ChronoField.DAY_OF_MONTH, 1)"); + this._renderer.emitLine(".toFormatter()"); + this._renderer.emitLine(".withZone(ZoneOffset.UTC);"); + }) + ); + this._renderer.ensureBlankLine(); + this._renderer.emitBlock("public static OffsetTime parseTimeString(String str)", () => { + this._renderer.emitLine( + "return ZonedDateTime.from(Converter.TIME_FORMATTER.parse(str)).toOffsetDateTime().toOffsetTime();" + ); + }); + } + + public convertStringToDateTime(variable: Sourcelike): Sourcelike { + return [this._className, ".parseDateTimeString(", variable, ")"]; + } + + public convertStringToTime(variable: Sourcelike): Sourcelike { + return [this._className, ".parseTimeString(", variable, ")"]; + } + + public convertStringToDate(variable: Sourcelike): Sourcelike { + return ["LocalDate.parse(", variable, ")"]; + } + + public convertDateTimeToString(variable: Sourcelike): Sourcelike { + return [variable, ".format(java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME)"]; + } + + public convertTimeToString(variable: Sourcelike): Sourcelike { + return [variable, ".format(java.time.format.DateTimeFormatter.ISO_OFFSET_TIME)"]; + } + + public convertDateToString(variable: Sourcelike): Sourcelike { + return [variable, ".format(java.time.format.DateTimeFormatter.ISO_DATE)"]; + } +} +export class JavaLegacyDateTimeProvider extends JavaDateTimeProvider { + public keywords = ["SimpleDateFormat", "Date"]; + + public dateTimeImports: string[] = ["java.util.Date"]; + + public dateImports: string[] = ["java.util.Date"]; + + public timeImports: string[] = ["java.util.Date"]; + + public converterImports: string[] = ["java.util.Date", "java.text.SimpleDateFormat"]; + + public dateTimeType = "Date"; + + public dateType = "Date"; + + public timeType = "Date"; + + public dateTimeJacksonAnnotations: string[] = [ + '@JsonFormat(pattern = "yyyy-MM-dd\'T\'HH:mm:ssX", timezone = "UTC")' + ]; + + public dateJacksonAnnotations: string[] = ['@JsonFormat(pattern = "yyyy-MM-dd")']; + + public timeJacksonAnnotations: string[] = ['@JsonFormat(pattern = "HH:mm:ssX", timezone = "UTC")']; + + public shouldEmitTimeConverter = false; + + public shouldEmitDateConverter = false; + + public emitDateTimeConverters(): void { + this._renderer.ensureBlankLine(); + this._renderer.emitLine("private static final String[] DATE_TIME_FORMATS = {"); + this._renderer.indent(() => + this._renderer.indent(() => { + this._renderer.emitLine("\"yyyy-MM-dd'T'HH:mm:ss.SX\","); + this._renderer.emitLine("\"yyyy-MM-dd'T'HH:mm:ss.S\","); + this._renderer.emitLine("\"yyyy-MM-dd'T'HH:mm:ssX\","); + this._renderer.emitLine("\"yyyy-MM-dd'T'HH:mm:ss\","); + this._renderer.emitLine('"yyyy-MM-dd HH:mm:ss.SX",'); + this._renderer.emitLine('"yyyy-MM-dd HH:mm:ss.S",'); + this._renderer.emitLine('"yyyy-MM-dd HH:mm:ssX",'); + this._renderer.emitLine('"yyyy-MM-dd HH:mm:ss",'); + this._renderer.emitLine('"HH:mm:ss.SZ",'); + this._renderer.emitLine('"HH:mm:ss.S",'); + this._renderer.emitLine('"HH:mm:ssZ",'); + this._renderer.emitLine('"HH:mm:ss",'); + this._renderer.emitLine('"yyyy-MM-dd",'); + }) + ); + this._renderer.emitLine("};"); + this._renderer.ensureBlankLine(); + this._renderer.emitBlock("public static Date parseAllDateTimeString(String str)", () => { + this._renderer.emitBlock("for (String format : DATE_TIME_FORMATS)", () => { + this._renderer.emitIgnoredTryCatchBlock(() => { + this._renderer.emitLine("return new SimpleDateFormat(format).parse(str);"); + }); + }); + this._renderer.emitLine("return null;"); + }); + + this._renderer.ensureBlankLine(); + this._renderer.emitBlock("public static String serializeDateTime(Date datetime)", () => { + this._renderer.emitLine("return new SimpleDateFormat(\"yyyy-MM-dd'T'hh:mm:ssZ\").format(datetime);"); + }); + + this._renderer.ensureBlankLine(); + this._renderer.emitBlock("public static String serializeDate(Date datetime)", () => { + this._renderer.emitLine('return new SimpleDateFormat("yyyy-MM-dd").format(datetime);'); + }); + + this._renderer.ensureBlankLine(); + this._renderer.emitBlock("public static String serializeTime(Date datetime)", () => { + this._renderer.emitLine('return new SimpleDateFormat("hh:mm:ssZ").format(datetime);'); + }); + } + + public convertStringToDateTime(variable: Sourcelike): Sourcelike { + return [this._className, ".parseAllDateTimeString(", variable, ")"]; + } + + public convertStringToTime(variable: Sourcelike): Sourcelike { + return [this._className, ".parseAllDateTimeString(", variable, ")"]; + } + + public convertStringToDate(variable: Sourcelike): Sourcelike { + return [this._className, ".parseAllDateTimeString(", variable, ")"]; + } + + public convertDateTimeToString(variable: Sourcelike): Sourcelike { + return [this._className, ".serializeDateTime(", variable, ")"]; + } + + public convertTimeToString(variable: Sourcelike): Sourcelike { + return [this._className, ".serializeTime(", variable, ")"]; + } + + public convertDateToString(variable: Sourcelike): Sourcelike { + return [this._className, ".serializeDate(", variable, ")"]; + } +} diff --git a/packages/quicktype-core/src/language/Java/JavaJacksonRenderer.ts b/packages/quicktype-core/src/language/Java/JavaJacksonRenderer.ts new file mode 100644 index 000000000..3329b61cd --- /dev/null +++ b/packages/quicktype-core/src/language/Java/JavaJacksonRenderer.ts @@ -0,0 +1,567 @@ +import { type Name } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type Sourcelike } from "../../Source"; +import { assertNever, panic } from "../../support/Support"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { ArrayType, type ClassProperty, ClassType, EnumType, type Type, type TypeKind, UnionType } from "../../Type"; +import { removeNullFromUnion } from "../../TypeUtils"; + +import { JavaRenderer } from "./JavaRenderer"; +import { type javaOptions } from "./language"; +import { stringEscape } from "./utils"; + + +export class JacksonRenderer extends JavaRenderer { + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + options: OptionValues + ) { + super(targetLanguage, renderContext, options); + } + + protected readonly _converterKeywords: string[] = [ + "JsonProperty", + "JsonDeserialize", + "JsonDeserializer", + "JsonSerialize", + "JsonSerializer", + "JsonParser", + "JsonProcessingException", + "DeserializationContext", + "SerializerProvider" + ]; + + protected emitClassAttributes(c: ClassType, _className: Name): void { + if (c.getProperties().size === 0) + this.emitLine("@JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.NONE)"); + + super.emitClassAttributes(c, _className); + } + + protected annotationsForAccessor( + _c: ClassType, + _className: Name, + _propertyName: Name, + jsonName: string, + p: ClassProperty, + _isSetter: boolean + ): string[] { + const superAnnotations = super.annotationsForAccessor(_c, _className, _propertyName, jsonName, p, _isSetter); + + const annotations: string[] = ['@JsonProperty("' + stringEscape(jsonName) + '")']; + + switch (p.type.kind) { + case "date-time": + this._dateTimeProvider.dateTimeJacksonAnnotations.forEach(annotation => annotations.push(annotation)); + break; + case "date": + this._dateTimeProvider.dateJacksonAnnotations.forEach(annotation => annotations.push(annotation)); + break; + case "time": + this._dateTimeProvider.timeJacksonAnnotations.forEach(annotation => annotations.push(annotation)); + break; + default: + break; + } + + return [...superAnnotations, ...annotations]; + } + + protected importsForType(t: ClassType | UnionType | EnumType): string[] { + if (t instanceof ClassType) { + const imports = super.importsForType(t); + imports.push("com.fasterxml.jackson.annotation.*"); + return imports; + } + + if (t instanceof UnionType) { + const imports = super.importsForType(t); + imports.push( + "java.io.IOException", + "com.fasterxml.jackson.core.*", + "com.fasterxml.jackson.databind.*", + "com.fasterxml.jackson.databind.annotation.*" + ); + if (this._options.useList) { + imports.push("com.fasterxml.jackson.core.type.*"); + } + + return imports; + } + + if (t instanceof EnumType) { + const imports = super.importsForType(t); + imports.push("com.fasterxml.jackson.annotation.*"); + return imports; + } + + return assertNever(t); + } + + protected emitUnionAttributes(_u: UnionType, unionName: Name): void { + this.emitLine("@JsonDeserialize(using = ", unionName, ".Deserializer.class)"); + this.emitLine("@JsonSerialize(using = ", unionName, ".Serializer.class)"); + } + + protected emitUnionSerializer(u: UnionType, unionName: Name): void { + const stringBasedObjects: TypeKind[] = ["uuid", "time", "date", "date-time"]; + + const tokenCase = (tokenType: string): void => { + this.emitLine("case ", tokenType, ":"); + }; + + const emitNullDeserializer = (): void => { + this.indent(() => { + tokenCase("VALUE_NULL"); + this.indent(() => this.emitLine("break;")); + }); + }; + + const emitDeserializerCodeForStringObjects = ( + fieldName: Sourcelike, + kind: TypeKind, + parseFrom: string + ): void => { + switch (kind) { + case "date": + this.emitLine( + "value.", + fieldName, + " = ", + this._dateTimeProvider.convertStringToDate(parseFrom), + ";" + ); + + break; + case "time": + this.emitLine( + "value.", + fieldName, + " = ", + this._dateTimeProvider.convertStringToTime(parseFrom), + ";" + ); + + break; + case "date-time": + this.emitLine( + "value.", + fieldName, + " = ", + this._dateTimeProvider.convertStringToDateTime(parseFrom), + ";" + ); + break; + case "uuid": + this.emitLine("value.", fieldName, " = UUID.fromString(", parseFrom, ");"); + + break; + default: + return panic("Requested type isnt an object!"); + } + }; + + const emitDeserializeType = (t: Type, variableFieldName = ""): void => { + const { fieldName } = this.unionField(u, t); + const rendered = this.javaTypeWithoutGenerics(true, t); + if (this._options.useList && t instanceof ArrayType) { + this.emitLine( + "value.", + fieldName, + " = jsonParser.readValueAs(new TypeReference<", + rendered, + ">() {});" + ); + } else if (stringBasedObjects.some(stringBasedTypeKind => t.kind === stringBasedTypeKind)) { + emitDeserializerCodeForStringObjects(fieldName, t.kind, variableFieldName); + } else if (t.kind === "string") { + this.emitLine("value.", fieldName, " = ", variableFieldName, ";"); + } else if (t.kind === "enum") { + const { fieldType } = this.unionField(u, t, true); + this.emitLine("value.", fieldName, " = ", fieldType, ".forValue(", variableFieldName, ");"); + } else { + this.emitLine("value.", fieldName, " = jsonParser.readValueAs(", rendered, ".class);"); + } + }; + + const emitDeserializer = (tokenTypes: string[], kind: TypeKind): void => { + const t = u.findMember(kind); + if (t === undefined) return; + + this.indent(() => { + for (const tokenType of tokenTypes) { + tokenCase(tokenType); + } + + this.indent(() => { + emitDeserializeType(t); + this.emitLine("break;"); + }); + }); + }; + + const emitStringDeserializer = (): void => { + const enumType = u.findMember("enum"); + const stringType = u.findMember("string"); + + if ( + stringBasedObjects.every(kind => u.findMember(kind) === undefined) && + stringType === undefined && + enumType === undefined + ) + return; + + this.indent(() => { + tokenCase("VALUE_STRING"); + + this.indent(() => { + const fromVariable = "string"; + this.emitLine("String " + fromVariable + " = jsonParser.readValueAs(String.class);"); + + stringBasedObjects.forEach(kind => { + const type = u.findMember(kind); + if (type !== undefined) { + this.emitIgnoredTryCatchBlock(() => { + emitDeserializeType(type, fromVariable); + }); + } + }); + + if (enumType !== undefined) { + this.emitIgnoredTryCatchBlock(() => { + emitDeserializeType(enumType, fromVariable); + }); + } + + // String should be the last one if exists, because it cannot fail, unlike the parsers. + if (stringType !== undefined) { + emitDeserializeType(stringType, fromVariable); + } + + this.emitLine("break;"); + }); + }); + }; + + const emitNumberDeserializer = (): void => { + const integerType = u.findMember("integer"); + const doubleType = u.findMember("double"); + if (doubleType === undefined && integerType === undefined) return; + + this.indent(() => { + tokenCase("VALUE_NUMBER_INT"); + if (integerType !== undefined) { + this.indent(() => { + emitDeserializeType(integerType); + this.emitLine("break;"); + }); + } + + if (doubleType !== undefined) { + tokenCase("VALUE_NUMBER_FLOAT"); + this.indent(() => { + emitDeserializeType(doubleType); + this.emitLine("break;"); + }); + } + }); + }; + + const customObjectSerializer: TypeKind[] = ["time", "date", "date-time"]; + + const serializerCodeForType = (type: Type, fieldName: Sourcelike): Sourcelike => { + switch (type.kind) { + case "date": + return this._dateTimeProvider.convertDateToString(fieldName); + case "time": + return this._dateTimeProvider.convertTimeToString(fieldName); + case "date-time": + return this._dateTimeProvider.convertDateTimeToString(fieldName); + default: + return panic("Requested type doesn't have custom serializer code!"); + } + }; + + const emitSerializeType = (t: Type): void => { + let { fieldName } = this.unionField(u, t, true); + + this.emitBlock(["if (obj.", fieldName, " != null)"], () => { + if (customObjectSerializer.some(customSerializerType => t.kind === customSerializerType)) { + this.emitLine("jsonGenerator.writeObject(", serializerCodeForType(t, ["obj.", fieldName]), ");"); + } else { + this.emitLine("jsonGenerator.writeObject(obj.", fieldName, ");"); + } + + this.emitLine("return;"); + }); + }; + + const [maybeNull, nonNulls] = removeNullFromUnion(u); + + this.ensureBlankLine(); + this.emitBlock(["static class Deserializer extends JsonDeserializer<", unionName, ">"], () => { + this.emitLine("@Override"); + this.emitBlock( + [ + "public ", + unionName, + " deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException" + ], + () => { + this.emitLine(unionName, " value = new ", unionName, "();"); + this.emitLine("switch (jsonParser.currentToken()) {"); + if (maybeNull !== null) emitNullDeserializer(); + emitNumberDeserializer(); + emitDeserializer(["VALUE_TRUE", "VALUE_FALSE"], "bool"); + emitStringDeserializer(); + emitDeserializer(["START_ARRAY"], "array"); + emitDeserializer(["START_OBJECT"], "class"); + emitDeserializer(["START_OBJECT"], "map"); + this.indent(() => + this.emitLine('default: throw new IOException("Cannot deserialize ', unionName, '");') + ); + this.emitLine("}"); + this.emitLine("return value;"); + } + ); + }); + this.ensureBlankLine(); + this.emitBlock(["static class Serializer extends JsonSerializer<", unionName, ">"], () => { + this.emitLine("@Override"); + this.emitBlock( + [ + "public void serialize(", + unionName, + " obj, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException" + ], + () => { + for (const t of nonNulls) { + emitSerializeType(t); + } + + if (maybeNull !== null) { + this.emitLine("jsonGenerator.writeNull();"); + } else { + this.emitLine('throw new IOException("', unionName, ' must not be null");'); + } + } + ); + }); + } + + protected emitEnumSerializationAttributes(_e: EnumType): void { + this.emitLine("@JsonValue"); + } + + protected emitEnumDeserializationAttributes(_e: EnumType): void { + this.emitLine("@JsonCreator"); + } + + protected emitOffsetDateTimeConverterModule(): void { + this.emitLine("SimpleModule module = new SimpleModule();"); + + if (this._dateTimeProvider.shouldEmitDateTimeConverter) { + this.emitLine( + "module.addDeserializer(", + this._dateTimeProvider.dateTimeType, + ".class, new JsonDeserializer<", + this._dateTimeProvider.dateTimeType, + ">() {" + ); + this.indent(() => { + this.emitLine("@Override"); + this.emitBlock( + [ + "public ", + this._dateTimeProvider.dateTimeType, + " deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) ", + "throws IOException, JsonProcessingException" + ], + () => { + this.emitLine("String value = jsonParser.getText();"); + this.emitLine("return ", this._dateTimeProvider.convertStringToDateTime("value"), ";"); + } + ); + }); + this.emitLine("});"); + } + + if (!this._dateTimeProvider.shouldEmitTimeConverter) { + this.emitLine( + "module.addDeserializer(", + this._dateTimeProvider.timeType, + ".class, new JsonDeserializer<", + this._dateTimeProvider.timeType, + ">() {" + ); + this.indent(() => { + this.emitLine("@Override"); + this.emitBlock( + [ + "public ", + this._dateTimeProvider.timeType, + " deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) ", + "throws IOException, JsonProcessingException" + ], + () => { + this.emitLine("String value = jsonParser.getText();"); + this.emitLine("return ", this._dateTimeProvider.convertStringToTime("value"), ";"); + } + ); + }); + this.emitLine("});"); + } + + if (!this._dateTimeProvider.shouldEmitDateConverter) { + this.emitLine( + "module.addDeserializer(", + this._dateTimeProvider.dateType, + ".class, new JsonDeserializer<", + this._dateTimeProvider.dateType, + ">() {" + ); + this.indent(() => { + this.emitLine("@Override"); + this.emitBlock( + [ + "public ", + this._dateTimeProvider.dateType, + " deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) ", + "throws IOException, JsonProcessingException" + ], + () => { + this.emitLine("String value = jsonParser.getText();"); + this.emitLine("return ", this._dateTimeProvider.convertStringToDate("value"), ";"); + } + ); + }); + this.emitLine("});"); + } + + this.emitLine("mapper.registerModule(module);"); + } + + protected emitConverterClass(): void { + this.startFile(this._converterClassname); + this.emitCommentLines([ + "To use this code, add the following Maven dependency to your project:", + "", + this._options.lombok ? " org.projectlombok : lombok : 1.18.2" : "", + " com.fasterxml.jackson.core : jackson-databind : 2.9.0", + this._options.dateTimeProvider === "java8" + ? " com.fasterxml.jackson.datatype : jackson-datatype-jsr310 : 2.9.0" + : "", + "", + "Import this package:", + "" + ]); + this.emitLine("// import ", this._options.packageName, ".Converter;"); + this.emitMultiline(`// +// Then you can deserialize a JSON string with +//`); + this.forEachTopLevel("none", (t, name) => { + this.emitLine( + "// ", + this.javaType(false, t), + " data = Converter.", + this.decoderName(name), + "(jsonString);" + ); + }); + this.ensureBlankLine(); + const imports = [ + "java.io.IOException", + "com.fasterxml.jackson.databind.*", + "com.fasterxml.jackson.databind.module.SimpleModule", + "com.fasterxml.jackson.core.JsonParser", + "com.fasterxml.jackson.core.JsonProcessingException", + "java.util.*" + ].concat(this._dateTimeProvider.converterImports); + this.emitPackageAndImports(imports); + this.ensureBlankLine(); + this.emitBlock(["public class Converter"], () => { + this.emitLine("// Date-time helpers"); + this._dateTimeProvider.emitDateTimeConverters(); + + this.emitLine("// Serialize/deserialize helpers"); + this.forEachTopLevel("leading-and-interposing", (topLevelType, topLevelName) => { + const topLevelTypeRendered = this.javaType(false, topLevelType); + this.emitBlock( + [ + "public static ", + topLevelTypeRendered, + " ", + this.decoderName(topLevelName), + "(String json) throws IOException" + ], + () => { + this.emitLine("return ", this.readerGetterName(topLevelName), "().readValue(json);"); + } + ); + this.ensureBlankLine(); + this.emitBlock( + [ + "public static String ", + this.encoderName(topLevelName), + "(", + topLevelTypeRendered, + " obj) throws JsonProcessingException" + ], + () => { + this.emitLine("return ", this.writerGetterName(topLevelName), "().writeValueAsString(obj);"); + } + ); + }); + this.forEachTopLevel("leading-and-interposing", (topLevelType, topLevelName) => { + const readerName = this.fieldOrMethodName("reader", topLevelName); + const writerName = this.fieldOrMethodName("writer", topLevelName); + this.emitLine("private static ObjectReader ", readerName, ";"); + this.emitLine("private static ObjectWriter ", writerName, ";"); + this.ensureBlankLine(); + this.emitBlock( + ["private static void ", this.methodName("instantiate", "Mapper", topLevelName), "()"], + () => { + const renderedForClass = this.javaTypeWithoutGenerics(false, topLevelType); + this.emitLine("ObjectMapper mapper = new ObjectMapper();"); + this.emitLine("mapper.findAndRegisterModules();"); + this.emitLine("mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);"); + this.emitLine("mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);"); + this.emitOffsetDateTimeConverterModule(); + this.emitLine(readerName, " = mapper.readerFor(", renderedForClass, ".class);"); + this.emitLine(writerName, " = mapper.writerFor(", renderedForClass, ".class);"); + } + ); + this.ensureBlankLine(); + this.emitBlock(["private static ObjectReader ", this.readerGetterName(topLevelName), "()"], () => { + this.emitLine( + "if (", + readerName, + " == null) ", + this.methodName("instantiate", "Mapper", topLevelName), + "();" + ); + this.emitLine("return ", readerName, ";"); + }); + this.ensureBlankLine(); + this.emitBlock(["private static ObjectWriter ", this.writerGetterName(topLevelName), "()"], () => { + this.emitLine( + "if (", + writerName, + " == null) ", + this.methodName("instantiate", "Mapper", topLevelName), + "();" + ); + this.emitLine("return ", writerName, ";"); + }); + }); + }); + this.finishFile(); + } + + protected emitSourceStructure(): void { + this.emitConverterClass(); + super.emitSourceStructure(); + } +} diff --git a/packages/quicktype-core/src/language/Java/JavaRenderer.ts b/packages/quicktype-core/src/language/Java/JavaRenderer.ts new file mode 100644 index 000000000..1054df770 --- /dev/null +++ b/packages/quicktype-core/src/language/Java/JavaRenderer.ts @@ -0,0 +1,514 @@ +import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../../Annotation"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../../ConvenienceRenderer"; +import { DependencyName, type Name, type Namer, funPrefixNamer } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type Sourcelike, maybeAnnotated } from "../../Source"; +import { acronymStyle } from "../../support/Acronyms"; +import { capitalize } from "../../support/Strings"; +import { assert, assertNever, defined } from "../../support/Support"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { ArrayType, type ClassProperty, ClassType, EnumType, MapType, type Type, UnionType } from "../../Type"; +import { directlyReachableSingleNamedType, matchType, nullableFromUnion, removeNullFromUnion } from "../../TypeUtils"; + +import { javaKeywords } from "./constants"; +import { Java8DateTimeProvider, type JavaDateTimeProvider, JavaLegacyDateTimeProvider } from "./DateTimeProvider"; +import { type javaOptions } from "./language"; +import { javaNameStyle, stringEscape } from "./utils"; + +export class JavaRenderer extends ConvenienceRenderer { + private _currentFilename: string | undefined; + + private readonly _gettersAndSettersForPropertyName = new Map(); + + private _haveEmittedLeadingComments = false; + + protected readonly _dateTimeProvider: JavaDateTimeProvider; + + protected readonly _converterClassname: string = "Converter"; + + protected readonly _converterKeywords: string[] = []; + + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + protected readonly _options: OptionValues + ) { + super(targetLanguage, renderContext); + + switch (_options.dateTimeProvider) { + default: + case "java8": + this._dateTimeProvider = new Java8DateTimeProvider(this, this._converterClassname); + break; + case "legacy": + this._dateTimeProvider = new JavaLegacyDateTimeProvider(this, this._converterClassname); + break; + } + } + + protected forbiddenNamesForGlobalNamespace(): string[] { + const keywords = [ + ...javaKeywords, + ...this._converterKeywords, + this._converterClassname, + ...this._dateTimeProvider.keywords + ]; + return keywords; + } + + protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: true }; + } + + protected makeNamedTypeNamer(): Namer { + return this.getNameStyling("typeNamingFunction"); + } + + protected namerForObjectProperty(): Namer { + return this.getNameStyling("propertyNamingFunction"); + } + + protected makeUnionMemberNamer(): Namer { + return this.getNameStyling("propertyNamingFunction"); + } + + protected makeEnumCaseNamer(): Namer { + return this.getNameStyling("enumCaseNamingFunction"); + } + + protected unionNeedsName(u: UnionType): boolean { + return nullableFromUnion(u) === null; + } + + protected namedTypeToNameForTopLevel(type: Type): Type | undefined { + // If the top-level type doesn't contain any classes or unions + // we have to define a class just for the `FromJson` method, in + // emitFromJsonForTopLevel. + return directlyReachableSingleNamedType(type); + } + + protected makeNamesForPropertyGetterAndSetter( + _c: ClassType, + _className: Name, + _p: ClassProperty, + _jsonName: string, + name: Name + ): [Name, Name] { + const getterName = new DependencyName( + this.getNameStyling("propertyNamingFunction"), + name.order, + lookup => `get_${lookup(name)}` + ); + const setterName = new DependencyName( + this.getNameStyling("propertyNamingFunction"), + name.order, + lookup => `set_${lookup(name)}` + ); + return [getterName, setterName]; + } + + protected makePropertyDependencyNames( + c: ClassType, + className: Name, + p: ClassProperty, + jsonName: string, + name: Name + ): Name[] { + const getterAndSetterNames = this.makeNamesForPropertyGetterAndSetter(c, className, p, jsonName, name); + this._gettersAndSettersForPropertyName.set(name, getterAndSetterNames); + return getterAndSetterNames; + } + + private getNameStyling(convention: string): Namer { + const styling: { [key: string]: Namer } = { + typeNamingFunction: funPrefixNamer("types", n => + javaNameStyle(true, false, n, acronymStyle(this._options.acronymStyle)) + ), + propertyNamingFunction: funPrefixNamer("properties", n => + javaNameStyle(false, false, n, acronymStyle(this._options.acronymStyle)) + ), + enumCaseNamingFunction: funPrefixNamer("enum-cases", n => + javaNameStyle(true, true, n, acronymStyle(this._options.acronymStyle)) + ) + }; + return styling[convention]; + } + + protected fieldOrMethodName(methodName: string, topLevelName: Name): Sourcelike { + if (this.topLevels.size === 1) { + return methodName; + } + + return [topLevelName, capitalize(methodName)]; + } + + protected methodName(prefix: string, suffix: string, topLevelName: Name): Sourcelike { + if (this.topLevels.size === 1) { + return [prefix, suffix]; + } + + return [prefix, topLevelName, suffix]; + } + + protected decoderName(topLevelName: Name): Sourcelike { + return this.fieldOrMethodName("fromJsonString", topLevelName); + } + + protected encoderName(topLevelName: Name): Sourcelike { + return this.fieldOrMethodName("toJsonString", topLevelName); + } + + protected readerGetterName(topLevelName: Name): Sourcelike { + return this.methodName("get", "ObjectReader", topLevelName); + } + + protected writerGetterName(topLevelName: Name): Sourcelike { + return this.methodName("get", "ObjectWriter", topLevelName); + } + + protected startFile(basename: Sourcelike): void { + assert(this._currentFilename === undefined, "Previous file wasn't finished"); + // FIXME: The filenames should actually be Sourcelikes, too + this._currentFilename = `${this.sourcelikeToString(basename)}.java`; + // FIXME: Why is this necessary? + this.ensureBlankLine(); + if (!this._haveEmittedLeadingComments && this.leadingComments !== undefined) { + this.emitComments(this.leadingComments); + this.ensureBlankLine(); + this._haveEmittedLeadingComments = true; + } + } + + protected finishFile(): void { + super.finishFile(defined(this._currentFilename)); + this._currentFilename = undefined; + } + + protected emitPackageAndImports(imports: string[]): void { + this.emitLine("package ", this._options.packageName, ";"); + this.ensureBlankLine(); + for (const pkg of imports) { + this.emitLine("import ", pkg, ";"); + } + } + + protected emitFileHeader(fileName: Sourcelike, imports: string[]): void { + this.startFile(fileName); + this.emitPackageAndImports(imports); + this.ensureBlankLine(); + } + + public emitDescriptionBlock(lines: Sourcelike[]): void { + this.emitCommentLines(lines, { lineStart: " * ", beforeComment: "/**", afterComment: " */" }); + } + + public emitBlock(line: Sourcelike, f: () => void): void { + this.emitLine(line, " {"); + this.indent(f); + this.emitLine("}"); + } + + public emitTryCatch(main: () => void, handler: () => void, exception = "Exception"): void { + this.emitLine("try {"); + this.indent(main); + this.emitLine("} catch (", exception, " ex) {"); + this.indent(handler); + this.emitLine("}"); + } + + public emitIgnoredTryCatchBlock(f: () => void): void { + this.emitTryCatch(f, () => this.emitLine("// Ignored")); + } + + protected javaType(reference: boolean, t: Type, withIssues = false): Sourcelike { + return matchType( + t, + _anyType => maybeAnnotated(withIssues, anyTypeIssueAnnotation, "Object"), + _nullType => maybeAnnotated(withIssues, nullTypeIssueAnnotation, "Object"), + _boolType => (reference ? "Boolean" : "boolean"), + _integerType => (reference ? "Long" : "long"), + _doubleType => (reference ? "Double" : "double"), + _stringType => "String", + arrayType => { + if (this._options.useList) { + return ["List<", this.javaType(true, arrayType.items, withIssues), ">"]; + } else { + return [this.javaType(false, arrayType.items, withIssues), "[]"]; + } + }, + classType => this.nameForNamedType(classType), + mapType => ["Map"], + enumType => this.nameForNamedType(enumType), + unionType => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) return this.javaType(true, nullable, withIssues); + return this.nameForNamedType(unionType); + }, + transformedStringType => { + if (transformedStringType.kind === "time") { + return this._dateTimeProvider.timeType; + } + + if (transformedStringType.kind === "date") { + return this._dateTimeProvider.dateType; + } + + if (transformedStringType.kind === "date-time") { + return this._dateTimeProvider.dateTimeType; + } + + if (transformedStringType.kind === "uuid") { + return "UUID"; + } + + return "String"; + } + ); + } + + protected javaImport(t: Type): string[] { + return matchType( + t, + _anyType => [], + _nullType => [], + _boolType => [], + _integerType => [], + _doubleType => [], + _stringType => [], + arrayType => { + if (this._options.useList) { + return [...this.javaImport(arrayType.items), "java.util.List"]; + } else { + return [...this.javaImport(arrayType.items)]; + } + }, + _classType => [], + mapType => [...this.javaImport(mapType.values), "java.util.Map"], + _enumType => [], + unionType => { + const imports: string[] = []; + unionType.members.forEach(type => this.javaImport(type).forEach(imp => imports.push(imp))); + return imports; + }, + transformedStringType => { + if (transformedStringType.kind === "time") { + return this._dateTimeProvider.timeImports; + } + + if (transformedStringType.kind === "date") { + return this._dateTimeProvider.dateImports; + } + + if (transformedStringType.kind === "date-time") { + return this._dateTimeProvider.dateTimeImports; + } + + if (transformedStringType.kind === "uuid") { + return ["java.util.UUID"]; + } + + return []; + } + ); + } + + protected javaTypeWithoutGenerics(reference: boolean, t: Type): Sourcelike { + if (t instanceof ArrayType) { + if (this._options.useList) { + return ["List"]; + } else { + return [this.javaTypeWithoutGenerics(false, t.items), "[]"]; + } + } else if (t instanceof MapType) { + return "Map"; + } else if (t instanceof UnionType) { + const nullable = nullableFromUnion(t); + if (nullable !== null) return this.javaTypeWithoutGenerics(true, nullable); + return this.nameForNamedType(t); + } else { + return this.javaType(reference, t); + } + } + + protected emitClassAttributes(_c: ClassType, _className: Name): void { + if (this._options.lombok) { + this.emitLine("@lombok.Data"); + } + } + + protected annotationsForAccessor( + _c: ClassType, + _className: Name, + _propertyName: Name, + _jsonName: string, + _p: ClassProperty, + _isSetter: boolean + ): string[] { + return []; + } + + protected importsForType(t: ClassType | UnionType | EnumType): string[] { + if (t instanceof ClassType) { + return []; + } + + if (t instanceof UnionType) { + return ["java.io.IOException"]; + } + + if (t instanceof EnumType) { + return ["java.io.IOException"]; + } + + return assertNever(t); + } + + protected importsForClass(c: ClassType): string[] { + const imports: string[] = []; + this.forEachClassProperty(c, "none", (_name, _jsonName, p) => { + this.javaImport(p.type).forEach(imp => imports.push(imp)); + }); + imports.sort(); + return [...new Set(imports)]; + } + + protected importsForUnionMembers(u: UnionType): string[] { + const imports: string[] = []; + const [, nonNulls] = removeNullFromUnion(u); + this.forEachUnionMember(u, nonNulls, "none", null, (_fieldName, t) => { + this.javaImport(t).forEach(imp => imports.push(imp)); + }); + imports.sort(); + return [...new Set(imports)]; + } + + protected emitClassDefinition(c: ClassType, className: Name): void { + let imports = [...this.importsForType(c), ...this.importsForClass(c)]; + + this.emitFileHeader(className, imports); + this.emitDescription(this.descriptionForType(c)); + this.emitClassAttributes(c, className); + this.emitBlock(["public class ", className], () => { + this.forEachClassProperty(c, "none", (name, jsonName, p) => { + if (this._options.lombok && this._options.lombokCopyAnnotations) { + const getter = this.annotationsForAccessor(c, className, name, jsonName, p, false); + const setter = this.annotationsForAccessor(c, className, name, jsonName, p, true); + if (getter.length !== 0) { + this.emitLine("@lombok.Getter(onMethod_ = {" + getter.join(", ") + "})"); + } + + if (setter.length !== 0) { + this.emitLine("@lombok.Setter(onMethod_ = {" + setter.join(", ") + "})"); + } + } + + this.emitLine("private ", this.javaType(false, p.type, true), " ", name, ";"); + }); + if (!this._options.lombok) { + this.forEachClassProperty(c, "leading-and-interposing", (name, jsonName, p) => { + this.emitDescription(this.descriptionForClassProperty(c, jsonName)); + const [getterName, setterName] = defined(this._gettersAndSettersForPropertyName.get(name)); + const rendered = this.javaType(false, p.type); + this.annotationsForAccessor(c, className, name, jsonName, p, false).forEach(annotation => + this.emitLine(annotation) + ); + this.emitLine("public ", rendered, " ", getterName, "() { return ", name, "; }"); + this.annotationsForAccessor(c, className, name, jsonName, p, true).forEach(annotation => + this.emitLine(annotation) + ); + this.emitLine("public void ", setterName, "(", rendered, " value) { this.", name, " = value; }"); + }); + } + }); + this.finishFile(); + } + + protected unionField(u: UnionType, t: Type, withIssues = false): { fieldName: Sourcelike; fieldType: Sourcelike } { + const fieldType = this.javaType(true, t, withIssues); + // FIXME: "Value" should be part of the name. + const fieldName = [this.nameForUnionMember(u, t), "Value"]; + return { fieldType, fieldName }; + } + + protected emitUnionAttributes(_u: UnionType, _unionName: Name): void { + // empty + } + + protected emitUnionSerializer(_u: UnionType, _unionName: Name): void { + // empty + } + + protected emitUnionDefinition(u: UnionType, unionName: Name): void { + const imports = [...this.importsForType(u), ...this.importsForUnionMembers(u)]; + + this.emitFileHeader(unionName, imports); + this.emitDescription(this.descriptionForType(u)); + const [, nonNulls] = removeNullFromUnion(u); + + this.emitUnionAttributes(u, unionName); + this.emitBlock(["public class ", unionName], () => { + for (const t of nonNulls) { + const { fieldType, fieldName } = this.unionField(u, t, true); + this.emitLine("public ", fieldType, " ", fieldName, ";"); + } + + this.emitUnionSerializer(u, unionName); + }); + this.finishFile(); + } + + protected emitEnumSerializationAttributes(_e: EnumType): void { + // Empty + } + + protected emitEnumDeserializationAttributes(_e: EnumType): void { + // Empty + } + + protected emitEnumDefinition(e: EnumType, enumName: Name): void { + this.emitFileHeader(enumName, this.importsForType(e)); + this.emitDescription(this.descriptionForType(e)); + const caseNames: Sourcelike[] = []; + this.forEachEnumCase(e, "none", name => { + if (caseNames.length > 0) caseNames.push(", "); + caseNames.push(name); + }); + caseNames.push(";"); + this.emitBlock(["public enum ", enumName], () => { + this.emitLine(caseNames); + this.ensureBlankLine(); + + this.emitEnumSerializationAttributes(e); + this.emitBlock("public String toValue()", () => { + this.emitLine("switch (this) {"); + this.indent(() => { + this.forEachEnumCase(e, "none", (name, jsonName) => { + this.emitLine("case ", name, ': return "', stringEscape(jsonName), '";'); + }); + }); + this.emitLine("}"); + this.emitLine("return null;"); + }); + this.ensureBlankLine(); + + this.emitEnumDeserializationAttributes(e); + this.emitBlock(["public static ", enumName, " forValue(String value) throws IOException"], () => { + this.forEachEnumCase(e, "none", (name, jsonName) => { + this.emitLine('if (value.equals("', stringEscape(jsonName), '")) return ', name, ";"); + }); + this.emitLine('throw new IOException("Cannot deserialize ', enumName, '");'); + }); + }); + this.finishFile(); + } + + protected emitSourceStructure(): void { + this.forEachNamedType( + "leading-and-interposing", + (c: ClassType, n: Name) => this.emitClassDefinition(c, n), + (e, n) => this.emitEnumDefinition(e, n), + (u, n) => this.emitUnionDefinition(u, n) + ); + } +} diff --git a/packages/quicktype-core/src/language/Java/constants.ts b/packages/quicktype-core/src/language/Java/constants.ts new file mode 100644 index 000000000..d1e2f797e --- /dev/null +++ b/packages/quicktype-core/src/language/Java/constants.ts @@ -0,0 +1,69 @@ +export const javaKeywords = [ + "_", // as of release 9, '_' is a keyword, and may not be used as an identifier + "Object", + "Class", + "System", + "Long", + "Double", + "Boolean", + "String", + "List", + "Map", + "UUID", + "Exception", + "IOException", + "Override", + "abstract", + "continue", + "for", + "new", + "switch", + "assert", + "default", + "goto", + "package", + "synchronized", + "boolean", + "do", + "if", + "private", + "this", + "break", + "double", + "implements", + "protected", + "throw", + "byte", + "else", + "import", + "public", + "throws", + "case", + "enum", + "instanceof", + "return", + "transient", + "catch", + "extends", + "int", + "short", + "try", + "char", + "final", + "interface", + "static", + "void", + "class", + "finally", + "long", + "strictfp", + "volatile", + "const", + "float", + "native", + "super", + "while", + "null", + "false", + "true" +] as const; diff --git a/packages/quicktype-core/src/language/Java/index.ts b/packages/quicktype-core/src/language/Java/index.ts new file mode 100644 index 000000000..ea2ba695e --- /dev/null +++ b/packages/quicktype-core/src/language/Java/index.ts @@ -0,0 +1,3 @@ +export { JavaTargetLanguage, javaOptions } from "./language"; +export { JavaRenderer } from "./JavaRenderer"; +export { JacksonRenderer } from "./JavaJacksonRenderer"; diff --git a/packages/quicktype-core/src/language/Java/language.ts b/packages/quicktype-core/src/language/Java/language.ts new file mode 100644 index 000000000..3d22278b5 --- /dev/null +++ b/packages/quicktype-core/src/language/Java/language.ts @@ -0,0 +1,77 @@ +import { type RenderContext } from "../../Renderer"; +import { BooleanOption, EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { AcronymStyleOptions, acronymOption } from "../../support/Acronyms"; +import { TargetLanguage } from "../../TargetLanguage"; +import { type PrimitiveStringTypeKind, type TransformedStringTypeKind } from "../../Type"; +import { type StringTypeMapping } from "../../TypeBuilder"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; + +import { JacksonRenderer } from "./JavaJacksonRenderer"; +import { JavaRenderer } from "./JavaRenderer"; + +export const javaOptions = { + useList: new EnumOption( + "array-type", + "Use T[] or List", + [ + ["array", false], + ["list", true] + ], + "array" + ), + justTypes: new BooleanOption("just-types", "Plain types only", false), + dateTimeProvider: new EnumOption( + "datetime-provider", + "Date time provider type", + [ + ["java8", "java8"], + ["legacy", "legacy"] + ], + "java8" + ), + acronymStyle: acronymOption(AcronymStyleOptions.Pascal), + // FIXME: Do this via a configurable named eventually. + packageName: new StringOption("package", "Generated package name", "NAME", "io.quicktype"), + lombok: new BooleanOption("lombok", "Use lombok", false, "primary"), + lombokCopyAnnotations: new BooleanOption("lombok-copy-annotations", "Copy accessor annotations", true, "secondary") +}; + +export class JavaTargetLanguage extends TargetLanguage { + public constructor() { + super("Java", ["java"], "java"); + } + + protected getOptions(): Array> { + return [ + javaOptions.useList, + javaOptions.justTypes, + javaOptions.dateTimeProvider, + javaOptions.acronymStyle, + javaOptions.packageName, + javaOptions.lombok, + javaOptions.lombokCopyAnnotations + ]; + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): JavaRenderer { + const options = getOptionValues(javaOptions, untypedOptionValues); + if (options.justTypes) { + return new JavaRenderer(this, renderContext, options); + } + + return new JacksonRenderer(this, renderContext, options); + } + + public get stringTypeMapping(): StringTypeMapping { + const mapping: Map = new Map(); + mapping.set("date", "date"); + mapping.set("time", "time"); + mapping.set("date-time", "date-time"); + mapping.set("uuid", "uuid"); + return mapping; + } +} diff --git a/packages/quicktype-core/src/language/Java/utils.ts b/packages/quicktype-core/src/language/Java/utils.ts new file mode 100644 index 000000000..abc461f47 --- /dev/null +++ b/packages/quicktype-core/src/language/Java/utils.ts @@ -0,0 +1,46 @@ +import { + allLowerWordStyle, + allUpperWordStyle, + combineWords, + escapeNonPrintableMapper, + firstUpperWordStyle, + isAscii, + isDigit, + isLetter, + splitIntoWords, + standardUnicodeHexEscape, + utf16ConcatMap, + utf16LegalizeCharacters +} from "../../support/Strings"; + +export const stringEscape = utf16ConcatMap(escapeNonPrintableMapper(isAscii, standardUnicodeHexEscape)); + +function isStartCharacter(codePoint: number): boolean { + if (codePoint === 0x5f) return true; // underscore + return isAscii(codePoint) && isLetter(codePoint); +} + +function isPartCharacter(codePoint: number): boolean { + return isStartCharacter(codePoint) || (isAscii(codePoint) && isDigit(codePoint)); +} + +const legalizeName = utf16LegalizeCharacters(isPartCharacter); + +export function javaNameStyle( + startWithUpper: boolean, + upperUnderscore: boolean, + original: string, + acronymsStyle: (s: string) => string = allUpperWordStyle +): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + upperUnderscore ? allUpperWordStyle : startWithUpper ? firstUpperWordStyle : allLowerWordStyle, + upperUnderscore ? allUpperWordStyle : firstUpperWordStyle, + upperUnderscore || startWithUpper ? allUpperWordStyle : allLowerWordStyle, + acronymsStyle, + upperUnderscore ? "_" : "", + isStartCharacter + ); +} diff --git a/packages/quicktype-core/src/language/JavaScript.ts b/packages/quicktype-core/src/language/JavaScript/JavaScriptRenderer.ts similarity index 84% rename from packages/quicktype-core/src/language/JavaScript.ts rename to packages/quicktype-core/src/language/JavaScript/JavaScriptRenderer.ts index 440502cff..7dfa79b33 100644 --- a/packages/quicktype-core/src/language/JavaScript.ts +++ b/packages/quicktype-core/src/language/JavaScript/JavaScriptRenderer.ts @@ -1,12 +1,12 @@ import { arrayIntercalate } from "collection-utils"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Name, type Namer, funPrefixNamer } from "../Naming"; -import { type RenderContext } from "../Renderer"; -import { BooleanOption, EnumOption, type Option, type OptionValues, getOptionValues } from "../RendererOptions"; -import { type Sourcelike, modifySource } from "../Source"; -import { AcronymStyleOptions, acronymOption, acronymStyle } from "../support/Acronyms"; -import { ConvertersOptions, convertersOption } from "../support/Converters"; +import { ConvenienceRenderer } from "../../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type Sourcelike, modifySource } from "../../Source"; +import { acronymStyle } from "../../support/Acronyms"; +import { ConvertersOptions } from "../../support/Converters"; import { allLowerWordStyle, camelCase, @@ -14,46 +14,16 @@ import { combineWords, firstUpperWordStyle, splitIntoWords, - utf16LegalizeCharacters, utf16StringEscape -} from "../support/Strings"; -import { panic } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; -import { - type ClassProperty, - type ClassType, - type ObjectType, - type PrimitiveStringTypeKind, - type TransformedStringTypeKind, - type Type -} from "../Type"; -import { type StringTypeMapping } from "../TypeBuilder"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; -import { directlyReachableSingleNamedType, matchType } from "../TypeUtils"; - -import { isES3IdentifierPart, isES3IdentifierStart } from "./JavaScriptUnicodeMaps"; - -export const javaScriptOptions = { - acronymStyle: acronymOption(AcronymStyleOptions.Pascal), - runtimeTypecheck: new BooleanOption("runtime-typecheck", "Verify JSON.parse results at runtime", true), - runtimeTypecheckIgnoreUnknownProperties: new BooleanOption( - "runtime-typecheck-ignore-unknown-properties", - "Ignore unknown properties when verifying at runtime", - false, - "secondary" - ), - converters: convertersOption(), - rawType: new EnumOption<"json" | "any">( - "raw-type", - "Type of raw input (json by default)", - [ - ["json", "json"], - ["any", "any"] - ], - "json", - "secondary" - ) -}; +} from "../../support/Strings"; +import { panic } from "../../support/Support"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { type ClassProperty, type ClassType, type ObjectType, type Type } from "../../Type"; +import { directlyReachableSingleNamedType, matchType } from "../../TypeUtils"; + +import { type javaScriptOptions } from "./language"; +import { isES3IdentifierStart } from "./unicodeMaps"; +import { legalizeName } from "./utils"; export interface JavaScriptTypeAnnotations { any: string; @@ -65,44 +35,6 @@ export interface JavaScriptTypeAnnotations { stringArray: string; } -export class JavaScriptTargetLanguage extends TargetLanguage { - public constructor(displayName = "JavaScript", names: string[] = ["javascript", "js", "jsx"], extension = "js") { - super(displayName, names, extension); - } - - protected getOptions(): Array> { - return [ - javaScriptOptions.runtimeTypecheck, - javaScriptOptions.runtimeTypecheckIgnoreUnknownProperties, - javaScriptOptions.acronymStyle, - javaScriptOptions.converters, - javaScriptOptions.rawType - ]; - } - - public get stringTypeMapping(): StringTypeMapping { - const mapping: Map = new Map(); - const dateTimeType = "date-time"; - mapping.set("date", dateTimeType); - mapping.set("date-time", dateTimeType); - return mapping; - } - - public get supportsOptionalClassProperties(): boolean { - return true; - } - - public get supportsFullObjectType(): boolean { - return true; - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): JavaScriptRenderer { - return new JavaScriptRenderer(this, renderContext, getOptionValues(javaScriptOptions, untypedOptionValues)); - } -} - -export const legalizeName = utf16LegalizeCharacters(isES3IdentifierPart); - const identityNamingFunction = funPrefixNamer("properties", s => s); export class JavaScriptRenderer extends ConvenienceRenderer { diff --git a/packages/quicktype-core/src/language/JavaScript/index.ts b/packages/quicktype-core/src/language/JavaScript/index.ts new file mode 100644 index 000000000..12526b3d9 --- /dev/null +++ b/packages/quicktype-core/src/language/JavaScript/index.ts @@ -0,0 +1,2 @@ +export { JavaScriptTargetLanguage, javaScriptOptions } from "./language"; +export { JavaScriptRenderer, type JavaScriptTypeAnnotations } from "./JavaScriptRenderer"; diff --git a/packages/quicktype-core/src/language/JavaScript/language.ts b/packages/quicktype-core/src/language/JavaScript/language.ts new file mode 100644 index 000000000..85d61bbb6 --- /dev/null +++ b/packages/quicktype-core/src/language/JavaScript/language.ts @@ -0,0 +1,68 @@ +import { type RenderContext } from "../../Renderer"; +import { BooleanOption, EnumOption, type Option, getOptionValues } from "../../RendererOptions"; +import { AcronymStyleOptions, acronymOption } from "../../support/Acronyms"; +import { convertersOption } from "../../support/Converters"; +import { TargetLanguage } from "../../TargetLanguage"; +import { type PrimitiveStringTypeKind, type TransformedStringTypeKind } from "../../Type"; +import { type StringTypeMapping } from "../../TypeBuilder"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; + +import { JavaScriptRenderer } from "./JavaScriptRenderer"; + +export const javaScriptOptions = { + acronymStyle: acronymOption(AcronymStyleOptions.Pascal), + runtimeTypecheck: new BooleanOption("runtime-typecheck", "Verify JSON.parse results at runtime", true), + runtimeTypecheckIgnoreUnknownProperties: new BooleanOption( + "runtime-typecheck-ignore-unknown-properties", + "Ignore unknown properties when verifying at runtime", + false, + "secondary" + ), + converters: convertersOption(), + rawType: new EnumOption<"json" | "any">( + "raw-type", + "Type of raw input (json by default)", + [ + ["json", "json"], + ["any", "any"] + ], + "json", + "secondary" + ) +}; + +export class JavaScriptTargetLanguage extends TargetLanguage { + public constructor(displayName = "JavaScript", names: string[] = ["javascript", "js", "jsx"], extension = "js") { + super(displayName, names, extension); + } + + protected getOptions(): Array> { + return [ + javaScriptOptions.runtimeTypecheck, + javaScriptOptions.runtimeTypecheckIgnoreUnknownProperties, + javaScriptOptions.acronymStyle, + javaScriptOptions.converters, + javaScriptOptions.rawType + ]; + } + + public get stringTypeMapping(): StringTypeMapping { + const mapping: Map = new Map(); + const dateTimeType = "date-time"; + mapping.set("date", dateTimeType); + mapping.set("date-time", dateTimeType); + return mapping; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + public get supportsFullObjectType(): boolean { + return true; + } + + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): JavaScriptRenderer { + return new JavaScriptRenderer(this, renderContext, getOptionValues(javaScriptOptions, untypedOptionValues)); + } +} diff --git a/packages/quicktype-core/src/language/JavaScriptUnicodeMaps.ts b/packages/quicktype-core/src/language/JavaScript/unicodeMaps.ts similarity index 100% rename from packages/quicktype-core/src/language/JavaScriptUnicodeMaps.ts rename to packages/quicktype-core/src/language/JavaScript/unicodeMaps.ts diff --git a/packages/quicktype-core/src/language/JavaScript/utils.ts b/packages/quicktype-core/src/language/JavaScript/utils.ts new file mode 100644 index 000000000..7acc4c931 --- /dev/null +++ b/packages/quicktype-core/src/language/JavaScript/utils.ts @@ -0,0 +1,5 @@ +import { utf16LegalizeCharacters } from "../../support/Strings"; + +import { isES3IdentifierPart } from "./unicodeMaps"; + +export const legalizeName = utf16LegalizeCharacters(isES3IdentifierPart); diff --git a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts b/packages/quicktype-core/src/language/JavaScriptPropTypes/JavaScriptPropTypesRenderer.ts similarity index 80% rename from packages/quicktype-core/src/language/JavaScriptPropTypes.ts rename to packages/quicktype-core/src/language/JavaScriptPropTypes/JavaScriptPropTypesRenderer.ts index 6754e83e2..7c7fe659e 100644 --- a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts +++ b/packages/quicktype-core/src/language/JavaScriptPropTypes/JavaScriptPropTypesRenderer.ts @@ -1,13 +1,11 @@ -import { panic } from "@glideapps/ts-necessities"; import { arrayIntercalate } from "collection-utils"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Name, type Namer, funPrefixNamer } from "../Naming"; -import { type RenderContext } from "../Renderer"; -import { EnumOption, type Option, type OptionValues, getOptionValues } from "../RendererOptions"; -import { type Sourcelike } from "../Source"; -import { AcronymStyleOptions, acronymOption, acronymStyle } from "../support/Acronyms"; -import { convertersOption } from "../support/Converters"; +import { ConvenienceRenderer } from "../../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type Sourcelike } from "../../Source"; +import { acronymStyle } from "../../support/Acronyms"; import { allLowerWordStyle, capitalize, @@ -15,53 +13,22 @@ import { firstUpperWordStyle, splitIntoWords, utf16StringEscape -} from "../support/Strings"; -import { TargetLanguage } from "../TargetLanguage"; -import { type ArrayType, type ClassProperty, type ClassType, type ObjectType, PrimitiveType, type Type } from "../Type"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; -import { directlyReachableSingleNamedType, matchType } from "../TypeUtils"; - -import { legalizeName } from "./JavaScript"; -import { isES3IdentifierStart } from "./JavaScriptUnicodeMaps"; - -export const javaScriptPropTypesOptions = { - acronymStyle: acronymOption(AcronymStyleOptions.Pascal), - converters: convertersOption(), - moduleSystem: new EnumOption( - "module-system", - "Which module system to use", - [ - ["common-js", false], - ["es6", true] - ], - "es6" - ) -}; - -export class JavaScriptPropTypesTargetLanguage extends TargetLanguage { - protected getOptions(): Array> { - return [javaScriptPropTypesOptions.acronymStyle, javaScriptPropTypesOptions.converters]; - } - - public constructor( - displayName = "JavaScript PropTypes", - names: string[] = ["javascript-prop-types"], - extension = "js" - ) { - super(displayName, names, extension); - } - - protected makeRenderer( - renderContext: RenderContext, - untypedOptionValues: FixMeOptionsType - ): JavaScriptPropTypesRenderer { - return new JavaScriptPropTypesRenderer( - this, - renderContext, - getOptionValues(javaScriptPropTypesOptions, untypedOptionValues) - ); - } -} +} from "../../support/Strings"; +import { panic } from "../../support/Support"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { + type ArrayType, + type ClassProperty, + type ClassType, + type ObjectType, + PrimitiveType, + type Type +} from "../../Type"; +import { directlyReachableSingleNamedType, matchType } from "../../TypeUtils"; +import { isES3IdentifierStart } from "../JavaScript/unicodeMaps"; +import { legalizeName } from "../JavaScript/utils"; + +import { type javaScriptPropTypesOptions } from "./language"; const identityNamingFunction = funPrefixNamer("properties", s => s); diff --git a/packages/quicktype-core/src/language/JavaScriptPropTypes/index.ts b/packages/quicktype-core/src/language/JavaScriptPropTypes/index.ts new file mode 100644 index 000000000..273e81878 --- /dev/null +++ b/packages/quicktype-core/src/language/JavaScriptPropTypes/index.ts @@ -0,0 +1,2 @@ +export { JavaScriptPropTypesTargetLanguage, javaScriptPropTypesOptions } from "./language"; +export { JavaScriptPropTypesRenderer } from "./JavaScriptPropTypesRenderer"; diff --git a/packages/quicktype-core/src/language/JavaScriptPropTypes/language.ts b/packages/quicktype-core/src/language/JavaScriptPropTypes/language.ts new file mode 100644 index 000000000..8ba620927 --- /dev/null +++ b/packages/quicktype-core/src/language/JavaScriptPropTypes/language.ts @@ -0,0 +1,47 @@ +import { type RenderContext } from "../../Renderer"; +import { EnumOption, type Option, getOptionValues } from "../../RendererOptions"; +import { AcronymStyleOptions, acronymOption } from "../../support/Acronyms"; +import { convertersOption } from "../../support/Converters"; +import { TargetLanguage } from "../../TargetLanguage"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; + +import { JavaScriptPropTypesRenderer } from "./JavaScriptPropTypesRenderer"; + +export const javaScriptPropTypesOptions = { + acronymStyle: acronymOption(AcronymStyleOptions.Pascal), + converters: convertersOption(), + moduleSystem: new EnumOption( + "module-system", + "Which module system to use", + [ + ["common-js", false], + ["es6", true] + ], + "es6" + ) +}; + +export class JavaScriptPropTypesTargetLanguage extends TargetLanguage { + protected getOptions(): Array> { + return [javaScriptPropTypesOptions.acronymStyle, javaScriptPropTypesOptions.converters]; + } + + public constructor( + displayName = "JavaScript PropTypes", + names: string[] = ["javascript-prop-types"], + extension = "js" + ) { + super(displayName, names, extension); + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: FixMeOptionsType + ): JavaScriptPropTypesRenderer { + return new JavaScriptPropTypesRenderer( + this, + renderContext, + getOptionValues(javaScriptPropTypesOptions, untypedOptionValues) + ); + } +} diff --git a/packages/quicktype-core/src/language/Kotlin.ts b/packages/quicktype-core/src/language/Kotlin.ts deleted file mode 100644 index d2f759506..000000000 --- a/packages/quicktype-core/src/language/Kotlin.ts +++ /dev/null @@ -1,1129 +0,0 @@ -import { arrayIntercalate, iterableSome } from "collection-utils"; - -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { type Name, type Namer, funPrefixNamer } from "../Naming"; -import { type RenderContext } from "../Renderer"; -import { EnumOption, type Option, type OptionValues, StringOption, getOptionValues } from "../RendererOptions"; -import { type Sourcelike, maybeAnnotated, modifySource } from "../Source"; -import { AcronymStyleOptions, acronymOption, acronymStyle } from "../support/Acronyms"; -import { - allLowerWordStyle, - allUpperWordStyle, - camelCase, - combineWords, - escapeNonPrintableMapper, - firstUpperWordStyle, - intToHex, - isDigit, - isLetterOrUnderscore, - isNumeric, - isPrintable, - legalizeCharacters, - splitIntoWords, - utf32ConcatMap -} from "../support/Strings"; -import { assertNever, mustNotHappen } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; -import { - ArrayType, - type ClassProperty, - ClassType, - type EnumType, - MapType, - type ObjectType, - type PrimitiveType, - type Type, - UnionType -} from "../Type"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; -import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; - -export enum Framework { - None = "None", - Jackson = "Jackson", - Klaxon = "Klaxon", - KotlinX = "KotlinX" -} - -export const kotlinOptions = { - framework: new EnumOption( - "framework", - "Serialization framework", - [ - ["just-types", Framework.None], - ["jackson", Framework.Jackson], - ["klaxon", Framework.Klaxon], - ["kotlinx", Framework.KotlinX] - ], - "klaxon" - ), - acronymStyle: acronymOption(AcronymStyleOptions.Pascal), - packageName: new StringOption("package", "Package", "PACKAGE", "quicktype") -}; - -export class KotlinTargetLanguage extends TargetLanguage { - public constructor() { - super("Kotlin", ["kotlin"], "kt"); - } - - protected getOptions(): Array> { - return [kotlinOptions.framework, kotlinOptions.acronymStyle, kotlinOptions.packageName]; - } - - public get supportsOptionalClassProperties(): boolean { - return true; - } - - public get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): ConvenienceRenderer { - const options = getOptionValues(kotlinOptions, untypedOptionValues); - - switch (options.framework) { - case Framework.None: - return new KotlinRenderer(this, renderContext, options); - case Framework.Jackson: - return new KotlinJacksonRenderer(this, renderContext, options); - case Framework.Klaxon: - return new KotlinKlaxonRenderer(this, renderContext, options); - case Framework.KotlinX: - return new KotlinXRenderer(this, renderContext, options); - default: - return assertNever(options.framework); - } - } -} - -const keywords = [ - "package", - "as", - "typealias", - "class", - "this", - "super", - "val", - "var", - "fun", - "for", - "null", - "true", - "false", - "is", - "in", - "throw", - "return", - "break", - "continue", - "object", - "if", - "try", - "else", - "while", - "do", - "when", - "interface", - "typeof", - "klaxon", - "toJson", - "Any", - "Boolean", - "Double", - "Float", - "Long", - "Int", - "Short", - "System", - "Byte", - "String", - "Array", - "List", - "Map", - "Enum", - "Class", - "JsonObject", - "JsonValue", - "Converter", - "Klaxon" -]; - -function isPartCharacter(codePoint: number): boolean { - return isLetterOrUnderscore(codePoint) || isNumeric(codePoint); -} - -function isStartCharacter(codePoint: number): boolean { - return isPartCharacter(codePoint) && !isDigit(codePoint); -} - -const legalizeName = legalizeCharacters(isPartCharacter); - -function kotlinNameStyle( - isUpper: boolean, - original: string, - acronymsStyle: (s: string) => string = allUpperWordStyle -): string { - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - isUpper ? firstUpperWordStyle : allLowerWordStyle, - firstUpperWordStyle, - isUpper ? allUpperWordStyle : allLowerWordStyle, - acronymsStyle, - "", - isStartCharacter - ); -} - -function unicodeEscape(codePoint: number): string { - return "\\u" + intToHex(codePoint, 4); -} - -// eslint-disable-next-line @typescript-eslint/naming-convention -const _stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, unicodeEscape)); - -function stringEscape(s: string): string { - // "$this" is a template string in Kotlin so we have to escape $ - return _stringEscape(s).replace(/\$/g, "\\$"); -} - -export class KotlinRenderer extends ConvenienceRenderer { - public constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - protected readonly _kotlinOptions: OptionValues - ) { - super(targetLanguage, renderContext); - } - - protected forbiddenNamesForGlobalNamespace(): string[] { - return keywords; - } - - protected forbiddenForObjectProperties(_o: ObjectType, _classNamed: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: true }; - } - - protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: true }; - } - - protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: false }; - } - - protected topLevelNameStyle(rawName: string): string { - return kotlinNameStyle(true, rawName); - } - - protected makeNamedTypeNamer(): Namer { - return funPrefixNamer("upper", s => kotlinNameStyle(true, s, acronymStyle(this._kotlinOptions.acronymStyle))); - } - - protected namerForObjectProperty(): Namer { - return funPrefixNamer("lower", s => kotlinNameStyle(false, s, acronymStyle(this._kotlinOptions.acronymStyle))); - } - - protected makeUnionMemberNamer(): Namer { - return funPrefixNamer("upper", s => kotlinNameStyle(true, s) + "Value"); - } - - protected makeEnumCaseNamer(): Namer { - return funPrefixNamer("upper", s => kotlinNameStyle(true, s, acronymStyle(this._kotlinOptions.acronymStyle))); - } - - protected emitDescriptionBlock(lines: Sourcelike[]): void { - this.emitCommentLines(lines, { lineStart: " * ", beforeComment: "/**", afterComment: " */" }); - } - - protected emitBlock(line: Sourcelike, f: () => void, delimiter: "curly" | "paren" | "lambda" = "curly"): void { - const [open, close] = delimiter === "curly" ? ["{", "}"] : delimiter === "paren" ? ["(", ")"] : ["{", "})"]; - this.emitLine(line, " ", open); - this.indent(f); - this.emitLine(close); - } - - protected anySourceType(optional: string): Sourcelike { - return ["Any", optional]; - } - - // (asarazan): I've broken out the following two functions - // because some renderers, such as kotlinx, can cope with `any`, while some get mad. - protected arrayType(arrayType: ArrayType, withIssues = false, _noOptional = false): Sourcelike { - return ["List<", this.kotlinType(arrayType.items, withIssues), ">"]; - } - - protected mapType(mapType: MapType, withIssues = false, _noOptional = false): Sourcelike { - return ["Map"]; - } - - protected kotlinType(t: Type, withIssues = false, noOptional = false): Sourcelike { - const optional = noOptional ? "" : "?"; - return matchType( - t, - _anyType => { - return maybeAnnotated(withIssues, anyTypeIssueAnnotation, this.anySourceType(optional)); - }, - _nullType => { - return maybeAnnotated(withIssues, nullTypeIssueAnnotation, this.anySourceType(optional)); - }, - _boolType => "Boolean", - _integerType => "Long", - _doubleType => "Double", - _stringType => "String", - arrayType => this.arrayType(arrayType, withIssues), - classType => this.nameForNamedType(classType), - mapType => this.mapType(mapType, withIssues), - enumType => this.nameForNamedType(enumType), - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) return [this.kotlinType(nullable, withIssues), optional]; - return this.nameForNamedType(unionType); - } - ); - } - - protected emitUsageHeader(): void { - // To be overridden - } - - protected emitHeader(): void { - if (this.leadingComments !== undefined) { - this.emitComments(this.leadingComments); - } else { - this.emitUsageHeader(); - } - - this.ensureBlankLine(); - this.emitLine("package ", this._kotlinOptions.packageName); - this.ensureBlankLine(); - } - - protected emitTopLevelPrimitive(t: PrimitiveType, name: Name): void { - const elementType = this.kotlinType(t); - this.emitLine(["typealias ", name, " = ", elementType, ""]); - } - - protected emitTopLevelArray(t: ArrayType, name: Name): void { - const elementType = this.kotlinType(t.items); - this.emitLine(["typealias ", name, " = ArrayList<", elementType, ">"]); - } - - protected emitTopLevelMap(t: MapType, name: Name): void { - const elementType = this.kotlinType(t.values); - this.emitLine(["typealias ", name, " = HashMap"]); - } - - protected emitEmptyClassDefinition(c: ClassType, className: Name): void { - this.emitDescription(this.descriptionForType(c)); - this.emitClassAnnotations(c, className); - this.emitLine("class ", className, "()"); - } - - protected emitClassDefinition(c: ClassType, className: Name): void { - if (c.getProperties().size === 0) { - this.emitEmptyClassDefinition(c, className); - return; - } - - const kotlinType = (p: ClassProperty): Sourcelike => { - if (p.isOptional) { - return [this.kotlinType(p.type, true, true), "?"]; - } else { - return this.kotlinType(p.type, true); - } - }; - - this.emitDescription(this.descriptionForType(c)); - this.emitClassAnnotations(c, className); - this.emitLine("data class ", className, " ("); - this.indent(() => { - let count = c.getProperties().size; - let first = true; - this.forEachClassProperty(c, "none", (name, jsonName, p) => { - const nullable = p.type.kind === "union" && nullableFromUnion(p.type as UnionType) !== null; - const nullableOrOptional = p.isOptional || p.type.kind === "null" || nullable; - const last = --count === 0; - let meta: Array<() => void> = []; - - const description = this.descriptionForClassProperty(c, jsonName); - if (description !== undefined) { - meta.push(() => this.emitDescription(description)); - } - - this.renameAttribute(name, jsonName, !nullableOrOptional, meta); - - if (meta.length > 0 && !first) { - this.ensureBlankLine(); - } - - for (const emit of meta) { - emit(); - } - - this.emitLine("val ", name, ": ", kotlinType(p), nullableOrOptional ? " = null" : "", last ? "" : ","); - - if (meta.length > 0 && !last) { - this.ensureBlankLine(); - } - - first = false; - }); - }); - - this.emitClassDefinitionMethods(c, className); - } - - protected emitClassDefinitionMethods(_c: ClassType, _className: Name): void { - this.emitLine(")"); - } - - protected emitClassAnnotations(_c: Type, _className: Name): void { - // to be overridden - } - - protected renameAttribute(_name: Name, _jsonName: string, _required: boolean, _meta: Array<() => void>): void { - // to be overridden - } - - protected emitEnumDefinition(e: EnumType, enumName: Name): void { - this.emitDescription(this.descriptionForType(e)); - - this.emitBlock(["enum class ", enumName], () => { - let count = e.cases.size; - this.forEachEnumCase(e, "none", name => { - this.emitLine(name, --count === 0 ? "" : ","); - }); - }); - } - - protected emitUnionDefinition(u: UnionType, unionName: Name): void { - function sortBy(t: Type): string { - const kind = t.kind; - if (kind === "class") return kind; - return "_" + kind; - } - - this.emitDescription(this.descriptionForType(u)); - - const [maybeNull, nonNulls] = removeNullFromUnion(u, sortBy); - this.emitClassAnnotations(u, unionName); - this.emitBlock(["sealed class ", unionName], () => { - { - let table: Sourcelike[][] = []; - this.forEachUnionMember(u, nonNulls, "none", null, (name, t) => { - table.push([ - ["class ", name, "(val value: ", this.kotlinType(t), ")"], - [" : ", unionName, "()"] - ]); - }); - if (maybeNull !== null) { - table.push([ - ["class ", this.nameForUnionMember(u, maybeNull), "()"], - [" : ", unionName, "()"] - ]); - } - - this.emitTable(table); - } - - this.emitUnionDefinitionMethods(u, nonNulls, maybeNull, unionName); - }); - } - - protected emitUnionDefinitionMethods( - _u: UnionType, - _nonNulls: ReadonlySet, - _maybeNull: PrimitiveType | null, - _unionName: Name - ): void { - // to be overridden - } - - protected emitSourceStructure(): void { - this.emitHeader(); - - // Top-level arrays, maps - this.forEachTopLevel("leading", (t, name) => { - if (t instanceof ArrayType) { - this.emitTopLevelArray(t, name); - } else if (t instanceof MapType) { - this.emitTopLevelMap(t, name); - } else if (t.isPrimitive()) { - this.emitTopLevelPrimitive(t, name); - } - }); - - this.forEachNamedType( - "leading-and-interposing", - (c: ClassType, n: Name) => this.emitClassDefinition(c, n), - (e, n) => this.emitEnumDefinition(e, n), - (u, n) => this.emitUnionDefinition(u, n) - ); - } -} - -export class KotlinKlaxonRenderer extends KotlinRenderer { - public constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - _kotlinOptions: OptionValues - ) { - super(targetLanguage, renderContext, _kotlinOptions); - } - - private unionMemberFromJsonValue(t: Type, e: Sourcelike): Sourcelike { - return matchType( - t, - _anyType => [e, ".inside"], - _nullType => "null", - _boolType => [e, ".boolean"], - _integerType => ["(", e, ".int?.toLong() ?: ", e, ".longValue)"], - _doubleType => [e, ".double"], - _stringType => [e, ".string"], - arrayType => [e, ".array?.let { klaxon.parseFromJsonArray<", this.kotlinType(arrayType.items), ">(it) }"], - _classType => [e, ".obj?.let { klaxon.parseFromJsonObject<", this.kotlinType(t), ">(it) }"], - _mapType => [e, ".obj?.let { klaxon.parseFromJsonObject<", this.kotlinType(t), ">(it) }"], - enumType => [e, ".string?.let { ", this.kotlinType(enumType), ".fromValue(it) }"], - _unionType => mustNotHappen() - ); - } - - private unionMemberJsonValueGuard(t: Type, _e: Sourcelike): Sourcelike { - return matchType( - t, - _anyType => "is Any", - _nullType => "null", - _boolType => "is Boolean", - _integerType => "is Int, is Long", - _doubleType => "is Double", - _stringType => "is String", - _arrayType => "is JsonArray<*>", - // These could be stricter, but for now we don't allow maps - // and objects in the same union - _classType => "is JsonObject", - _mapType => "is JsonObject", - // This could be stricter, but for now we don't allow strings - // and enums in the same union - _enumType => "is String", - _unionType => mustNotHappen() - ); - } - - protected emitUsageHeader(): void { - this.emitLine("// To parse the JSON, install Klaxon and do:"); - this.emitLine("//"); - this.forEachTopLevel("none", (_, name) => { - this.emitLine("// val ", modifySource(camelCase, name), " = ", name, ".fromJson(jsonString)"); - }); - } - - protected emitHeader(): void { - super.emitHeader(); - - this.emitLine("import com.beust.klaxon.*"); - - const hasUnions = iterableSome( - this.typeGraph.allNamedTypes(), - t => t instanceof UnionType && nullableFromUnion(t) === null - ); - const hasEmptyObjects = iterableSome( - this.typeGraph.allNamedTypes(), - c => c instanceof ClassType && c.getProperties().size === 0 - ); - if (hasUnions || this.haveEnums || hasEmptyObjects) { - this.emitGenericConverter(); - } - - let converters: Sourcelike[][] = []; - if (hasEmptyObjects) { - converters.push([[".convert(JsonObject::class,"], [" { it.obj!! },"], [" { it.toJsonString() })"]]); - } - - this.forEachEnum("none", (_, name) => { - converters.push([ - [".convert(", name, "::class,"], - [" { ", name, ".fromValue(it.string!!) },"], - [' { "\\"${it.value}\\"" })'] - ]); - }); - this.forEachUnion("none", (_, name) => { - converters.push([ - [".convert(", name, "::class,"], - [" { ", name, ".fromJson(it) },"], - [" { it.toJson() }, true)"] - ]); - }); - - this.ensureBlankLine(); - this.emitLine("private val klaxon = Klaxon()"); - if (converters.length > 0) { - this.indent(() => this.emitTable(converters)); - } - } - - protected emitTopLevelArray(t: ArrayType, name: Name): void { - const elementType = this.kotlinType(t.items); - this.emitBlock( - ["class ", name, "(elements: Collection<", elementType, ">) : ArrayList<", elementType, ">(elements)"], - () => { - this.emitLine("public fun toJson() = klaxon.toJsonString(this)"); - this.ensureBlankLine(); - this.emitBlock("companion object", () => { - this.emitLine( - "public fun fromJson(json: String) = ", - name, - "(klaxon.parseArray<", - elementType, - ">(json)!!)" - ); - }); - } - ); - } - - protected emitTopLevelMap(t: MapType, name: Name): void { - const elementType = this.kotlinType(t.values); - this.emitBlock( - [ - "class ", - name, - "(elements: Map) : HashMap(elements)" - ], - () => { - this.emitLine("public fun toJson() = klaxon.toJsonString(this)"); - this.ensureBlankLine(); - this.emitBlock("companion object", () => { - this.emitBlock( - ["public fun fromJson(json: String) = ", name], - () => { - this.emitLine( - "klaxon.parseJsonObject(java.io.StringReader(json)) as Map" - ); - }, - "paren" - ); - }); - } - ); - } - - private klaxonRenameAttribute(propName: Name, jsonName: string, ignore = false): Sourcelike | undefined { - const escapedName = stringEscape(jsonName); - const namesDiffer = this.sourcelikeToString(propName) !== escapedName; - const properties: Sourcelike[] = []; - if (namesDiffer) { - properties.push(['name = "', escapedName, '"']); - } - - if (ignore) { - properties.push("ignored = true"); - } - - return properties.length === 0 ? undefined : ["@Json(", arrayIntercalate(", ", properties), ")"]; - } - - protected emitEmptyClassDefinition(c: ClassType, className: Name): void { - this.emitDescription(this.descriptionForType(c)); - - this.emitLine("typealias ", className, " = JsonObject"); - } - - protected emitClassDefinitionMethods(c: ClassType, className: Name): void { - const isTopLevel = iterableSome(this.topLevels, ([_, top]) => top === c); - if (isTopLevel) { - this.emitBlock(")", () => { - this.emitLine("public fun toJson() = klaxon.toJsonString(this)"); - this.ensureBlankLine(); - this.emitBlock("companion object", () => { - this.emitLine("public fun fromJson(json: String) = klaxon.parse<", className, ">(json)"); - }); - }); - } else { - this.emitLine(")"); - } - } - - protected renameAttribute(name: Name, jsonName: string, _required: boolean, meta: Array<() => void>): void { - const rename = this.klaxonRenameAttribute(name, jsonName); - if (rename !== undefined) { - meta.push(() => this.emitLine(rename)); - } - } - - protected emitEnumDefinition(e: EnumType, enumName: Name): void { - this.emitDescription(this.descriptionForType(e)); - - this.emitBlock(["enum class ", enumName, "(val value: String)"], () => { - let count = e.cases.size; - this.forEachEnumCase(e, "none", (name, json) => { - this.emitLine(name, `("${stringEscape(json)}")`, --count === 0 ? ";" : ","); - }); - this.ensureBlankLine(); - this.emitBlock("companion object", () => { - this.emitBlock(["public fun fromValue(value: String): ", enumName, " = when (value)"], () => { - let table: Sourcelike[][] = []; - this.forEachEnumCase(e, "none", (name, json) => { - table.push([[`"${stringEscape(json)}"`], [" -> ", name]]); - }); - table.push([["else"], [" -> throw IllegalArgumentException()"]]); - this.emitTable(table); - }); - }); - }); - } - - private emitGenericConverter(): void { - this.ensureBlankLine(); - this.emitLine( - "private fun Klaxon.convert(k: kotlin.reflect.KClass<*>, fromJson: (JsonValue) -> T, toJson: (T) -> String, isUnion: Boolean = false) =" - ); - this.indent(() => { - this.emitLine("this.converter(object: Converter {"); - this.indent(() => { - this.emitLine('@Suppress("UNCHECKED_CAST")'); - this.emitTable([ - ["override fun toJson(value: Any)", " = toJson(value as T)"], - ["override fun fromJson(jv: JsonValue)", " = fromJson(jv) as Any"], - [ - "override fun canConvert(cls: Class<*>)", - " = cls == k.java || (isUnion && cls.superclass == k.java)" - ] - ]); - }); - this.emitLine("})"); - }); - } - - protected emitUnionDefinitionMethods( - u: UnionType, - nonNulls: ReadonlySet, - maybeNull: PrimitiveType | null, - unionName: Name - ): void { - this.ensureBlankLine(); - this.emitLine("public fun toJson(): String = klaxon.toJsonString(when (this) {"); - this.indent(() => { - let toJsonTable: Sourcelike[][] = []; - this.forEachUnionMember(u, nonNulls, "none", null, name => { - toJsonTable.push([["is ", name], [" -> this.value"]]); - }); - if (maybeNull !== null) { - const name = this.nameForUnionMember(u, maybeNull); - toJsonTable.push([["is ", name], [' -> "null"']]); - } - - this.emitTable(toJsonTable); - }); - this.emitLine("})"); - this.ensureBlankLine(); - this.emitBlock("companion object", () => { - this.emitLine("public fun fromJson(jv: JsonValue): ", unionName, " = when (jv.inside) {"); - this.indent(() => { - let table: Sourcelike[][] = []; - this.forEachUnionMember(u, nonNulls, "none", null, (name, t) => { - table.push([ - [this.unionMemberJsonValueGuard(t, "jv.inside")], - [" -> ", name, "(", this.unionMemberFromJsonValue(t, "jv"), "!!)"] - ]); - }); - if (maybeNull !== null) { - const name = this.nameForUnionMember(u, maybeNull); - table.push([[this.unionMemberJsonValueGuard(maybeNull, "jv.inside")], [" -> ", name, "()"]]); - } - - table.push([["else"], [" -> throw IllegalArgumentException()"]]); - this.emitTable(table); - }); - this.emitLine("}"); - }); - } -} - -export class KotlinJacksonRenderer extends KotlinRenderer { - public constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - _kotlinOptions: OptionValues - ) { - super(targetLanguage, renderContext, _kotlinOptions); - } - - private unionMemberJsonValueGuard(t: Type, _e: Sourcelike): Sourcelike { - return matchType( - t, - _anyType => "is Any", - _nullType => "null", - _boolType => "is BooleanNode", - _integerType => "is IntNode, is LongNode", - _doubleType => "is DoubleNode", - _stringType => "is TextNode", - _arrayType => "is ArrayNode", - // These could be stricter, but for now we don't allow maps - // and objects in the same union - _classType => "is ObjectNode", - _mapType => "is ObjectNode", - // This could be stricter, but for now we don't allow strings - // and enums in the same union - _enumType => "is TextNode", - _unionType => mustNotHappen() - ); - } - - protected emitUsageHeader(): void { - this.emitLine("// To parse the JSON, install jackson-module-kotlin and do:"); - this.emitLine("//"); - this.forEachTopLevel("none", (_, name) => { - this.emitLine("// val ", modifySource(camelCase, name), " = ", name, ".fromJson(jsonString)"); - }); - } - - protected emitHeader(): void { - super.emitHeader(); - - this.emitMultiline(`import com.fasterxml.jackson.annotation.* -import com.fasterxml.jackson.core.* -import com.fasterxml.jackson.databind.* -import com.fasterxml.jackson.databind.deser.std.StdDeserializer -import com.fasterxml.jackson.databind.module.SimpleModule -import com.fasterxml.jackson.databind.node.* -import com.fasterxml.jackson.databind.ser.std.StdSerializer -import com.fasterxml.jackson.module.kotlin.*`); - - const hasUnions = iterableSome( - this.typeGraph.allNamedTypes(), - t => t instanceof UnionType && nullableFromUnion(t) === null - ); - const hasEmptyObjects = iterableSome( - this.typeGraph.allNamedTypes(), - c => c instanceof ClassType && c.getProperties().size === 0 - ); - if (hasUnions || this.haveEnums || hasEmptyObjects) { - this.emitGenericConverter(); - } - - let converters: Sourcelike[][] = []; - // if (hasEmptyObjects) { - // converters.push([["convert(JsonNode::class,"], [" { it },"], [" { writeValueAsString(it) })"]]); - // } - this.forEachEnum("none", (_, name) => { - converters.push([ - ["convert(", name, "::class,"], - [" { ", name, ".fromValue(it.asText()) },"], - [' { "\\"${it.value}\\"" })'] - ]); - }); - this.forEachUnion("none", (_, name) => { - converters.push([ - ["convert(", name, "::class,"], - [" { ", name, ".fromJson(it) },"], - [" { it.toJson() }, true)"] - ]); - }); - - this.ensureBlankLine(); - this.emitLine("val mapper = jacksonObjectMapper().apply {"); - this.indent(() => { - this.emitLine("propertyNamingStrategy = PropertyNamingStrategy.LOWER_CAMEL_CASE"); - this.emitLine("setSerializationInclusion(JsonInclude.Include.NON_NULL)"); - }); - - if (converters.length > 0) { - this.indent(() => this.emitTable(converters)); - } - - this.emitLine("}"); - } - - protected emitTopLevelArray(t: ArrayType, name: Name): void { - const elementType = this.kotlinType(t.items); - this.emitBlock( - ["class ", name, "(elements: Collection<", elementType, ">) : ArrayList<", elementType, ">(elements)"], - () => { - this.emitLine("fun toJson() = mapper.writeValueAsString(this)"); - this.ensureBlankLine(); - this.emitBlock("companion object", () => { - this.emitLine("fun fromJson(json: String) = mapper.readValue<", name, ">(json)"); - }); - } - ); - } - - protected emitTopLevelMap(t: MapType, name: Name): void { - const elementType = this.kotlinType(t.values); - this.emitBlock( - [ - "class ", - name, - "(elements: Map) : HashMap(elements)" - ], - () => { - this.emitLine("fun toJson() = mapper.writeValueAsString(this)"); - this.ensureBlankLine(); - this.emitBlock("companion object", () => { - this.emitLine("fun fromJson(json: String) = mapper.readValue<", name, ">(json)"); - }); - } - ); - } - - private jacksonRenameAttribute( - propName: Name, - jsonName: string, - required: boolean, - ignore = false - ): Sourcelike | undefined { - const escapedName = stringEscape(jsonName); - const namesDiffer = this.sourcelikeToString(propName) !== escapedName; - const properties: Sourcelike[] = []; - const isPrefixBool = jsonName.startsWith("is"); // https://github.com/FasterXML/jackson-module-kotlin/issues/80 - const propertyOpts: Sourcelike[] = []; - - if (namesDiffer || isPrefixBool) { - propertyOpts.push('"' + escapedName + '"'); - } - - if (required) { - propertyOpts.push("required=true"); - } - - if (propertyOpts.length > 0) { - properties.push(["@get:JsonProperty(", arrayIntercalate(", ", propertyOpts), ")"]); - properties.push(["@field:JsonProperty(", arrayIntercalate(", ", propertyOpts), ")"]); - } - - if (ignore) { - properties.push("@get:JsonIgnore"); - properties.push("@field:JsonIgnore"); - } - - return properties.length === 0 ? undefined : properties; - } - - protected emitEmptyClassDefinition(c: ClassType, className: Name): void { - this.emitDescription(this.descriptionForType(c)); - - this.emitLine("typealias ", className, " = JsonNode"); - } - - protected emitClassDefinitionMethods(c: ClassType, className: Name): void { - const isTopLevel = iterableSome(this.topLevels, ([_, top]) => top === c); - if (isTopLevel) { - this.emitBlock(")", () => { - this.emitLine("fun toJson() = mapper.writeValueAsString(this)"); - this.ensureBlankLine(); - this.emitBlock("companion object", () => { - this.emitLine("fun fromJson(json: String) = mapper.readValue<", className, ">(json)"); - }); - }); - } else { - this.emitLine(")"); - } - } - - protected renameAttribute(name: Name, jsonName: string, required: boolean, meta: Array<() => void>): void { - const rename = this.jacksonRenameAttribute(name, jsonName, required); - if (rename !== undefined) { - meta.push(() => this.emitLine(rename)); - } - } - - protected emitEnumDefinition(e: EnumType, enumName: Name): void { - this.emitDescription(this.descriptionForType(e)); - - this.emitBlock(["enum class ", enumName, "(val value: String)"], () => { - let count = e.cases.size; - this.forEachEnumCase(e, "none", (name, json) => { - this.emitLine(name, `("${stringEscape(json)}")`, --count === 0 ? ";" : ","); - }); - this.ensureBlankLine(); - this.emitBlock("companion object", () => { - this.emitBlock(["fun fromValue(value: String): ", enumName, " = when (value)"], () => { - let table: Sourcelike[][] = []; - this.forEachEnumCase(e, "none", (name, json) => { - table.push([[`"${stringEscape(json)}"`], [" -> ", name]]); - }); - table.push([["else"], [" -> throw IllegalArgumentException()"]]); - this.emitTable(table); - }); - }); - }); - } - - private emitGenericConverter(): void { - this.ensureBlankLine(); - this.emitMultiline(` -@Suppress("UNCHECKED_CAST") -private fun ObjectMapper.convert(k: kotlin.reflect.KClass<*>, fromJson: (JsonNode) -> T, toJson: (T) -> String, isUnion: Boolean = false) = registerModule(SimpleModule().apply { - addSerializer(k.java as Class, object : StdSerializer(k.java as Class) { - override fun serialize(value: T, gen: JsonGenerator, provider: SerializerProvider) = gen.writeRawValue(toJson(value)) - }) - addDeserializer(k.java as Class, object : StdDeserializer(k.java as Class) { - override fun deserialize(p: JsonParser, ctxt: DeserializationContext) = fromJson(p.readValueAsTree()) - }) -})`); - } - - protected emitUnionDefinitionMethods( - u: UnionType, - nonNulls: ReadonlySet, - maybeNull: PrimitiveType | null, - unionName: Name - ): void { - this.ensureBlankLine(); - this.emitLine("fun toJson(): String = mapper.writeValueAsString(when (this) {"); - this.indent(() => { - let toJsonTable: Sourcelike[][] = []; - this.forEachUnionMember(u, nonNulls, "none", null, name => { - toJsonTable.push([["is ", name], [" -> this.value"]]); - }); - if (maybeNull !== null) { - const name = this.nameForUnionMember(u, maybeNull); - toJsonTable.push([["is ", name], [' -> "null"']]); - } - - this.emitTable(toJsonTable); - }); - this.emitLine("})"); - this.ensureBlankLine(); - this.emitBlock("companion object", () => { - this.emitLine("fun fromJson(jn: JsonNode): ", unionName, " = when (jn) {"); - this.indent(() => { - let table: Sourcelike[][] = []; - this.forEachUnionMember(u, nonNulls, "none", null, (name, t) => { - table.push([[this.unionMemberJsonValueGuard(t, "jn")], [" -> ", name, "(mapper.treeToValue(jn))"]]); - }); - if (maybeNull !== null) { - const name = this.nameForUnionMember(u, maybeNull); - table.push([[this.unionMemberJsonValueGuard(maybeNull, "jn")], [" -> ", name, "()"]]); - } - - table.push([["else"], [" -> throw IllegalArgumentException()"]]); - this.emitTable(table); - }); - this.emitLine("}"); - }); - } -} - -/** - * Currently supports simple classes, enums, and TS string unions (which are also enums). - * TODO: Union, Any, Top Level Array, Top Level Map - */ -export class KotlinXRenderer extends KotlinRenderer { - public constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - _kotlinOptions: OptionValues - ) { - super(targetLanguage, renderContext, _kotlinOptions); - } - - protected anySourceType(optional: string): Sourcelike { - return ["JsonElement", optional]; - } - - protected arrayType(arrayType: ArrayType, withIssues = false, noOptional = false): Sourcelike { - const valType = this.kotlinType(arrayType.items, withIssues, true); - const name = this.sourcelikeToString(valType); - if (name === "JsonObject" || name === "JsonElement") { - return "JsonArray"; - } - - return super.arrayType(arrayType, withIssues, noOptional); - } - - protected mapType(mapType: MapType, withIssues = false, noOptional = false): Sourcelike { - const valType = this.kotlinType(mapType.values, withIssues, true); - const name = this.sourcelikeToString(valType); - if (name === "JsonObject" || name === "JsonElement") { - return "JsonObject"; - } - - return super.mapType(mapType, withIssues, noOptional); - } - - protected emitTopLevelMap(t: MapType, name: Name): void { - const elementType = this.kotlinType(t.values); - if (elementType === "JsonObject") { - this.emitLine(["typealias ", name, " = JsonObject"]); - } else { - super.emitTopLevelMap(t, name); - } - } - - protected emitTopLevelArray(t: ArrayType, name: Name): void { - const elementType = this.kotlinType(t.items); - this.emitLine(["typealias ", name, " = JsonArray<", elementType, ">"]); - } - - protected emitUsageHeader(): void { - this.emitLine("// To parse the JSON, install kotlin's serialization plugin and do:"); - this.emitLine("//"); - const table: Sourcelike[][] = []; - table.push(["// val ", "json", " = Json { allowStructuredMapKeys = true }"]); - this.forEachTopLevel("none", (_, name) => { - table.push([ - "// val ", - modifySource(camelCase, name), - ` = json.parse(${this.sourcelikeToString(name)}.serializer(), jsonString)` - ]); - }); - this.emitTable(table); - } - - protected emitHeader(): void { - super.emitHeader(); - - this.emitLine("import kotlinx.serialization.*"); - this.emitLine("import kotlinx.serialization.json.*"); - this.emitLine("import kotlinx.serialization.descriptors.*"); - this.emitLine("import kotlinx.serialization.encoding.*"); - } - - protected emitClassAnnotations(_c: Type, _className: Name): void { - this.emitLine("@Serializable"); - } - - protected renameAttribute(name: Name, jsonName: string, _required: boolean, meta: Array<() => void>): void { - const rename = this._rename(name, jsonName); - if (rename !== undefined) { - meta.push(() => this.emitLine(rename)); - } - } - - private _rename(propName: Name, jsonName: string): Sourcelike | undefined { - const escapedName = stringEscape(jsonName); - const namesDiffer = this.sourcelikeToString(propName) !== escapedName; - if (namesDiffer) { - return ['@SerialName("', escapedName, '")']; - } - - return undefined; - } - - protected emitEnumDefinition(e: EnumType, enumName: Name): void { - this.emitDescription(this.descriptionForType(e)); - - this.emitLine(["@Serializable"]); - this.emitBlock(["enum class ", enumName, "(val value: String)"], () => { - let count = e.cases.size; - this.forEachEnumCase(e, "none", (name, json) => { - const jsonEnum = stringEscape(json); - this.emitLine(`@SerialName("${jsonEnum}") `, name, `("${jsonEnum}")`, --count === 0 ? ";" : ","); - }); - }); - } -} diff --git a/packages/quicktype-core/src/language/Kotlin/KotlinJacksonRenderer.ts b/packages/quicktype-core/src/language/Kotlin/KotlinJacksonRenderer.ts new file mode 100644 index 000000000..0b840946a --- /dev/null +++ b/packages/quicktype-core/src/language/Kotlin/KotlinJacksonRenderer.ts @@ -0,0 +1,293 @@ +import { arrayIntercalate, iterableSome } from "collection-utils"; + +import { type Name } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type Sourcelike, modifySource } from "../../Source"; +import { camelCase } from "../../support/Strings"; +import { mustNotHappen } from "../../support/Support"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { + type ArrayType, + ClassType, + type EnumType, + type MapType, + type PrimitiveType, + type Type, + UnionType +} from "../../Type"; +import { matchType, nullableFromUnion } from "../../TypeUtils"; + +import { KotlinRenderer } from "./KotlinRenderer"; +import { type kotlinOptions } from "./language"; +import { stringEscape } from "./utils"; + +export class KotlinJacksonRenderer extends KotlinRenderer { + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + _kotlinOptions: OptionValues + ) { + super(targetLanguage, renderContext, _kotlinOptions); + } + + private unionMemberJsonValueGuard(t: Type, _e: Sourcelike): Sourcelike { + return matchType( + t, + _anyType => "is Any", + _nullType => "null", + _boolType => "is BooleanNode", + _integerType => "is IntNode, is LongNode", + _doubleType => "is DoubleNode", + _stringType => "is TextNode", + _arrayType => "is ArrayNode", + // These could be stricter, but for now we don't allow maps + // and objects in the same union + _classType => "is ObjectNode", + _mapType => "is ObjectNode", + // This could be stricter, but for now we don't allow strings + // and enums in the same union + _enumType => "is TextNode", + _unionType => mustNotHappen() + ); + } + + protected emitUsageHeader(): void { + this.emitLine("// To parse the JSON, install jackson-module-kotlin and do:"); + this.emitLine("//"); + this.forEachTopLevel("none", (_, name) => { + this.emitLine("// val ", modifySource(camelCase, name), " = ", name, ".fromJson(jsonString)"); + }); + } + + protected emitHeader(): void { + super.emitHeader(); + + this.emitMultiline(`import com.fasterxml.jackson.annotation.* +import com.fasterxml.jackson.core.* +import com.fasterxml.jackson.databind.* +import com.fasterxml.jackson.databind.deser.std.StdDeserializer +import com.fasterxml.jackson.databind.module.SimpleModule +import com.fasterxml.jackson.databind.node.* +import com.fasterxml.jackson.databind.ser.std.StdSerializer +import com.fasterxml.jackson.module.kotlin.*`); + + const hasUnions = iterableSome( + this.typeGraph.allNamedTypes(), + t => t instanceof UnionType && nullableFromUnion(t) === null + ); + const hasEmptyObjects = iterableSome( + this.typeGraph.allNamedTypes(), + c => c instanceof ClassType && c.getProperties().size === 0 + ); + if (hasUnions || this.haveEnums || hasEmptyObjects) { + this.emitGenericConverter(); + } + + let converters: Sourcelike[][] = []; + // if (hasEmptyObjects) { + // converters.push([["convert(JsonNode::class,"], [" { it },"], [" { writeValueAsString(it) })"]]); + // } + this.forEachEnum("none", (_, name) => { + converters.push([ + ["convert(", name, "::class,"], + [" { ", name, ".fromValue(it.asText()) },"], + [' { "\\"${it.value}\\"" })'] + ]); + }); + this.forEachUnion("none", (_, name) => { + converters.push([ + ["convert(", name, "::class,"], + [" { ", name, ".fromJson(it) },"], + [" { it.toJson() }, true)"] + ]); + }); + + this.ensureBlankLine(); + this.emitLine("val mapper = jacksonObjectMapper().apply {"); + this.indent(() => { + this.emitLine("propertyNamingStrategy = PropertyNamingStrategy.LOWER_CAMEL_CASE"); + this.emitLine("setSerializationInclusion(JsonInclude.Include.NON_NULL)"); + }); + + if (converters.length > 0) { + this.indent(() => this.emitTable(converters)); + } + + this.emitLine("}"); + } + + protected emitTopLevelArray(t: ArrayType, name: Name): void { + const elementType = this.kotlinType(t.items); + this.emitBlock( + ["class ", name, "(elements: Collection<", elementType, ">) : ArrayList<", elementType, ">(elements)"], + () => { + this.emitLine("fun toJson() = mapper.writeValueAsString(this)"); + this.ensureBlankLine(); + this.emitBlock("companion object", () => { + this.emitLine("fun fromJson(json: String) = mapper.readValue<", name, ">(json)"); + }); + } + ); + } + + protected emitTopLevelMap(t: MapType, name: Name): void { + const elementType = this.kotlinType(t.values); + this.emitBlock( + [ + "class ", + name, + "(elements: Map) : HashMap(elements)" + ], + () => { + this.emitLine("fun toJson() = mapper.writeValueAsString(this)"); + this.ensureBlankLine(); + this.emitBlock("companion object", () => { + this.emitLine("fun fromJson(json: String) = mapper.readValue<", name, ">(json)"); + }); + } + ); + } + + private jacksonRenameAttribute( + propName: Name, + jsonName: string, + required: boolean, + ignore = false + ): Sourcelike | undefined { + const escapedName = stringEscape(jsonName); + const namesDiffer = this.sourcelikeToString(propName) !== escapedName; + const properties: Sourcelike[] = []; + const isPrefixBool = jsonName.startsWith("is"); // https://github.com/FasterXML/jackson-module-kotlin/issues/80 + const propertyOpts: Sourcelike[] = []; + + if (namesDiffer || isPrefixBool) { + propertyOpts.push('"' + escapedName + '"'); + } + + if (required) { + propertyOpts.push("required=true"); + } + + if (propertyOpts.length > 0) { + properties.push(["@get:JsonProperty(", arrayIntercalate(", ", propertyOpts), ")"]); + properties.push(["@field:JsonProperty(", arrayIntercalate(", ", propertyOpts), ")"]); + } + + if (ignore) { + properties.push("@get:JsonIgnore"); + properties.push("@field:JsonIgnore"); + } + + return properties.length === 0 ? undefined : properties; + } + + protected emitEmptyClassDefinition(c: ClassType, className: Name): void { + this.emitDescription(this.descriptionForType(c)); + + this.emitLine("typealias ", className, " = JsonNode"); + } + + protected emitClassDefinitionMethods(c: ClassType, className: Name): void { + const isTopLevel = iterableSome(this.topLevels, ([_, top]) => top === c); + if (isTopLevel) { + this.emitBlock(")", () => { + this.emitLine("fun toJson() = mapper.writeValueAsString(this)"); + this.ensureBlankLine(); + this.emitBlock("companion object", () => { + this.emitLine("fun fromJson(json: String) = mapper.readValue<", className, ">(json)"); + }); + }); + } else { + this.emitLine(")"); + } + } + + protected renameAttribute(name: Name, jsonName: string, required: boolean, meta: Array<() => void>): void { + const rename = this.jacksonRenameAttribute(name, jsonName, required); + if (rename !== undefined) { + meta.push(() => this.emitLine(rename)); + } + } + + protected emitEnumDefinition(e: EnumType, enumName: Name): void { + this.emitDescription(this.descriptionForType(e)); + + this.emitBlock(["enum class ", enumName, "(val value: String)"], () => { + let count = e.cases.size; + this.forEachEnumCase(e, "none", (name, json) => { + this.emitLine(name, `("${stringEscape(json)}")`, --count === 0 ? ";" : ","); + }); + this.ensureBlankLine(); + this.emitBlock("companion object", () => { + this.emitBlock(["fun fromValue(value: String): ", enumName, " = when (value)"], () => { + let table: Sourcelike[][] = []; + this.forEachEnumCase(e, "none", (name, json) => { + table.push([[`"${stringEscape(json)}"`], [" -> ", name]]); + }); + table.push([["else"], [" -> throw IllegalArgumentException()"]]); + this.emitTable(table); + }); + }); + }); + } + + private emitGenericConverter(): void { + this.ensureBlankLine(); + this.emitMultiline(` +@Suppress("UNCHECKED_CAST") +private fun ObjectMapper.convert(k: kotlin.reflect.KClass<*>, fromJson: (JsonNode) -> T, toJson: (T) -> String, isUnion: Boolean = false) = registerModule(SimpleModule().apply { + addSerializer(k.java as Class, object : StdSerializer(k.java as Class) { + override fun serialize(value: T, gen: JsonGenerator, provider: SerializerProvider) = gen.writeRawValue(toJson(value)) + }) + addDeserializer(k.java as Class, object : StdDeserializer(k.java as Class) { + override fun deserialize(p: JsonParser, ctxt: DeserializationContext) = fromJson(p.readValueAsTree()) + }) +})`); + } + + protected emitUnionDefinitionMethods( + u: UnionType, + nonNulls: ReadonlySet, + maybeNull: PrimitiveType | null, + unionName: Name + ): void { + this.ensureBlankLine(); + this.emitLine("fun toJson(): String = mapper.writeValueAsString(when (this) {"); + this.indent(() => { + let toJsonTable: Sourcelike[][] = []; + this.forEachUnionMember(u, nonNulls, "none", null, name => { + toJsonTable.push([["is ", name], [" -> this.value"]]); + }); + if (maybeNull !== null) { + const name = this.nameForUnionMember(u, maybeNull); + toJsonTable.push([["is ", name], [' -> "null"']]); + } + + this.emitTable(toJsonTable); + }); + this.emitLine("})"); + this.ensureBlankLine(); + this.emitBlock("companion object", () => { + this.emitLine("fun fromJson(jn: JsonNode): ", unionName, " = when (jn) {"); + this.indent(() => { + let table: Sourcelike[][] = []; + this.forEachUnionMember(u, nonNulls, "none", null, (name, t) => { + table.push([[this.unionMemberJsonValueGuard(t, "jn")], [" -> ", name, "(mapper.treeToValue(jn))"]]); + }); + if (maybeNull !== null) { + const name = this.nameForUnionMember(u, maybeNull); + table.push([[this.unionMemberJsonValueGuard(maybeNull, "jn")], [" -> ", name, "()"]]); + } + + table.push([["else"], [" -> throw IllegalArgumentException()"]]); + this.emitTable(table); + }); + this.emitLine("}"); + }); + } +} diff --git a/packages/quicktype-core/src/language/Kotlin/KotlinKlaxonRenderer.ts b/packages/quicktype-core/src/language/Kotlin/KotlinKlaxonRenderer.ts new file mode 100644 index 000000000..bcfaf9043 --- /dev/null +++ b/packages/quicktype-core/src/language/Kotlin/KotlinKlaxonRenderer.ts @@ -0,0 +1,306 @@ +import { arrayIntercalate, iterableSome } from "collection-utils"; + +import { type Name } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type Sourcelike, modifySource } from "../../Source"; +import { camelCase } from "../../support/Strings"; +import { mustNotHappen } from "../../support/Support"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { + type ArrayType, + ClassType, + type EnumType, + type MapType, + type PrimitiveType, + type Type, + UnionType +} from "../../Type"; +import { matchType, nullableFromUnion } from "../../TypeUtils"; + +import { KotlinRenderer } from "./KotlinRenderer"; +import { type kotlinOptions } from "./language"; +import { stringEscape } from "./utils"; + +export class KotlinKlaxonRenderer extends KotlinRenderer { + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + _kotlinOptions: OptionValues + ) { + super(targetLanguage, renderContext, _kotlinOptions); + } + + private unionMemberFromJsonValue(t: Type, e: Sourcelike): Sourcelike { + return matchType( + t, + _anyType => [e, ".inside"], + _nullType => "null", + _boolType => [e, ".boolean"], + _integerType => ["(", e, ".int?.toLong() ?: ", e, ".longValue)"], + _doubleType => [e, ".double"], + _stringType => [e, ".string"], + arrayType => [e, ".array?.let { klaxon.parseFromJsonArray<", this.kotlinType(arrayType.items), ">(it) }"], + _classType => [e, ".obj?.let { klaxon.parseFromJsonObject<", this.kotlinType(t), ">(it) }"], + _mapType => [e, ".obj?.let { klaxon.parseFromJsonObject<", this.kotlinType(t), ">(it) }"], + enumType => [e, ".string?.let { ", this.kotlinType(enumType), ".fromValue(it) }"], + _unionType => mustNotHappen() + ); + } + + private unionMemberJsonValueGuard(t: Type, _e: Sourcelike): Sourcelike { + return matchType( + t, + _anyType => "is Any", + _nullType => "null", + _boolType => "is Boolean", + _integerType => "is Int, is Long", + _doubleType => "is Double", + _stringType => "is String", + _arrayType => "is JsonArray<*>", + // These could be stricter, but for now we don't allow maps + // and objects in the same union + _classType => "is JsonObject", + _mapType => "is JsonObject", + // This could be stricter, but for now we don't allow strings + // and enums in the same union + _enumType => "is String", + _unionType => mustNotHappen() + ); + } + + protected emitUsageHeader(): void { + this.emitLine("// To parse the JSON, install Klaxon and do:"); + this.emitLine("//"); + this.forEachTopLevel("none", (_, name) => { + this.emitLine("// val ", modifySource(camelCase, name), " = ", name, ".fromJson(jsonString)"); + }); + } + + protected emitHeader(): void { + super.emitHeader(); + + this.emitLine("import com.beust.klaxon.*"); + + const hasUnions = iterableSome( + this.typeGraph.allNamedTypes(), + t => t instanceof UnionType && nullableFromUnion(t) === null + ); + const hasEmptyObjects = iterableSome( + this.typeGraph.allNamedTypes(), + c => c instanceof ClassType && c.getProperties().size === 0 + ); + if (hasUnions || this.haveEnums || hasEmptyObjects) { + this.emitGenericConverter(); + } + + let converters: Sourcelike[][] = []; + if (hasEmptyObjects) { + converters.push([[".convert(JsonObject::class,"], [" { it.obj!! },"], [" { it.toJsonString() })"]]); + } + + this.forEachEnum("none", (_, name) => { + converters.push([ + [".convert(", name, "::class,"], + [" { ", name, ".fromValue(it.string!!) },"], + [' { "\\"${it.value}\\"" })'] + ]); + }); + this.forEachUnion("none", (_, name) => { + converters.push([ + [".convert(", name, "::class,"], + [" { ", name, ".fromJson(it) },"], + [" { it.toJson() }, true)"] + ]); + }); + + this.ensureBlankLine(); + this.emitLine("private val klaxon = Klaxon()"); + if (converters.length > 0) { + this.indent(() => this.emitTable(converters)); + } + } + + protected emitTopLevelArray(t: ArrayType, name: Name): void { + const elementType = this.kotlinType(t.items); + this.emitBlock( + ["class ", name, "(elements: Collection<", elementType, ">) : ArrayList<", elementType, ">(elements)"], + () => { + this.emitLine("public fun toJson() = klaxon.toJsonString(this)"); + this.ensureBlankLine(); + this.emitBlock("companion object", () => { + this.emitLine( + "public fun fromJson(json: String) = ", + name, + "(klaxon.parseArray<", + elementType, + ">(json)!!)" + ); + }); + } + ); + } + + protected emitTopLevelMap(t: MapType, name: Name): void { + const elementType = this.kotlinType(t.values); + this.emitBlock( + [ + "class ", + name, + "(elements: Map) : HashMap(elements)" + ], + () => { + this.emitLine("public fun toJson() = klaxon.toJsonString(this)"); + this.ensureBlankLine(); + this.emitBlock("companion object", () => { + this.emitBlock( + ["public fun fromJson(json: String) = ", name], + () => { + this.emitLine( + "klaxon.parseJsonObject(java.io.StringReader(json)) as Map" + ); + }, + "paren" + ); + }); + } + ); + } + + private klaxonRenameAttribute(propName: Name, jsonName: string, ignore = false): Sourcelike | undefined { + const escapedName = stringEscape(jsonName); + const namesDiffer = this.sourcelikeToString(propName) !== escapedName; + const properties: Sourcelike[] = []; + if (namesDiffer) { + properties.push(['name = "', escapedName, '"']); + } + + if (ignore) { + properties.push("ignored = true"); + } + + return properties.length === 0 ? undefined : ["@Json(", arrayIntercalate(", ", properties), ")"]; + } + + protected emitEmptyClassDefinition(c: ClassType, className: Name): void { + this.emitDescription(this.descriptionForType(c)); + + this.emitLine("typealias ", className, " = JsonObject"); + } + + protected emitClassDefinitionMethods(c: ClassType, className: Name): void { + const isTopLevel = iterableSome(this.topLevels, ([_, top]) => top === c); + if (isTopLevel) { + this.emitBlock(")", () => { + this.emitLine("public fun toJson() = klaxon.toJsonString(this)"); + this.ensureBlankLine(); + this.emitBlock("companion object", () => { + this.emitLine("public fun fromJson(json: String) = klaxon.parse<", className, ">(json)"); + }); + }); + } else { + this.emitLine(")"); + } + } + + protected renameAttribute(name: Name, jsonName: string, _required: boolean, meta: Array<() => void>): void { + const rename = this.klaxonRenameAttribute(name, jsonName); + if (rename !== undefined) { + meta.push(() => this.emitLine(rename)); + } + } + + protected emitEnumDefinition(e: EnumType, enumName: Name): void { + this.emitDescription(this.descriptionForType(e)); + + this.emitBlock(["enum class ", enumName, "(val value: String)"], () => { + let count = e.cases.size; + this.forEachEnumCase(e, "none", (name, json) => { + this.emitLine(name, `("${stringEscape(json)}")`, --count === 0 ? ";" : ","); + }); + this.ensureBlankLine(); + this.emitBlock("companion object", () => { + this.emitBlock(["public fun fromValue(value: String): ", enumName, " = when (value)"], () => { + let table: Sourcelike[][] = []; + this.forEachEnumCase(e, "none", (name, json) => { + table.push([[`"${stringEscape(json)}"`], [" -> ", name]]); + }); + table.push([["else"], [" -> throw IllegalArgumentException()"]]); + this.emitTable(table); + }); + }); + }); + } + + private emitGenericConverter(): void { + this.ensureBlankLine(); + this.emitLine( + "private fun Klaxon.convert(k: kotlin.reflect.KClass<*>, fromJson: (JsonValue) -> T, toJson: (T) -> String, isUnion: Boolean = false) =" + ); + this.indent(() => { + this.emitLine("this.converter(object: Converter {"); + this.indent(() => { + this.emitLine('@Suppress("UNCHECKED_CAST")'); + this.emitTable([ + ["override fun toJson(value: Any)", " = toJson(value as T)"], + ["override fun fromJson(jv: JsonValue)", " = fromJson(jv) as Any"], + [ + "override fun canConvert(cls: Class<*>)", + " = cls == k.java || (isUnion && cls.superclass == k.java)" + ] + ]); + }); + this.emitLine("})"); + }); + } + + protected emitUnionDefinitionMethods( + u: UnionType, + nonNulls: ReadonlySet, + maybeNull: PrimitiveType | null, + unionName: Name + ): void { + this.ensureBlankLine(); + this.emitLine("public fun toJson(): String = klaxon.toJsonString(when (this) {"); + this.indent(() => { + let toJsonTable: Sourcelike[][] = []; + this.forEachUnionMember(u, nonNulls, "none", null, name => { + toJsonTable.push([["is ", name], [" -> this.value"]]); + }); + if (maybeNull !== null) { + const name = this.nameForUnionMember(u, maybeNull); + toJsonTable.push([["is ", name], [' -> "null"']]); + } + + this.emitTable(toJsonTable); + }); + this.emitLine("})"); + this.ensureBlankLine(); + this.emitBlock("companion object", () => { + this.emitLine("public fun fromJson(jv: JsonValue): ", unionName, " = when (jv.inside) {"); + this.indent(() => { + let table: Sourcelike[][] = []; + this.forEachUnionMember(u, nonNulls, "none", null, (name, t) => { + table.push([ + [this.unionMemberJsonValueGuard(t, "jv.inside")], + [" -> ", name, "(", this.unionMemberFromJsonValue(t, "jv"), "!!)"] + ]); + }); + if (maybeNull !== null) { + const name = this.nameForUnionMember(u, maybeNull); + table.push([[this.unionMemberJsonValueGuard(maybeNull, "jv.inside")], [" -> ", name, "()"]]); + } + + table.push([["else"], [" -> throw IllegalArgumentException()"]]); + this.emitTable(table); + }); + this.emitLine("}"); + }); + } +} diff --git a/packages/quicktype-core/src/language/Kotlin/KotlinRenderer.ts b/packages/quicktype-core/src/language/Kotlin/KotlinRenderer.ts new file mode 100644 index 000000000..d7e5abaaa --- /dev/null +++ b/packages/quicktype-core/src/language/Kotlin/KotlinRenderer.ts @@ -0,0 +1,300 @@ +import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../../Annotation"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type Sourcelike, maybeAnnotated } from "../../Source"; +import { acronymStyle } from "../../support/Acronyms"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { + ArrayType, + type ClassProperty, + type ClassType, + type EnumType, + MapType, + type ObjectType, + type PrimitiveType, + type Type, + type UnionType +} from "../../Type"; +import { matchType, nullableFromUnion, removeNullFromUnion } from "../../TypeUtils"; + +import { keywords } from "./constants"; +import { type kotlinOptions } from "./language"; +import { kotlinNameStyle } from "./utils"; + +export class KotlinRenderer extends ConvenienceRenderer { + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + protected readonly _kotlinOptions: OptionValues + ) { + super(targetLanguage, renderContext); + } + + protected forbiddenNamesForGlobalNamespace(): readonly string[] { + return keywords; + } + + protected forbiddenForObjectProperties(_o: ObjectType, _classNamed: Name): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: true }; + } + + protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: true }; + } + + protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: false }; + } + + protected topLevelNameStyle(rawName: string): string { + return kotlinNameStyle(true, rawName); + } + + protected makeNamedTypeNamer(): Namer { + return funPrefixNamer("upper", s => kotlinNameStyle(true, s, acronymStyle(this._kotlinOptions.acronymStyle))); + } + + protected namerForObjectProperty(): Namer { + return funPrefixNamer("lower", s => kotlinNameStyle(false, s, acronymStyle(this._kotlinOptions.acronymStyle))); + } + + protected makeUnionMemberNamer(): Namer { + return funPrefixNamer("upper", s => kotlinNameStyle(true, s) + "Value"); + } + + protected makeEnumCaseNamer(): Namer { + return funPrefixNamer("upper", s => kotlinNameStyle(true, s, acronymStyle(this._kotlinOptions.acronymStyle))); + } + + protected emitDescriptionBlock(lines: Sourcelike[]): void { + this.emitCommentLines(lines, { lineStart: " * ", beforeComment: "/**", afterComment: " */" }); + } + + protected emitBlock(line: Sourcelike, f: () => void, delimiter: "curly" | "paren" | "lambda" = "curly"): void { + const [open, close] = delimiter === "curly" ? ["{", "}"] : delimiter === "paren" ? ["(", ")"] : ["{", "})"]; + this.emitLine(line, " ", open); + this.indent(f); + this.emitLine(close); + } + + protected anySourceType(optional: string): Sourcelike { + return ["Any", optional]; + } + + // (asarazan): I've broken out the following two functions + // because some renderers, such as kotlinx, can cope with `any`, while some get mad. + protected arrayType(arrayType: ArrayType, withIssues = false, _noOptional = false): Sourcelike { + return ["List<", this.kotlinType(arrayType.items, withIssues), ">"]; + } + + protected mapType(mapType: MapType, withIssues = false, _noOptional = false): Sourcelike { + return ["Map"]; + } + + protected kotlinType(t: Type, withIssues = false, noOptional = false): Sourcelike { + const optional = noOptional ? "" : "?"; + return matchType( + t, + _anyType => { + return maybeAnnotated(withIssues, anyTypeIssueAnnotation, this.anySourceType(optional)); + }, + _nullType => { + return maybeAnnotated(withIssues, nullTypeIssueAnnotation, this.anySourceType(optional)); + }, + _boolType => "Boolean", + _integerType => "Long", + _doubleType => "Double", + _stringType => "String", + arrayType => this.arrayType(arrayType, withIssues), + classType => this.nameForNamedType(classType), + mapType => this.mapType(mapType, withIssues), + enumType => this.nameForNamedType(enumType), + unionType => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) return [this.kotlinType(nullable, withIssues), optional]; + return this.nameForNamedType(unionType); + } + ); + } + + protected emitUsageHeader(): void { + // To be overridden + } + + protected emitHeader(): void { + if (this.leadingComments !== undefined) { + this.emitComments(this.leadingComments); + } else { + this.emitUsageHeader(); + } + + this.ensureBlankLine(); + this.emitLine("package ", this._kotlinOptions.packageName); + this.ensureBlankLine(); + } + + protected emitTopLevelPrimitive(t: PrimitiveType, name: Name): void { + const elementType = this.kotlinType(t); + this.emitLine(["typealias ", name, " = ", elementType, ""]); + } + + protected emitTopLevelArray(t: ArrayType, name: Name): void { + const elementType = this.kotlinType(t.items); + this.emitLine(["typealias ", name, " = ArrayList<", elementType, ">"]); + } + + protected emitTopLevelMap(t: MapType, name: Name): void { + const elementType = this.kotlinType(t.values); + this.emitLine(["typealias ", name, " = HashMap"]); + } + + protected emitEmptyClassDefinition(c: ClassType, className: Name): void { + this.emitDescription(this.descriptionForType(c)); + this.emitClassAnnotations(c, className); + this.emitLine("class ", className, "()"); + } + + protected emitClassDefinition(c: ClassType, className: Name): void { + if (c.getProperties().size === 0) { + this.emitEmptyClassDefinition(c, className); + return; + } + + const kotlinType = (p: ClassProperty): Sourcelike => { + if (p.isOptional) { + return [this.kotlinType(p.type, true, true), "?"]; + } else { + return this.kotlinType(p.type, true); + } + }; + + this.emitDescription(this.descriptionForType(c)); + this.emitClassAnnotations(c, className); + this.emitLine("data class ", className, " ("); + this.indent(() => { + let count = c.getProperties().size; + let first = true; + this.forEachClassProperty(c, "none", (name, jsonName, p) => { + const nullable = p.type.kind === "union" && nullableFromUnion(p.type as UnionType) !== null; + const nullableOrOptional = p.isOptional || p.type.kind === "null" || nullable; + const last = --count === 0; + let meta: Array<() => void> = []; + + const description = this.descriptionForClassProperty(c, jsonName); + if (description !== undefined) { + meta.push(() => this.emitDescription(description)); + } + + this.renameAttribute(name, jsonName, !nullableOrOptional, meta); + + if (meta.length > 0 && !first) { + this.ensureBlankLine(); + } + + for (const emit of meta) { + emit(); + } + + this.emitLine("val ", name, ": ", kotlinType(p), nullableOrOptional ? " = null" : "", last ? "" : ","); + + if (meta.length > 0 && !last) { + this.ensureBlankLine(); + } + + first = false; + }); + }); + + this.emitClassDefinitionMethods(c, className); + } + + protected emitClassDefinitionMethods(_c: ClassType, _className: Name): void { + this.emitLine(")"); + } + + protected emitClassAnnotations(_c: Type, _className: Name): void { + // to be overridden + } + + protected renameAttribute(_name: Name, _jsonName: string, _required: boolean, _meta: Array<() => void>): void { + // to be overridden + } + + protected emitEnumDefinition(e: EnumType, enumName: Name): void { + this.emitDescription(this.descriptionForType(e)); + + this.emitBlock(["enum class ", enumName], () => { + let count = e.cases.size; + this.forEachEnumCase(e, "none", name => { + this.emitLine(name, --count === 0 ? "" : ","); + }); + }); + } + + protected emitUnionDefinition(u: UnionType, unionName: Name): void { + function sortBy(t: Type): string { + const kind = t.kind; + if (kind === "class") return kind; + return "_" + kind; + } + + this.emitDescription(this.descriptionForType(u)); + + const [maybeNull, nonNulls] = removeNullFromUnion(u, sortBy); + this.emitClassAnnotations(u, unionName); + this.emitBlock(["sealed class ", unionName], () => { + { + let table: Sourcelike[][] = []; + this.forEachUnionMember(u, nonNulls, "none", null, (name, t) => { + table.push([ + ["class ", name, "(val value: ", this.kotlinType(t), ")"], + [" : ", unionName, "()"] + ]); + }); + if (maybeNull !== null) { + table.push([ + ["class ", this.nameForUnionMember(u, maybeNull), "()"], + [" : ", unionName, "()"] + ]); + } + + this.emitTable(table); + } + + this.emitUnionDefinitionMethods(u, nonNulls, maybeNull, unionName); + }); + } + + protected emitUnionDefinitionMethods( + _u: UnionType, + _nonNulls: ReadonlySet, + _maybeNull: PrimitiveType | null, + _unionName: Name + ): void { + // to be overridden + } + + protected emitSourceStructure(): void { + this.emitHeader(); + + // Top-level arrays, maps + this.forEachTopLevel("leading", (t, name) => { + if (t instanceof ArrayType) { + this.emitTopLevelArray(t, name); + } else if (t instanceof MapType) { + this.emitTopLevelMap(t, name); + } else if (t.isPrimitive()) { + this.emitTopLevelPrimitive(t, name); + } + }); + + this.forEachNamedType( + "leading-and-interposing", + (c: ClassType, n: Name) => this.emitClassDefinition(c, n), + (e, n) => this.emitEnumDefinition(e, n), + (u, n) => this.emitUnionDefinition(u, n) + ); + } +} diff --git a/packages/quicktype-core/src/language/Kotlin/KotlinXRenderer.ts b/packages/quicktype-core/src/language/Kotlin/KotlinXRenderer.ts new file mode 100644 index 000000000..66a579b45 --- /dev/null +++ b/packages/quicktype-core/src/language/Kotlin/KotlinXRenderer.ts @@ -0,0 +1,121 @@ +import { type Name } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type Sourcelike, modifySource } from "../../Source"; +import { camelCase } from "../../support/Strings"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { type ArrayType, type EnumType, type MapType, type Type } from "../../Type"; + +import { KotlinRenderer } from "./KotlinRenderer"; +import { type kotlinOptions } from "./language"; +import { stringEscape } from "./utils"; + +/** + * Currently supports simple classes, enums, and TS string unions (which are also enums). + * TODO: Union, Any, Top Level Array, Top Level Map + */ +export class KotlinXRenderer extends KotlinRenderer { + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + _kotlinOptions: OptionValues + ) { + super(targetLanguage, renderContext, _kotlinOptions); + } + + protected anySourceType(optional: string): Sourcelike { + return ["JsonElement", optional]; + } + + protected arrayType(arrayType: ArrayType, withIssues = false, noOptional = false): Sourcelike { + const valType = this.kotlinType(arrayType.items, withIssues, true); + const name = this.sourcelikeToString(valType); + if (name === "JsonObject" || name === "JsonElement") { + return "JsonArray"; + } + + return super.arrayType(arrayType, withIssues, noOptional); + } + + protected mapType(mapType: MapType, withIssues = false, noOptional = false): Sourcelike { + const valType = this.kotlinType(mapType.values, withIssues, true); + const name = this.sourcelikeToString(valType); + if (name === "JsonObject" || name === "JsonElement") { + return "JsonObject"; + } + + return super.mapType(mapType, withIssues, noOptional); + } + + protected emitTopLevelMap(t: MapType, name: Name): void { + const elementType = this.kotlinType(t.values); + if (elementType === "JsonObject") { + this.emitLine(["typealias ", name, " = JsonObject"]); + } else { + super.emitTopLevelMap(t, name); + } + } + + protected emitTopLevelArray(t: ArrayType, name: Name): void { + const elementType = this.kotlinType(t.items); + this.emitLine(["typealias ", name, " = JsonArray<", elementType, ">"]); + } + + protected emitUsageHeader(): void { + this.emitLine("// To parse the JSON, install kotlin's serialization plugin and do:"); + this.emitLine("//"); + const table: Sourcelike[][] = []; + table.push(["// val ", "json", " = Json { allowStructuredMapKeys = true }"]); + this.forEachTopLevel("none", (_, name) => { + table.push([ + "// val ", + modifySource(camelCase, name), + ` = json.parse(${this.sourcelikeToString(name)}.serializer(), jsonString)` + ]); + }); + this.emitTable(table); + } + + protected emitHeader(): void { + super.emitHeader(); + + this.emitLine("import kotlinx.serialization.*"); + this.emitLine("import kotlinx.serialization.json.*"); + this.emitLine("import kotlinx.serialization.descriptors.*"); + this.emitLine("import kotlinx.serialization.encoding.*"); + } + + protected emitClassAnnotations(_c: Type, _className: Name): void { + this.emitLine("@Serializable"); + } + + protected renameAttribute(name: Name, jsonName: string, _required: boolean, meta: Array<() => void>): void { + const rename = this._rename(name, jsonName); + if (rename !== undefined) { + meta.push(() => this.emitLine(rename)); + } + } + + private _rename(propName: Name, jsonName: string): Sourcelike | undefined { + const escapedName = stringEscape(jsonName); + const namesDiffer = this.sourcelikeToString(propName) !== escapedName; + if (namesDiffer) { + return ['@SerialName("', escapedName, '")']; + } + + return undefined; + } + + protected emitEnumDefinition(e: EnumType, enumName: Name): void { + this.emitDescription(this.descriptionForType(e)); + + this.emitLine(["@Serializable"]); + this.emitBlock(["enum class ", enumName, "(val value: String)"], () => { + let count = e.cases.size; + this.forEachEnumCase(e, "none", (name, json) => { + const jsonEnum = stringEscape(json); + this.emitLine(`@SerialName("${jsonEnum}") `, name, `("${jsonEnum}")`, --count === 0 ? ";" : ","); + }); + }); + } +} diff --git a/packages/quicktype-core/src/language/Kotlin/constants.ts b/packages/quicktype-core/src/language/Kotlin/constants.ts new file mode 100644 index 000000000..8e83c7388 --- /dev/null +++ b/packages/quicktype-core/src/language/Kotlin/constants.ts @@ -0,0 +1,51 @@ +export const keywords = [ + "package", + "as", + "typealias", + "class", + "this", + "super", + "val", + "var", + "fun", + "for", + "null", + "true", + "false", + "is", + "in", + "throw", + "return", + "break", + "continue", + "object", + "if", + "try", + "else", + "while", + "do", + "when", + "interface", + "typeof", + "klaxon", + "toJson", + "Any", + "Boolean", + "Double", + "Float", + "Long", + "Int", + "Short", + "System", + "Byte", + "String", + "Array", + "List", + "Map", + "Enum", + "Class", + "JsonObject", + "JsonValue", + "Converter", + "Klaxon" +] as const; diff --git a/packages/quicktype-core/src/language/Kotlin/index.ts b/packages/quicktype-core/src/language/Kotlin/index.ts new file mode 100644 index 000000000..e6459d694 --- /dev/null +++ b/packages/quicktype-core/src/language/Kotlin/index.ts @@ -0,0 +1,5 @@ +export { KotlinTargetLanguage, kotlinOptions } from "./language"; +export { KotlinRenderer } from "./KotlinRenderer"; +export { KotlinJacksonRenderer } from "./KotlinJacksonRenderer"; +export { KotlinKlaxonRenderer } from "./KotlinKlaxonRenderer"; +export { KotlinXRenderer } from "./KotlinXRenderer"; diff --git a/packages/quicktype-core/src/language/Kotlin/language.ts b/packages/quicktype-core/src/language/Kotlin/language.ts new file mode 100644 index 000000000..59a150dc9 --- /dev/null +++ b/packages/quicktype-core/src/language/Kotlin/language.ts @@ -0,0 +1,70 @@ +import { type ConvenienceRenderer } from "../../ConvenienceRenderer"; +import { type RenderContext } from "../../Renderer"; +import { EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { AcronymStyleOptions, acronymOption } from "../../support/Acronyms"; +import { assertNever } from "../../support/Support"; +import { TargetLanguage } from "../../TargetLanguage"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; + +import { KotlinJacksonRenderer } from "./KotlinJacksonRenderer"; +import { KotlinKlaxonRenderer } from "./KotlinKlaxonRenderer"; +import { KotlinRenderer } from "./KotlinRenderer"; +import { KotlinXRenderer } from "./KotlinXRenderer"; + +export enum Framework { + None = "None", + Jackson = "Jackson", + Klaxon = "Klaxon", + KotlinX = "KotlinX" +} + +export const kotlinOptions = { + framework: new EnumOption( + "framework", + "Serialization framework", + [ + ["just-types", Framework.None], + ["jackson", Framework.Jackson], + ["klaxon", Framework.Klaxon], + ["kotlinx", Framework.KotlinX] + ], + "klaxon" + ), + acronymStyle: acronymOption(AcronymStyleOptions.Pascal), + packageName: new StringOption("package", "Package", "PACKAGE", "quicktype") +}; + +export class KotlinTargetLanguage extends TargetLanguage { + public constructor() { + super("Kotlin", ["kotlin"], "kt"); + } + + protected getOptions(): Array> { + return [kotlinOptions.framework, kotlinOptions.acronymStyle, kotlinOptions.packageName]; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): ConvenienceRenderer { + const options = getOptionValues(kotlinOptions, untypedOptionValues); + + switch (options.framework) { + case Framework.None: + return new KotlinRenderer(this, renderContext, options); + case Framework.Jackson: + return new KotlinJacksonRenderer(this, renderContext, options); + case Framework.Klaxon: + return new KotlinKlaxonRenderer(this, renderContext, options); + case Framework.KotlinX: + return new KotlinXRenderer(this, renderContext, options); + default: + return assertNever(options.framework); + } + } +} diff --git a/packages/quicktype-core/src/language/Kotlin/utils.ts b/packages/quicktype-core/src/language/Kotlin/utils.ts new file mode 100644 index 000000000..69fc8fb0c --- /dev/null +++ b/packages/quicktype-core/src/language/Kotlin/utils.ts @@ -0,0 +1,55 @@ +import { + allLowerWordStyle, + allUpperWordStyle, + combineWords, + escapeNonPrintableMapper, + firstUpperWordStyle, + intToHex, + isDigit, + isLetterOrUnderscore, + isNumeric, + isPrintable, + legalizeCharacters, + splitIntoWords, + utf32ConcatMap +} from "../../support/Strings"; + +function isPartCharacter(codePoint: number): boolean { + return isLetterOrUnderscore(codePoint) || isNumeric(codePoint); +} + +function isStartCharacter(codePoint: number): boolean { + return isPartCharacter(codePoint) && !isDigit(codePoint); +} + +const legalizeName = legalizeCharacters(isPartCharacter); + +export function kotlinNameStyle( + isUpper: boolean, + original: string, + acronymsStyle: (s: string) => string = allUpperWordStyle +): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + isUpper ? firstUpperWordStyle : allLowerWordStyle, + firstUpperWordStyle, + isUpper ? allUpperWordStyle : allLowerWordStyle, + acronymsStyle, + "", + isStartCharacter + ); +} + +function unicodeEscape(codePoint: number): string { + return "\\u" + intToHex(codePoint, 4); +} + +// eslint-disable-next-line @typescript-eslint/naming-convention +const _stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, unicodeEscape)); + +export function stringEscape(s: string): string { + // "$this" is a template string in Kotlin so we have to escape $ + return _stringEscape(s).replace(/\$/g, "\\$"); +} diff --git a/packages/quicktype-core/src/language/Objective-C.ts b/packages/quicktype-core/src/language/Objective-C/ObjectiveCRenderer.ts similarity index 84% rename from packages/quicktype-core/src/language/Objective-C.ts rename to packages/quicktype-core/src/language/Objective-C/ObjectiveCRenderer.ts index 3b46b914b..faca214c8 100644 --- a/packages/quicktype-core/src/language/Objective-C.ts +++ b/packages/quicktype-core/src/language/Objective-C/ObjectiveCRenderer.ts @@ -1,231 +1,28 @@ import { iterableFirst, iterableSome, mapContains, mapFirst, mapSome } from "collection-utils"; -import unicode from "unicode-properties"; -import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { type Name, Namer, funPrefixNamer } from "../Naming"; -import { type RenderContext } from "../Renderer"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../../ConvenienceRenderer"; +import { type Name, Namer, funPrefixNamer } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type Sourcelike, modifySource } from "../../Source"; +import { camelCase, fastIsUpperCase, repeatString, stringEscape } from "../../support/Strings"; +import { assert, defined } from "../../support/Support"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { ArrayType, type ClassProperty, ClassType, EnumType, MapType, Type, UnionType } from "../../Type"; +import { isAnyOrNull, matchType, nullableFromUnion } from "../../TypeUtils"; + +import { forbiddenPropertyNames, keywords } from "./constants"; +import { type MemoryAttribute, type objectiveCOptions } from "./language"; import { - BooleanOption, - EnumOption, - type Option, - type OptionValues, - StringOption, - getOptionValues -} from "../RendererOptions"; -import { type Sourcelike, modifySource } from "../Source"; -import { - addPrefixIfNecessary, - allLowerWordStyle, - allUpperWordStyle, - camelCase, - combineWords, - fastIsUpperCase, - firstUpperWordStyle, - repeatString, - splitIntoWords, - stringEscape, - utf16LegalizeCharacters -} from "../support/Strings"; -import { assert, defined } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; -import { ArrayType, type ClassProperty, ClassType, EnumType, MapType, Type, UnionType } from "../Type"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; -import { isAnyOrNull, matchType, nullableFromUnion } from "../TypeUtils"; - -export type MemoryAttribute = "assign" | "strong" | "copy"; -export interface OutputFeatures { - implementation: boolean; - interface: boolean; -} + DEFAULT_CLASS_PREFIX, + forbiddenForEnumCases, + propertyNameStyle, + splitExtension, + staticEnumValuesIdentifier, + typeNameStyle +} from "./utils"; const DEBUG = false; -const DEFAULT_CLASS_PREFIX = "QT"; - -export const objcOptions = { - features: new EnumOption("features", "Interface and implementation", [ - ["all", { interface: true, implementation: true }], - ["interface", { interface: true, implementation: false }], - ["implementation", { interface: false, implementation: true }] - ]), - justTypes: new BooleanOption("just-types", "Plain types only", false), - marshallingFunctions: new BooleanOption("functions", "C-style functions", false), - classPrefix: new StringOption("class-prefix", "Class prefix", "PREFIX", DEFAULT_CLASS_PREFIX), - extraComments: new BooleanOption("extra-comments", "Extra comments", false) -}; - -export class ObjectiveCTargetLanguage extends TargetLanguage { - public constructor() { - super("Objective-C", ["objc", "objective-c", "objectivec"], "m"); - } - - protected getOptions(): Array> { - return [ - objcOptions.justTypes, - objcOptions.classPrefix, - objcOptions.features, - objcOptions.extraComments, - objcOptions.marshallingFunctions - ]; - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): ObjectiveCRenderer { - return new ObjectiveCRenderer(this, renderContext, getOptionValues(objcOptions, untypedOptionValues)); - } -} - -function typeNameStyle(prefix: string, original: string): string { - const words = splitIntoWords(original); - const result = combineWords( - words, - legalizeName, - firstUpperWordStyle, - firstUpperWordStyle, - allUpperWordStyle, - allUpperWordStyle, - "", - isStartCharacter - ); - return addPrefixIfNecessary(prefix, result); -} - -function propertyNameStyle(original: string, isBool = false): string { - // Objective-C developers are uncomfortable with property "id" - // so we use an alternate name in this special case. - if (original === "id") { - original = "identifier"; - } - - let words = splitIntoWords(original); - - if (isBool) { - if (words.length === 0) { - words = [{ word: "flag", isAcronym: false }]; - } else if (!words[0].isAcronym && !booleanPrefixes.includes(words[0].word)) { - words = [{ word: "is", isAcronym: false }, ...words]; - } - } - - // Properties cannot even begin with any of the forbidden names - // For example, properies named new* are treated differently by ARC - if (words.length > 0 && forbiddenPropertyNames.includes(words[0].word)) { - words = [{ word: "the", isAcronym: false }, ...words]; - } - - return combineWords( - words, - legalizeName, - allLowerWordStyle, - firstUpperWordStyle, - allLowerWordStyle, - allUpperWordStyle, - "", - isStartCharacter - ); -} - -const keywords = [ - /* - "_Bool", - "_Complex", - "_Imaginary", - */ - "asm", - "atomic", - "auto", - "bool", - "break", - "case", - "char", - "const", - "continue", - "default", - "do", - "double", - "else", - "enum", - "extern", - "false", - "float", - "for", - "goto", - "if", - "inline", - "int", - "long", - "nil", - "nonatomic", - "register", - "restrict", - "retain", - "return", - "short", - "signed", - "sizeof", - "static", - "struct", - "switch", - "typedef", - "typeof", - "true", - "union", - "unsigned", - "void", - "volatile", - "while" -]; - -const forbiddenPropertyNames = [ - "id", - "hash", - "description", - "init", - "copy", - "mutableCopy", - "superclass", - "debugDescription", - "new" -]; - -const booleanPrefixes = [ - "is", - "are", - "were", - "was", - "will", - "all", - "some", - "many", - "has", - "have", - "had", - "does", - "do", - "requires", - "require", - "needs", - "need" -]; - -function isStartCharacter(utf16Unit: number): boolean { - return unicode.isAlphabetic(utf16Unit) || utf16Unit === 0x5f; // underscore -} - -function isPartCharacter(utf16Unit: number): boolean { - const category: string = unicode.getCategory(utf16Unit); - return ["Nd", "Pc", "Mn", "Mc"].includes(category) || isStartCharacter(utf16Unit); -} - -const legalizeName = utf16LegalizeCharacters(isPartCharacter); - -const staticEnumValuesIdentifier = "values"; -const forbiddenForEnumCases = ["new", staticEnumValuesIdentifier]; - -function splitExtension(filename: string): [string, string] { - const i = filename.lastIndexOf("."); - const extension = i !== -1 ? filename.split(".").pop() : "m"; - filename = i !== -1 ? filename.slice(0, i) : filename; - return [filename, extension ?? "m"]; -} export class ObjectiveCRenderer extends ConvenienceRenderer { private _currentFilename: string | undefined; @@ -235,7 +32,7 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues + private readonly _options: OptionValues ) { super(targetLanguage, renderContext); @@ -259,12 +56,12 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { return name.slice(0, firstNonUpper - 1); } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace(): readonly string[] { return keywords; } protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { - return { names: forbiddenPropertyNames, includeGlobalForbidden: true }; + return { names: forbiddenPropertyNames as unknown as string[], includeGlobalForbidden: true }; } protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { @@ -1087,15 +884,15 @@ export class ObjectiveCRenderer extends ConvenienceRenderer { protected emitMapFunction(): void { if (this.needsMap) { this.emitMultiline(`static id map(id collection, id (^f)(id value)) { - id result = nil; - if ([collection isKindOfClass:NSArray.class]) { - result = [NSMutableArray arrayWithCapacity:[collection count]]; - for (id x in collection) [result addObject:f(x)]; - } else if ([collection isKindOfClass:NSDictionary.class]) { - result = [NSMutableDictionary dictionaryWithCapacity:[collection count]]; - for (id key in collection) [result setObject:f([collection objectForKey:key]) forKey:key]; - } - return result; + id result = nil; + if ([collection isKindOfClass:NSArray.class]) { + result = [NSMutableArray arrayWithCapacity:[collection count]]; + for (id x in collection) [result addObject:f(x)]; + } else if ([collection isKindOfClass:NSDictionary.class]) { + result = [NSMutableDictionary dictionaryWithCapacity:[collection count]]; + for (id key in collection) [result setObject:f([collection objectForKey:key]) forKey:key]; + } + return result; }`); } } diff --git a/packages/quicktype-core/src/language/Objective-C/constants.ts b/packages/quicktype-core/src/language/Objective-C/constants.ts new file mode 100644 index 000000000..84ec8f95f --- /dev/null +++ b/packages/quicktype-core/src/language/Objective-C/constants.ts @@ -0,0 +1,82 @@ +export const keywords = [ + /* + "_Bool", + "_Complex", + "_Imaginary", + */ + "asm", + "atomic", + "auto", + "bool", + "break", + "case", + "char", + "const", + "continue", + "default", + "do", + "double", + "else", + "enum", + "extern", + "false", + "float", + "for", + "goto", + "if", + "inline", + "int", + "long", + "nil", + "nonatomic", + "register", + "restrict", + "retain", + "return", + "short", + "signed", + "sizeof", + "static", + "struct", + "switch", + "typedef", + "typeof", + "true", + "union", + "unsigned", + "void", + "volatile", + "while" +] as const; + +export const forbiddenPropertyNames = [ + "id", + "hash", + "description", + "init", + "copy", + "mutableCopy", + "superclass", + "debugDescription", + "new" +] as const; + +export const booleanPrefixes = [ + "is", + "are", + "were", + "was", + "will", + "all", + "some", + "many", + "has", + "have", + "had", + "does", + "do", + "requires", + "require", + "needs", + "need" +] as const; diff --git a/packages/quicktype-core/src/language/Objective-C/index.ts b/packages/quicktype-core/src/language/Objective-C/index.ts new file mode 100644 index 000000000..46926c8c6 --- /dev/null +++ b/packages/quicktype-core/src/language/Objective-C/index.ts @@ -0,0 +1,2 @@ +export { ObjectiveCTargetLanguage, objectiveCOptions } from "./language"; +export { ObjectiveCRenderer } from "./ObjectiveCRenderer"; diff --git a/packages/quicktype-core/src/language/Objective-C/language.ts b/packages/quicktype-core/src/language/Objective-C/language.ts new file mode 100644 index 000000000..cb34271f9 --- /dev/null +++ b/packages/quicktype-core/src/language/Objective-C/language.ts @@ -0,0 +1,45 @@ +import { type RenderContext } from "../../Renderer"; +import { BooleanOption, EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; + +import { ObjectiveCRenderer } from "./ObjectiveCRenderer"; +import { DEFAULT_CLASS_PREFIX } from "./utils"; + +export type MemoryAttribute = "assign" | "strong" | "copy"; +export interface OutputFeatures { + implementation: boolean; + interface: boolean; +} + +export const objectiveCOptions = { + features: new EnumOption("features", "Interface and implementation", [ + ["all", { interface: true, implementation: true }], + ["interface", { interface: true, implementation: false }], + ["implementation", { interface: false, implementation: true }] + ]), + justTypes: new BooleanOption("just-types", "Plain types only", false), + marshallingFunctions: new BooleanOption("functions", "C-style functions", false), + classPrefix: new StringOption("class-prefix", "Class prefix", "PREFIX", DEFAULT_CLASS_PREFIX), + extraComments: new BooleanOption("extra-comments", "Extra comments", false) +}; + +export class ObjectiveCTargetLanguage extends TargetLanguage { + public constructor() { + super("Objective-C", ["objc", "objective-c", "objectivec"], "m"); + } + + protected getOptions(): Array> { + return [ + objectiveCOptions.justTypes, + objectiveCOptions.classPrefix, + objectiveCOptions.features, + objectiveCOptions.extraComments, + objectiveCOptions.marshallingFunctions + ]; + } + + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): ObjectiveCRenderer { + return new ObjectiveCRenderer(this, renderContext, getOptionValues(objectiveCOptions, untypedOptionValues)); + } +} diff --git a/packages/quicktype-core/src/language/Objective-C/utils.ts b/packages/quicktype-core/src/language/Objective-C/utils.ts new file mode 100644 index 000000000..cdff7db57 --- /dev/null +++ b/packages/quicktype-core/src/language/Objective-C/utils.ts @@ -0,0 +1,88 @@ +import unicode from "unicode-properties"; + +import { + addPrefixIfNecessary, + allLowerWordStyle, + allUpperWordStyle, + combineWords, + firstUpperWordStyle, + splitIntoWords, + utf16LegalizeCharacters +} from "../../support/Strings"; + +import { booleanPrefixes, forbiddenPropertyNames } from "./constants"; + +export const DEFAULT_CLASS_PREFIX = "QT"; + +export function typeNameStyle(prefix: string, original: string): string { + const words = splitIntoWords(original); + const result = combineWords( + words, + legalizeName, + firstUpperWordStyle, + firstUpperWordStyle, + allUpperWordStyle, + allUpperWordStyle, + "", + isStartCharacter + ); + return addPrefixIfNecessary(prefix, result); +} + +export function propertyNameStyle(original: string, isBool = false): string { + // Objective-C developers are uncomfortable with property "id" + // so we use an alternate name in this special case. + if (original === "id") { + original = "identifier"; + } + + let words = splitIntoWords(original); + + if (isBool) { + if (words.length === 0) { + words = [{ word: "flag", isAcronym: false }]; + // @ts-expect-error needs strict type + } else if (!words[0].isAcronym && !booleanPrefixes.includes(words[0].word)) { + words = [{ word: "is", isAcronym: false }, ...words]; + } + } + + // Properties cannot even begin with any of the forbidden names + // For example, properies named new* are treated differently by ARC + // @ts-expect-error needs strict type + if (words.length > 0 && forbiddenPropertyNames.includes(words[0].word)) { + words = [{ word: "the", isAcronym: false }, ...words]; + } + + return combineWords( + words, + legalizeName, + allLowerWordStyle, + firstUpperWordStyle, + allLowerWordStyle, + allUpperWordStyle, + "", + isStartCharacter + ); +} + +function isStartCharacter(utf16Unit: number): boolean { + return unicode.isAlphabetic(utf16Unit) || utf16Unit === 0x5f; // underscore +} + +function isPartCharacter(utf16Unit: number): boolean { + const category: string = unicode.getCategory(utf16Unit); + return ["Nd", "Pc", "Mn", "Mc"].includes(category) || isStartCharacter(utf16Unit); +} + +const legalizeName = utf16LegalizeCharacters(isPartCharacter); + +export const staticEnumValuesIdentifier = "values"; +export const forbiddenForEnumCases = ["new", staticEnumValuesIdentifier]; + +export function splitExtension(filename: string): [string, string] { + const i = filename.lastIndexOf("."); + const extension = i !== -1 ? filename.split(".").pop() : "m"; + filename = i !== -1 ? filename.slice(0, i) : filename; + return [filename, extension ?? "m"]; +} diff --git a/packages/quicktype-core/src/language/Php.ts b/packages/quicktype-core/src/language/Php/PhpRenderer.ts similarity index 91% rename from packages/quicktype-core/src/language/Php.ts rename to packages/quicktype-core/src/language/Php/PhpRenderer.ts index e448bb1ee..720f5b6e4 100644 --- a/packages/quicktype-core/src/language/Php.ts +++ b/packages/quicktype-core/src/language/Php/PhpRenderer.ts @@ -1,100 +1,19 @@ import * as _ from "lodash"; -import { type PrimitiveStringTypeKind, type StringTypeMapping, type TransformedStringTypeKind } from ".."; -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { DependencyName, type Name, type Namer, funPrefixNamer } from "../Naming"; -import { type RenderContext } from "../Renderer"; -import { BooleanOption, type Option, type OptionValues, getOptionValues } from "../RendererOptions"; -import { type Sourcelike, maybeAnnotated } from "../Source"; -import { AcronymStyleOptions, acronymOption, acronymStyle } from "../support/Acronyms"; -import { - allLowerWordStyle, - allUpperWordStyle, - combineWords, - escapeNonPrintableMapper, - firstUpperWordStyle, - isAscii, - isDigit, - isLetter, - splitIntoWords, - standardUnicodeHexEscape, - utf16ConcatMap, - utf16LegalizeCharacters -} from "../support/Strings"; -import { defined } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; -import { type ClassProperty, type ClassType, type EnumType, type Type, type UnionType } from "../Type"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; -import { directlyReachableSingleNamedType, matchType, nullableFromUnion } from "../TypeUtils"; - -export const phpOptions = { - withGet: new BooleanOption("with-get", "Create Getter", true), - fastGet: new BooleanOption("fast-get", "getter without validation", false), - withSet: new BooleanOption("with-set", "Create Setter", false), - withClosing: new BooleanOption("with-closing", "PHP Closing Tag", false), - acronymStyle: acronymOption(AcronymStyleOptions.Pascal) -}; - -export class PhpTargetLanguage extends TargetLanguage { - public constructor() { - super("PHP", ["php"], "php"); - } - - protected getOptions(): Array> { - return _.values(phpOptions); - } - - public get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): PhpRenderer { - const options = getOptionValues(phpOptions, untypedOptionValues); - return new PhpRenderer(this, renderContext, options); - } - - public get stringTypeMapping(): StringTypeMapping { - const mapping: Map = new Map(); - mapping.set("date", "date"); // TODO is not implemented yet - mapping.set("time", "time"); // TODO is not implemented yet - mapping.set("uuid", "uuid"); // TODO is not implemented yet - mapping.set("date-time", "date-time"); - return mapping; - } -} - -export const stringEscape = utf16ConcatMap(escapeNonPrintableMapper(isAscii, standardUnicodeHexEscape)); - -function isStartCharacter(codePoint: number): boolean { - if (codePoint === 0x5f) return true; // underscore - return isAscii(codePoint) && isLetter(codePoint); -} - -function isPartCharacter(codePoint: number): boolean { - return isStartCharacter(codePoint) || (isAscii(codePoint) && isDigit(codePoint)); -} - -const legalizeName = utf16LegalizeCharacters(isPartCharacter); - -export function phpNameStyle( - startWithUpper: boolean, - upperUnderscore: boolean, - original: string, - acronymsStyle: (s: string) => string = allUpperWordStyle -): string { - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - upperUnderscore ? allUpperWordStyle : startWithUpper ? firstUpperWordStyle : allLowerWordStyle, - upperUnderscore ? allUpperWordStyle : firstUpperWordStyle, - upperUnderscore || startWithUpper ? allUpperWordStyle : allLowerWordStyle, - acronymsStyle, - upperUnderscore ? "_" : "", - isStartCharacter - ); -} +import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../../Annotation"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../../ConvenienceRenderer"; +import { DependencyName, type Name, type Namer, funPrefixNamer } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type Sourcelike, maybeAnnotated } from "../../Source"; +import { acronymStyle } from "../../support/Acronyms"; +import { defined } from "../../support/Support"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { type ClassProperty, type ClassType, type EnumType, type Type, type UnionType } from "../../Type"; +import { directlyReachableSingleNamedType, matchType, nullableFromUnion } from "../../TypeUtils"; + +import { type phpOptions } from "./language"; +import { phpNameStyle, stringEscape } from "./utils"; export interface FunctionNames { readonly from: Name; diff --git a/packages/quicktype-core/src/language/Php/index.ts b/packages/quicktype-core/src/language/Php/index.ts new file mode 100644 index 000000000..2e11f2650 --- /dev/null +++ b/packages/quicktype-core/src/language/Php/index.ts @@ -0,0 +1,2 @@ +export { PhpTargetLanguage, phpOptions } from "./language"; +export { PhpRenderer } from "./PhpRenderer"; diff --git a/packages/quicktype-core/src/language/Php/language.ts b/packages/quicktype-core/src/language/Php/language.ts new file mode 100644 index 000000000..cfcfe9654 --- /dev/null +++ b/packages/quicktype-core/src/language/Php/language.ts @@ -0,0 +1,46 @@ +import * as _ from "lodash"; + +import { type RenderContext } from "../../Renderer"; +import { BooleanOption, type Option, getOptionValues } from "../../RendererOptions"; +import { AcronymStyleOptions, acronymOption } from "../../support/Acronyms"; +import { TargetLanguage } from "../../TargetLanguage"; +import { type PrimitiveStringTypeKind, type TransformedStringTypeKind } from "../../Type"; +import { type StringTypeMapping } from "../../TypeBuilder"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; + +import { PhpRenderer } from "./PhpRenderer"; + +export const phpOptions = { + withGet: new BooleanOption("with-get", "Create Getter", true), + fastGet: new BooleanOption("fast-get", "getter without validation", false), + withSet: new BooleanOption("with-set", "Create Setter", false), + withClosing: new BooleanOption("with-closing", "PHP Closing Tag", false), + acronymStyle: acronymOption(AcronymStyleOptions.Pascal) +}; +export class PhpTargetLanguage extends TargetLanguage { + public constructor() { + super("PHP", ["php"], "php"); + } + + protected getOptions(): Array> { + return _.values(phpOptions); + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): PhpRenderer { + const options = getOptionValues(phpOptions, untypedOptionValues); + return new PhpRenderer(this, renderContext, options); + } + + public get stringTypeMapping(): StringTypeMapping { + const mapping: Map = new Map(); + mapping.set("date", "date"); // TODO is not implemented yet + mapping.set("time", "time"); // TODO is not implemented yet + mapping.set("uuid", "uuid"); // TODO is not implemented yet + mapping.set("date-time", "date-time"); + return mapping; + } +} diff --git a/packages/quicktype-core/src/language/Php/utils.ts b/packages/quicktype-core/src/language/Php/utils.ts new file mode 100644 index 000000000..2ccb0e228 --- /dev/null +++ b/packages/quicktype-core/src/language/Php/utils.ts @@ -0,0 +1,48 @@ +import * as _ from "lodash"; + +import { + allLowerWordStyle, + allUpperWordStyle, + combineWords, + escapeNonPrintableMapper, + firstUpperWordStyle, + isAscii, + isDigit, + isLetter, + splitIntoWords, + standardUnicodeHexEscape, + utf16ConcatMap, + utf16LegalizeCharacters +} from "../../support/Strings"; + +export const stringEscape = utf16ConcatMap(escapeNonPrintableMapper(isAscii, standardUnicodeHexEscape)); + +function isStartCharacter(codePoint: number): boolean { + if (codePoint === 0x5f) return true; // underscore + return isAscii(codePoint) && isLetter(codePoint); +} + +function isPartCharacter(codePoint: number): boolean { + return isStartCharacter(codePoint) || (isAscii(codePoint) && isDigit(codePoint)); +} + +const legalizeName = utf16LegalizeCharacters(isPartCharacter); + +export function phpNameStyle( + startWithUpper: boolean, + upperUnderscore: boolean, + original: string, + acronymsStyle: (s: string) => string = allUpperWordStyle +): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + upperUnderscore ? allUpperWordStyle : startWithUpper ? firstUpperWordStyle : allLowerWordStyle, + upperUnderscore ? allUpperWordStyle : firstUpperWordStyle, + upperUnderscore || startWithUpper ? allUpperWordStyle : allLowerWordStyle, + acronymsStyle, + upperUnderscore ? "_" : "", + isStartCharacter + ); +} diff --git a/packages/quicktype-core/src/language/Pike.ts b/packages/quicktype-core/src/language/Pike/PikeRenderer.ts similarity index 81% rename from packages/quicktype-core/src/language/Pike.ts rename to packages/quicktype-core/src/language/Pike/PikeRenderer.ts index ea7f9d3a5..01e383c6e 100644 --- a/packages/quicktype-core/src/language/Pike.ts +++ b/packages/quicktype-core/src/language/Pike/PikeRenderer.ts @@ -1,89 +1,20 @@ -import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { type Name, type Namer, funPrefixNamer } from "../Naming"; -import { type RenderContext } from "../Renderer"; -import { type Option } from "../RendererOptions"; -import { type MultiWord, type Sourcelike, multiWord, parenIfNeeded, singleWord } from "../Source"; -import { isLetterOrUnderscoreOrDigit, legalizeCharacters, makeNameStyle, stringEscape } from "../support/Strings"; -import { TargetLanguage } from "../TargetLanguage"; -import { ArrayType, type ClassType, type EnumType, MapType, PrimitiveType, type Type, type UnionType } from "../Type"; -import { type FixMeOptionsAnyType } from "../types"; -import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; - -export const pikeOptions = {}; - -const keywords = [ - "auto", - "nomask", - "final", - "static", - "extern", - "private", - "local", - "public", - "protected", - "inline", - "optional", - "variant", - "void", - "mixed", - "array", - "__attribute__", - "__deprecated__", - "mapping", - "multiset", - "object", - "function", - "__func__", - "program", - "string", - "float", - "int", - "enum", - "typedef", - "if", - "do", - "for", - "while", - "else", - "foreach", - "catch", - "gauge", - "class", - "break", - "case", - "const", - "constant", - "continue", - "default", - "import", - "inherit", - "lambda", - "predef", - "return", - "sscanf", - "switch", - "typeof", - "global" -]; - -const legalizeName = legalizeCharacters(isLetterOrUnderscoreOrDigit); -const enumNamingFunction = funPrefixNamer("enumNamer", makeNameStyle("upper-underscore", legalizeName)); -const namingFunction = funPrefixNamer("genericNamer", makeNameStyle("underscore", legalizeName)); -const namedTypeNamingFunction = funPrefixNamer("typeNamer", makeNameStyle("pascal", legalizeName)); - -export class PikeTargetLanguage extends TargetLanguage { - public constructor() { - super("Pike", ["pike", "pikelang"], "pmod"); - } - - protected getOptions(): Array> { - return []; - } - - protected makeRenderer(renderContext: RenderContext): PikeRenderer { - return new PikeRenderer(this, renderContext); - } -} +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../../ConvenienceRenderer"; +import { type Name, type Namer } from "../../Naming"; +import { type MultiWord, type Sourcelike, multiWord, parenIfNeeded, singleWord } from "../../Source"; +import { stringEscape } from "../../support/Strings"; +import { + ArrayType, + type ClassType, + type EnumType, + MapType, + PrimitiveType, + type Type, + type UnionType +} from "../../Type"; +import { matchType, nullableFromUnion, removeNullFromUnion } from "../../TypeUtils"; + +import { keywords } from "./constants"; +import { enumNamingFunction, namedTypeNamingFunction, namingFunction } from "./utils"; export class PikeRenderer extends ConvenienceRenderer { protected emitSourceStructure(): void { diff --git a/packages/quicktype-core/src/language/Pike/constants.ts b/packages/quicktype-core/src/language/Pike/constants.ts new file mode 100644 index 000000000..d3927948f --- /dev/null +++ b/packages/quicktype-core/src/language/Pike/constants.ts @@ -0,0 +1,54 @@ +export const keywords = [ + "auto", + "nomask", + "final", + "static", + "extern", + "private", + "local", + "public", + "protected", + "inline", + "optional", + "variant", + "void", + "mixed", + "array", + "__attribute__", + "__deprecated__", + "mapping", + "multiset", + "object", + "function", + "__func__", + "program", + "string", + "float", + "int", + "enum", + "typedef", + "if", + "do", + "for", + "while", + "else", + "foreach", + "catch", + "gauge", + "class", + "break", + "case", + "const", + "constant", + "continue", + "default", + "import", + "inherit", + "lambda", + "predef", + "return", + "sscanf", + "switch", + "typeof", + "global" +] as const; diff --git a/packages/quicktype-core/src/language/Pike/index.ts b/packages/quicktype-core/src/language/Pike/index.ts new file mode 100644 index 000000000..2b80f3674 --- /dev/null +++ b/packages/quicktype-core/src/language/Pike/index.ts @@ -0,0 +1,2 @@ +export { PikeTargetLanguage, pikeOptions } from "./language"; +export { PikeRenderer } from "./PikeRenderer"; diff --git a/packages/quicktype-core/src/language/Pike/language.ts b/packages/quicktype-core/src/language/Pike/language.ts new file mode 100644 index 000000000..1772085a0 --- /dev/null +++ b/packages/quicktype-core/src/language/Pike/language.ts @@ -0,0 +1,22 @@ +import { type RenderContext } from "../../Renderer"; +import { type Option } from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import { type FixMeOptionsAnyType } from "../../types"; + +import { PikeRenderer } from "./PikeRenderer"; + +export const pikeOptions = {}; + +export class PikeTargetLanguage extends TargetLanguage { + public constructor() { + super("Pike", ["pike", "pikelang"], "pmod"); + } + + protected getOptions(): Array> { + return []; + } + + protected makeRenderer(renderContext: RenderContext): PikeRenderer { + return new PikeRenderer(this, renderContext); + } +} diff --git a/packages/quicktype-core/src/language/Pike/utils.ts b/packages/quicktype-core/src/language/Pike/utils.ts new file mode 100644 index 000000000..f097ad2c6 --- /dev/null +++ b/packages/quicktype-core/src/language/Pike/utils.ts @@ -0,0 +1,7 @@ +import { funPrefixNamer } from "../../Naming"; +import { isLetterOrUnderscoreOrDigit, legalizeCharacters, makeNameStyle } from "../../support/Strings"; + +const legalizeName = legalizeCharacters(isLetterOrUnderscoreOrDigit); +export const enumNamingFunction = funPrefixNamer("enumNamer", makeNameStyle("upper-underscore", legalizeName)); +export const namingFunction = funPrefixNamer("genericNamer", makeNameStyle("underscore", legalizeName)); +export const namedTypeNamingFunction = funPrefixNamer("typeNamer", makeNameStyle("pascal", legalizeName)); diff --git a/packages/quicktype-core/src/language/Python.ts b/packages/quicktype-core/src/language/Python/JSONPythonRenderer.ts similarity index 63% rename from packages/quicktype-core/src/language/Python.ts rename to packages/quicktype-core/src/language/Python/JSONPythonRenderer.ts index dc3f5b9e9..28d16eece 100644 --- a/packages/quicktype-core/src/language/Python.ts +++ b/packages/quicktype-core/src/language/Python/JSONPythonRenderer.ts @@ -1,31 +1,9 @@ -import { - arrayIntercalate, - iterableFirst, - iterableSome, - mapSortBy, - mapUpdateInto, - setUnionInto -} from "collection-utils"; -import unicode from "unicode-properties"; - -import { ConvenienceRenderer, type ForbiddenWordsInfo, topLevelNameOrder } from "../ConvenienceRenderer"; -import { DependencyName, type Name, type Namer, funPrefixNamer } from "../Naming"; -import { type RenderContext } from "../Renderer"; -import { BooleanOption, EnumOption, type Option, type OptionValues, getOptionValues } from "../RendererOptions"; -import { type MultiWord, type Sourcelike, modifySource, multiWord, parenIfNeeded, singleWord } from "../Source"; -import { - type WordStyle, - allLowerWordStyle, - allUpperWordStyle, - combineWords, - firstUpperWordStyle, - originalWord, - splitIntoWords, - stringEscape, - utf16LegalizeCharacters -} from "../support/Strings"; -import { assertNever, defined, panic } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; +import { arrayIntercalate } from "collection-utils"; + +import { topLevelNameOrder } from "../../ConvenienceRenderer"; +import { DependencyName, type Name, funPrefixNamer } from "../../Naming"; +import { type MultiWord, type Sourcelike, multiWord, parenIfNeeded, singleWord } from "../../Source"; +import { assertNever, defined, panic } from "../../support/Support"; import { ChoiceTransformer, DecodingChoiceTransformer, @@ -36,512 +14,13 @@ import { type Transformer, UnionInstantiationTransformer, UnionMemberMatchTransformer, - followTargetType, transformationForType -} from "../Transformers"; -import { - type ClassProperty, - ClassType, - EnumType, - type PrimitiveStringTypeKind, - type TransformedStringTypeKind, - type Type, - UnionType -} from "../Type"; -import { type StringTypeMapping } from "../TypeBuilder"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; -import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; - -const forbiddenTypeNames = [ - "Any", - "True", - "False", - "None", - "Enum", - "List", - "Dict", - "Optional", - "Union", - "Iterable", - "Type", - "TypeVar", - "T", - "EnumT" -]; -const forbiddenPropertyNames = [ - "and", - "as", - "assert", - "async", - "await", - "bool", - "break", - "class", - "continue", - "datetime", - "def", - "del", - "dict", - "elif", - "else", - "except", - "finally", - "float", - "for", - "from", - "global", - "if", - "import", - "in", - "int", - "is", - "lambda", - "nonlocal", - "not", - "or", - "pass", - "print", - "raise", - "return", - "self", - "str", - "try", - "while", - "with", - "yield" -]; - -export interface PythonFeatures { - dataClasses: boolean; - typeHints: boolean; -} - -export const pythonOptions = { - features: new EnumOption( - "python-version", - "Python version", - [ - ["3.5", { typeHints: false, dataClasses: false }], - ["3.6", { typeHints: true, dataClasses: false }], - ["3.7", { typeHints: true, dataClasses: true }] - ], - "3.6" - ), - justTypes: new BooleanOption("just-types", "Classes only", false), - nicePropertyNames: new BooleanOption("nice-property-names", "Transform property names to be Pythonic", true) -}; - -export class PythonTargetLanguage extends TargetLanguage { - protected getOptions(): Array> { - return [pythonOptions.features, pythonOptions.justTypes, pythonOptions.nicePropertyNames]; - } - - public get stringTypeMapping(): StringTypeMapping { - const mapping: Map = new Map(); - const dateTimeType = "date-time"; - mapping.set("date", dateTimeType); - mapping.set("time", dateTimeType); - mapping.set("date-time", dateTimeType); - mapping.set("uuid", "uuid"); - mapping.set("integer-string", "integer-string"); - mapping.set("bool-string", "bool-string"); - return mapping; - } - - public get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - public get supportsOptionalClassProperties(): boolean { - return false; - } - - public needsTransformerForType(t: Type): boolean { - if (t instanceof UnionType) { - return iterableSome(t.members, m => this.needsTransformerForType(m)); - } - - return t.kind === "integer-string" || t.kind === "bool-string"; - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): PythonRenderer { - const options = getOptionValues(pythonOptions, untypedOptionValues); - if (options.justTypes) { - return new PythonRenderer(this, renderContext, options); - } else { - return new JSONPythonRenderer(this, renderContext, options); - } - } -} - -function isNormalizedStartCharacter3(utf16Unit: number): boolean { - // FIXME: add Other_ID_Start - https://docs.python.org/3/reference/lexical_analysis.html#identifiers - const category: string = unicode.getCategory(utf16Unit); - return ["Lu", "Ll", "Lt", "Lm", "Lo", "Nl"].includes(category); -} - -function isNormalizedPartCharacter3(utf16Unit: number): boolean { - // FIXME: add Other_ID_Continue - https://docs.python.org/3/reference/lexical_analysis.html#identifiers - if (isNormalizedStartCharacter3(utf16Unit)) return true; - const category: string = unicode.getCategory(utf16Unit); - return ["Mn", "Mc", "Nd", "Pc"].includes(category); -} - -function isStartCharacter3(utf16Unit: number): boolean { - const s = String.fromCharCode(utf16Unit).normalize("NFKC"); - const l = s.length; - if (l === 0 || !isNormalizedStartCharacter3(s.charCodeAt(0))) return false; - for (let i = 1; i < l; i++) { - if (!isNormalizedPartCharacter3(s.charCodeAt(i))) return false; - } - - return true; -} - -function isPartCharacter3(utf16Unit: number): boolean { - const s = String.fromCharCode(utf16Unit).normalize("NFKC"); - const l = s.length; - for (let i = 0; i < l; i++) { - if (!isNormalizedPartCharacter3(s.charCodeAt(i))) return false; - } - - return true; -} - -const legalizeName3 = utf16LegalizeCharacters(isPartCharacter3); - -function classNameStyle(original: string): string { - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName3, - firstUpperWordStyle, - firstUpperWordStyle, - allUpperWordStyle, - allUpperWordStyle, - "", - isStartCharacter3 - ); -} - -function getWordStyle(uppercase: boolean, forceSnakeNameStyle: boolean): WordStyle { - if (!forceSnakeNameStyle) { - return originalWord; - } - - return uppercase ? allUpperWordStyle : allLowerWordStyle; -} - -function snakeNameStyle(original: string, uppercase: boolean, forceSnakeNameStyle: boolean): string { - const wordStyle = getWordStyle(uppercase, forceSnakeNameStyle); - const separator = forceSnakeNameStyle ? "_" : ""; - const words = splitIntoWords(original); - return combineWords(words, legalizeName3, wordStyle, wordStyle, wordStyle, wordStyle, separator, isStartCharacter3); -} - -export class PythonRenderer extends ConvenienceRenderer { - private readonly imports: Map> = new Map(); - - private readonly declaredTypes: Set = new Set(); - - public constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - protected readonly pyOptions: OptionValues - ) { - super(targetLanguage, renderContext); - } - - protected forbiddenNamesForGlobalNamespace(): string[] { - return forbiddenTypeNames; - } - - protected forbiddenForObjectProperties(_: ClassType, _classNamed: Name): ForbiddenWordsInfo { - return { names: forbiddenPropertyNames, includeGlobalForbidden: false }; - } - - protected makeNamedTypeNamer(): Namer { - return funPrefixNamer("type", classNameStyle); - } - - protected namerForObjectProperty(): Namer { - return funPrefixNamer("property", s => snakeNameStyle(s, false, this.pyOptions.nicePropertyNames)); - } - - protected makeUnionMemberNamer(): null { - return null; - } - - protected makeEnumCaseNamer(): Namer { - return funPrefixNamer("enum-case", s => snakeNameStyle(s, true, this.pyOptions.nicePropertyNames)); - } - - protected get commentLineStart(): string { - return "# "; - } - - protected emitDescriptionBlock(lines: Sourcelike[]): void { - if (lines.length === 1) { - const docstring = modifySource(content => { - if (content.endsWith('"')) { - return content.slice(0, -1) + '\\"'; - } - - return content; - }, lines[0]); - this.emitComments([{ customLines: [docstring], lineStart: '"""', lineEnd: '"""' }]); - } else { - this.emitCommentLines(lines, { - firstLineStart: '"""', - lineStart: "", - afterComment: '"""' - }); - } - } - - protected get needsTypeDeclarationBeforeUse(): boolean { - return true; - } - - protected canBeForwardDeclared(t: Type): boolean { - const kind = t.kind; - return kind === "class" || kind === "enum"; - } - - protected emitBlock(line: Sourcelike, f: () => void): void { - this.emitLine(line); - this.indent(f); - } - - protected string(s: string): Sourcelike { - const openQuote = '"'; - return [openQuote, stringEscape(s), '"']; - } - - protected withImport(module: string, name: string): Sourcelike { - if (this.pyOptions.features.typeHints || module !== "typing") { - // FIXME: This is ugly. We should rather not generate that import in the first - // place, but right now we just make the type source and then throw it away. It's - // not a performance issue, so it's fine, I just bemoan this special case, and - // potential others down the road. - mapUpdateInto(this.imports, module, s => (s ? setUnionInto(s, [name]) : new Set([name]))); - } - - return name; - } - - protected withTyping(name: string): Sourcelike { - return this.withImport("typing", name); - } - - protected namedType(t: Type): Sourcelike { - const name = this.nameForNamedType(t); - if (this.declaredTypes.has(t)) return name; - return ["'", name, "'"]; - } - - protected pythonType(t: Type, _isRootTypeDef = false): Sourcelike { - const actualType = followTargetType(t); - - return matchType( - actualType, - _anyType => this.withTyping("Any"), - _nullType => "None", - _boolType => "bool", - _integerType => "int", - _doubletype => "float", - _stringType => "str", - arrayType => [this.withTyping("List"), "[", this.pythonType(arrayType.items), "]"], - classType => this.namedType(classType), - mapType => [this.withTyping("Dict"), "[str, ", this.pythonType(mapType.values), "]"], - enumType => this.namedType(enumType), - unionType => { - const [hasNull, nonNulls] = removeNullFromUnion(unionType); - const memberTypes = Array.from(nonNulls).map(m => this.pythonType(m)); - - if (hasNull !== null) { - let rest: string[] = []; - if (!this.getAlphabetizeProperties() && this.pyOptions.features.dataClasses && _isRootTypeDef) { - // Only push "= None" if this is a root level type def - // otherwise we may get type defs like List[Optional[int] = None] - // which are invalid - rest.push(" = None"); - } - - if (nonNulls.size > 1) { - this.withImport("typing", "Union"); - return [ - this.withTyping("Optional"), - "[Union[", - arrayIntercalate(", ", memberTypes), - "]]", - ...rest - ]; - } else { - return [this.withTyping("Optional"), "[", defined(iterableFirst(memberTypes)), "]", ...rest]; - } - } else { - return [this.withTyping("Union"), "[", arrayIntercalate(", ", memberTypes), "]"]; - } - }, - transformedStringType => { - if (transformedStringType.kind === "date-time") { - return this.withImport("datetime", "datetime"); - } - - if (transformedStringType.kind === "uuid") { - return this.withImport("uuid", "UUID"); - } - - return panic(`Transformed type ${transformedStringType.kind} not supported`); - } - ); - } - - protected declarationLine(t: Type): Sourcelike { - if (t instanceof ClassType) { - return ["class ", this.nameForNamedType(t), ":"]; - } - - if (t instanceof EnumType) { - return ["class ", this.nameForNamedType(t), "(", this.withImport("enum", "Enum"), "):"]; - } - - return panic(`Can't declare type ${t.kind}`); - } +} from "../../Transformers"; +import { type ClassType, type Type } from "../../Type"; +import { matchType } from "../../TypeUtils"; - protected declareType(t: T, emitter: () => void): void { - this.emitBlock(this.declarationLine(t), () => { - this.emitDescription(this.descriptionForType(t)); - emitter(); - }); - this.declaredTypes.add(t); - } - - protected emitClassMembers(t: ClassType): void { - if (this.pyOptions.features.dataClasses) return; - - const args: Sourcelike[] = []; - this.forEachClassProperty(t, "none", (name, _, cp) => { - args.push([name, this.typeHint(": ", this.pythonType(cp.type))]); - }); - this.emitBlock( - ["def __init__(self, ", arrayIntercalate(", ", args), ")", this.typeHint(" -> None"), ":"], - () => { - if (args.length === 0) { - this.emitLine("pass"); - } else { - this.forEachClassProperty(t, "none", name => { - this.emitLine("self.", name, " = ", name); - }); - } - } - ); - } - - protected typeHint(...sl: Sourcelike[]): Sourcelike { - if (this.pyOptions.features.typeHints) { - return sl; - } - - return []; - } - - protected typingDecl(name: Sourcelike, type: string): Sourcelike { - return [name, this.typeHint(": ", this.withTyping(type))]; - } - - protected typingReturn(type: string): Sourcelike { - return this.typeHint(" -> ", this.withTyping(type)); - } - - protected sortClassProperties( - properties: ReadonlyMap, - propertyNames: ReadonlyMap - ): ReadonlyMap { - if (this.pyOptions.features.dataClasses) { - return mapSortBy(properties, (p: ClassProperty) => { - return (p.type instanceof UnionType && nullableFromUnion(p.type) != null) || p.isOptional ? 1 : 0; - }); - } else { - return super.sortClassProperties(properties, propertyNames); - } - } - - protected emitClass(t: ClassType): void { - if (this.pyOptions.features.dataClasses) { - this.emitLine("@", this.withImport("dataclasses", "dataclass")); - } - - this.declareType(t, () => { - if (this.pyOptions.features.typeHints) { - if (t.getProperties().size === 0) { - this.emitLine("pass"); - } else { - this.forEachClassProperty(t, "none", (name, jsonName, cp) => { - this.emitLine(name, this.typeHint(": ", this.pythonType(cp.type, true))); - this.emitDescription(this.descriptionForClassProperty(t, jsonName)); - }); - } - - this.ensureBlankLine(); - } - - this.emitClassMembers(t); - }); - } - - protected emitEnum(t: EnumType): void { - this.declareType(t, () => { - this.forEachEnumCase(t, "none", (name, jsonName) => { - this.emitLine([name, " = ", this.string(jsonName)]); - }); - }); - } - - protected emitImports(): void { - this.imports.forEach((names, module) => { - this.emitLine("from ", module, " import ", Array.from(names).join(", ")); - }); - } - - protected emitSupportCode(): void { - return; - } - - protected emitClosingCode(): void { - return; - } - - protected emitSourceStructure(_givenOutputFilename: string): void { - const declarationLines = this.gatherSource(() => { - this.forEachNamedType( - ["interposing", 2], - (c: ClassType) => this.emitClass(c), - e => this.emitEnum(e), - _u => { - return; - } - ); - }); - - const closingLines = this.gatherSource(() => this.emitClosingCode()); - const supportLines = this.gatherSource(() => this.emitSupportCode()); - - if (this.leadingComments !== undefined) { - this.emitComments(this.leadingComments); - } - - this.ensureBlankLine(); - this.emitImports(); - this.ensureBlankLine(2); - this.emitGatheredSource(supportLines); - this.ensureBlankLine(2); - this.emitGatheredSource(declarationLines); - this.ensureBlankLine(2); - this.emitGatheredSource(closingLines); - } -} +import { PythonRenderer } from "./PythonRenderer"; +import { snakeNameStyle } from "./utils"; export type ConverterFunction = | "none" diff --git a/packages/quicktype-core/src/language/Python/PythonRenderer.ts b/packages/quicktype-core/src/language/Python/PythonRenderer.ts new file mode 100644 index 000000000..63ec3c70d --- /dev/null +++ b/packages/quicktype-core/src/language/Python/PythonRenderer.ts @@ -0,0 +1,321 @@ +import { arrayIntercalate, iterableFirst, mapSortBy, mapUpdateInto, setUnionInto } from "collection-utils"; + +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type Sourcelike, modifySource } from "../../Source"; +import { stringEscape } from "../../support/Strings"; +import { defined, panic } from "../../support/Support"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { followTargetType } from "../../Transformers"; +import { type ClassProperty, ClassType, EnumType, type Type, UnionType } from "../../Type"; +import { matchType, nullableFromUnion, removeNullFromUnion } from "../../TypeUtils"; + +import { forbiddenPropertyNames, forbiddenTypeNames } from "./constants"; +import { type pythonOptions } from "./language"; +import { classNameStyle, snakeNameStyle } from "./utils"; + +export class PythonRenderer extends ConvenienceRenderer { + private readonly imports: Map> = new Map(); + + private readonly declaredTypes: Set = new Set(); + + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + protected readonly pyOptions: OptionValues + ) { + super(targetLanguage, renderContext); + } + + protected forbiddenNamesForGlobalNamespace(): readonly string[] { + return forbiddenTypeNames; + } + + protected forbiddenForObjectProperties(_: ClassType, _classNamed: Name): ForbiddenWordsInfo { + return { names: forbiddenPropertyNames as unknown as string[], includeGlobalForbidden: false }; + } + + protected makeNamedTypeNamer(): Namer { + return funPrefixNamer("type", classNameStyle); + } + + protected namerForObjectProperty(): Namer { + return funPrefixNamer("property", s => snakeNameStyle(s, false, this.pyOptions.nicePropertyNames)); + } + + protected makeUnionMemberNamer(): null { + return null; + } + + protected makeEnumCaseNamer(): Namer { + return funPrefixNamer("enum-case", s => snakeNameStyle(s, true, this.pyOptions.nicePropertyNames)); + } + + protected get commentLineStart(): string { + return "# "; + } + + protected emitDescriptionBlock(lines: Sourcelike[]): void { + if (lines.length === 1) { + const docstring = modifySource(content => { + if (content.endsWith('"')) { + return content.slice(0, -1) + '\\"'; + } + + return content; + }, lines[0]); + this.emitComments([{ customLines: [docstring], lineStart: '"""', lineEnd: '"""' }]); + } else { + this.emitCommentLines(lines, { + firstLineStart: '"""', + lineStart: "", + afterComment: '"""' + }); + } + } + + protected get needsTypeDeclarationBeforeUse(): boolean { + return true; + } + + protected canBeForwardDeclared(t: Type): boolean { + const kind = t.kind; + return kind === "class" || kind === "enum"; + } + + protected emitBlock(line: Sourcelike, f: () => void): void { + this.emitLine(line); + this.indent(f); + } + + protected string(s: string): Sourcelike { + const openQuote = '"'; + return [openQuote, stringEscape(s), '"']; + } + + protected withImport(module: string, name: string): Sourcelike { + if (this.pyOptions.features.typeHints || module !== "typing") { + // FIXME: This is ugly. We should rather not generate that import in the first + // place, but right now we just make the type source and then throw it away. It's + // not a performance issue, so it's fine, I just bemoan this special case, and + // potential others down the road. + mapUpdateInto(this.imports, module, s => (s ? setUnionInto(s, [name]) : new Set([name]))); + } + + return name; + } + + protected withTyping(name: string): Sourcelike { + return this.withImport("typing", name); + } + + protected namedType(t: Type): Sourcelike { + const name = this.nameForNamedType(t); + if (this.declaredTypes.has(t)) return name; + return ["'", name, "'"]; + } + + protected pythonType(t: Type, _isRootTypeDef = false): Sourcelike { + const actualType = followTargetType(t); + + return matchType( + actualType, + _anyType => this.withTyping("Any"), + _nullType => "None", + _boolType => "bool", + _integerType => "int", + _doubletype => "float", + _stringType => "str", + arrayType => [this.withTyping("List"), "[", this.pythonType(arrayType.items), "]"], + classType => this.namedType(classType), + mapType => [this.withTyping("Dict"), "[str, ", this.pythonType(mapType.values), "]"], + enumType => this.namedType(enumType), + unionType => { + const [hasNull, nonNulls] = removeNullFromUnion(unionType); + const memberTypes = Array.from(nonNulls).map(m => this.pythonType(m)); + + if (hasNull !== null) { + let rest: string[] = []; + if (!this.getAlphabetizeProperties() && this.pyOptions.features.dataClasses && _isRootTypeDef) { + // Only push "= None" if this is a root level type def + // otherwise we may get type defs like List[Optional[int] = None] + // which are invalid + rest.push(" = None"); + } + + if (nonNulls.size > 1) { + this.withImport("typing", "Union"); + return [ + this.withTyping("Optional"), + "[Union[", + arrayIntercalate(", ", memberTypes), + "]]", + ...rest + ]; + } else { + return [this.withTyping("Optional"), "[", defined(iterableFirst(memberTypes)), "]", ...rest]; + } + } else { + return [this.withTyping("Union"), "[", arrayIntercalate(", ", memberTypes), "]"]; + } + }, + transformedStringType => { + if (transformedStringType.kind === "date-time") { + return this.withImport("datetime", "datetime"); + } + + if (transformedStringType.kind === "uuid") { + return this.withImport("uuid", "UUID"); + } + + return panic(`Transformed type ${transformedStringType.kind} not supported`); + } + ); + } + + protected declarationLine(t: Type): Sourcelike { + if (t instanceof ClassType) { + return ["class ", this.nameForNamedType(t), ":"]; + } + + if (t instanceof EnumType) { + return ["class ", this.nameForNamedType(t), "(", this.withImport("enum", "Enum"), "):"]; + } + + return panic(`Can't declare type ${t.kind}`); + } + + protected declareType(t: T, emitter: () => void): void { + this.emitBlock(this.declarationLine(t), () => { + this.emitDescription(this.descriptionForType(t)); + emitter(); + }); + this.declaredTypes.add(t); + } + + protected emitClassMembers(t: ClassType): void { + if (this.pyOptions.features.dataClasses) return; + + const args: Sourcelike[] = []; + this.forEachClassProperty(t, "none", (name, _, cp) => { + args.push([name, this.typeHint(": ", this.pythonType(cp.type))]); + }); + this.emitBlock( + ["def __init__(self, ", arrayIntercalate(", ", args), ")", this.typeHint(" -> None"), ":"], + () => { + if (args.length === 0) { + this.emitLine("pass"); + } else { + this.forEachClassProperty(t, "none", name => { + this.emitLine("self.", name, " = ", name); + }); + } + } + ); + } + + protected typeHint(...sl: Sourcelike[]): Sourcelike { + if (this.pyOptions.features.typeHints) { + return sl; + } + + return []; + } + + protected typingDecl(name: Sourcelike, type: string): Sourcelike { + return [name, this.typeHint(": ", this.withTyping(type))]; + } + + protected typingReturn(type: string): Sourcelike { + return this.typeHint(" -> ", this.withTyping(type)); + } + + protected sortClassProperties( + properties: ReadonlyMap, + propertyNames: ReadonlyMap + ): ReadonlyMap { + if (this.pyOptions.features.dataClasses) { + return mapSortBy(properties, (p: ClassProperty) => { + return (p.type instanceof UnionType && nullableFromUnion(p.type) != null) || p.isOptional ? 1 : 0; + }); + } else { + return super.sortClassProperties(properties, propertyNames); + } + } + + protected emitClass(t: ClassType): void { + if (this.pyOptions.features.dataClasses) { + this.emitLine("@", this.withImport("dataclasses", "dataclass")); + } + + this.declareType(t, () => { + if (this.pyOptions.features.typeHints) { + if (t.getProperties().size === 0) { + this.emitLine("pass"); + } else { + this.forEachClassProperty(t, "none", (name, jsonName, cp) => { + this.emitLine(name, this.typeHint(": ", this.pythonType(cp.type, true))); + this.emitDescription(this.descriptionForClassProperty(t, jsonName)); + }); + } + + this.ensureBlankLine(); + } + + this.emitClassMembers(t); + }); + } + + protected emitEnum(t: EnumType): void { + this.declareType(t, () => { + this.forEachEnumCase(t, "none", (name, jsonName) => { + this.emitLine([name, " = ", this.string(jsonName)]); + }); + }); + } + + protected emitImports(): void { + this.imports.forEach((names, module) => { + this.emitLine("from ", module, " import ", Array.from(names).join(", ")); + }); + } + + protected emitSupportCode(): void { + return; + } + + protected emitClosingCode(): void { + return; + } + + protected emitSourceStructure(_givenOutputFilename: string): void { + const declarationLines = this.gatherSource(() => { + this.forEachNamedType( + ["interposing", 2], + (c: ClassType) => this.emitClass(c), + e => this.emitEnum(e), + _u => { + return; + } + ); + }); + + const closingLines = this.gatherSource(() => this.emitClosingCode()); + const supportLines = this.gatherSource(() => this.emitSupportCode()); + + if (this.leadingComments !== undefined) { + this.emitComments(this.leadingComments); + } + + this.ensureBlankLine(); + this.emitImports(); + this.ensureBlankLine(2); + this.emitGatheredSource(supportLines); + this.ensureBlankLine(2); + this.emitGatheredSource(declarationLines); + this.ensureBlankLine(2); + this.emitGatheredSource(closingLines); + } +} diff --git a/packages/quicktype-core/src/language/Python/constants.ts b/packages/quicktype-core/src/language/Python/constants.ts new file mode 100644 index 000000000..0e725bf50 --- /dev/null +++ b/packages/quicktype-core/src/language/Python/constants.ts @@ -0,0 +1,59 @@ +export const forbiddenTypeNames = [ + "Any", + "True", + "False", + "None", + "Enum", + "List", + "Dict", + "Optional", + "Union", + "Iterable", + "Type", + "TypeVar", + "T", + "EnumT" +] as const; + +export const forbiddenPropertyNames = [ + "and", + "as", + "assert", + "async", + "await", + "bool", + "break", + "class", + "continue", + "datetime", + "def", + "del", + "dict", + "elif", + "else", + "except", + "finally", + "float", + "for", + "from", + "global", + "if", + "import", + "in", + "int", + "is", + "lambda", + "nonlocal", + "not", + "or", + "pass", + "print", + "raise", + "return", + "self", + "str", + "try", + "while", + "with", + "yield" +] as const; diff --git a/packages/quicktype-core/src/language/Python/index.ts b/packages/quicktype-core/src/language/Python/index.ts new file mode 100644 index 000000000..7c7b92ba3 --- /dev/null +++ b/packages/quicktype-core/src/language/Python/index.ts @@ -0,0 +1,3 @@ +export { PythonTargetLanguage, pythonOptions } from "./language"; +export { PythonRenderer } from "./PythonRenderer"; +export { JSONPythonRenderer } from "./JSONPythonRenderer"; diff --git a/packages/quicktype-core/src/language/Python/language.ts b/packages/quicktype-core/src/language/Python/language.ts new file mode 100644 index 000000000..e6aac1d87 --- /dev/null +++ b/packages/quicktype-core/src/language/Python/language.ts @@ -0,0 +1,74 @@ +import { iterableSome } from "collection-utils"; + +import { type RenderContext } from "../../Renderer"; +import { BooleanOption, EnumOption, type Option, getOptionValues } from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import { type PrimitiveStringTypeKind, type TransformedStringTypeKind, type Type, UnionType } from "../../Type"; +import { type StringTypeMapping } from "../../TypeBuilder"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; + +import { JSONPythonRenderer } from "./JSONPythonRenderer"; +import { PythonRenderer } from "./PythonRenderer"; + +export interface PythonFeatures { + dataClasses: boolean; + typeHints: boolean; +} + +export const pythonOptions = { + features: new EnumOption( + "python-version", + "Python version", + [ + ["3.5", { typeHints: false, dataClasses: false }], + ["3.6", { typeHints: true, dataClasses: false }], + ["3.7", { typeHints: true, dataClasses: true }] + ], + "3.6" + ), + justTypes: new BooleanOption("just-types", "Classes only", false), + nicePropertyNames: new BooleanOption("nice-property-names", "Transform property names to be Pythonic", true) +}; + +export class PythonTargetLanguage extends TargetLanguage { + protected getOptions(): Array> { + return [pythonOptions.features, pythonOptions.justTypes, pythonOptions.nicePropertyNames]; + } + + public get stringTypeMapping(): StringTypeMapping { + const mapping: Map = new Map(); + const dateTimeType = "date-time"; + mapping.set("date", dateTimeType); + mapping.set("time", dateTimeType); + mapping.set("date-time", dateTimeType); + mapping.set("uuid", "uuid"); + mapping.set("integer-string", "integer-string"); + mapping.set("bool-string", "bool-string"); + return mapping; + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + public get supportsOptionalClassProperties(): boolean { + return false; + } + + public needsTransformerForType(t: Type): boolean { + if (t instanceof UnionType) { + return iterableSome(t.members, m => this.needsTransformerForType(m)); + } + + return t.kind === "integer-string" || t.kind === "bool-string"; + } + + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): PythonRenderer { + const options = getOptionValues(pythonOptions, untypedOptionValues); + if (options.justTypes) { + return new PythonRenderer(this, renderContext, options); + } else { + return new JSONPythonRenderer(this, renderContext, options); + } + } +} diff --git a/packages/quicktype-core/src/language/Python/utils.ts b/packages/quicktype-core/src/language/Python/utils.ts new file mode 100644 index 000000000..6ffb8c5a2 --- /dev/null +++ b/packages/quicktype-core/src/language/Python/utils.ts @@ -0,0 +1,76 @@ +import unicode from "unicode-properties"; + +import { + allLowerWordStyle, + allUpperWordStyle, + combineWords, + firstUpperWordStyle, + originalWord, + splitIntoWords, + utf16LegalizeCharacters +} from "../../support/Strings"; + +function isNormalizedStartCharacter3(utf16Unit: number): boolean { + // FIXME: add Other_ID_Start - https://docs.python.org/3/reference/lexical_analysis.html#identifiers + const category: string = unicode.getCategory(utf16Unit); + return ["Lu", "Ll", "Lt", "Lm", "Lo", "Nl"].includes(category); +} + +function isNormalizedPartCharacter3(utf16Unit: number): boolean { + // FIXME: add Other_ID_Continue - https://docs.python.org/3/reference/lexical_analysis.html#identifiers + if (isNormalizedStartCharacter3(utf16Unit)) return true; + const category: string = unicode.getCategory(utf16Unit); + return ["Mn", "Mc", "Nd", "Pc"].includes(category); +} + +function isStartCharacter3(utf16Unit: number): boolean { + const s = String.fromCharCode(utf16Unit).normalize("NFKC"); + const l = s.length; + if (l === 0 || !isNormalizedStartCharacter3(s.charCodeAt(0))) return false; + for (let i = 1; i < l; i++) { + if (!isNormalizedPartCharacter3(s.charCodeAt(i))) return false; + } + + return true; +} + +function isPartCharacter3(utf16Unit: number): boolean { + const s = String.fromCharCode(utf16Unit).normalize("NFKC"); + const l = s.length; + for (let i = 0; i < l; i++) { + if (!isNormalizedPartCharacter3(s.charCodeAt(i))) return false; + } + + return true; +} + +const legalizeName3 = utf16LegalizeCharacters(isPartCharacter3); + +export function classNameStyle(original: string): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName3, + firstUpperWordStyle, + firstUpperWordStyle, + allUpperWordStyle, + allUpperWordStyle, + "", + isStartCharacter3 + ); +} + +function getWordStyle(uppercase: boolean, forceSnakeNameStyle: boolean) { + if (!forceSnakeNameStyle) { + return originalWord; + } + + return uppercase ? allUpperWordStyle : allLowerWordStyle; +} + +export function snakeNameStyle(original: string, uppercase: boolean, forceSnakeNameStyle: boolean): string { + const wordStyle = getWordStyle(uppercase, forceSnakeNameStyle); + const separator = forceSnakeNameStyle ? "_" : ""; + const words = splitIntoWords(original); + return combineWords(words, legalizeName3, wordStyle, wordStyle, wordStyle, wordStyle, separator, isStartCharacter3); +} diff --git a/packages/quicktype-core/src/language/ruby/index.ts b/packages/quicktype-core/src/language/Ruby/RubyRenderer.ts similarity index 87% rename from packages/quicktype-core/src/language/ruby/index.ts rename to packages/quicktype-core/src/language/Ruby/RubyRenderer.ts index 42466baba..081139193 100644 --- a/packages/quicktype-core/src/language/ruby/index.ts +++ b/packages/quicktype-core/src/language/Ruby/RubyRenderer.ts @@ -1,32 +1,10 @@ -import * as unicode from "unicode-properties"; - import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../../ConvenienceRenderer"; import { type Name, Namer } from "../../Naming"; import { type RenderContext } from "../../Renderer"; -import { - BooleanOption, - EnumOption, - type Option, - type OptionValues, - StringOption, - getOptionValues -} from "../../RendererOptions"; +import { type OptionValues } from "../../RendererOptions"; import { type Sourcelike, modifySource } from "../../Source"; -import { - allLowerWordStyle, - allUpperWordStyle, - combineWords, - escapeNonPrintableMapper, - firstUpperWordStyle, - intToHex, - isLetterOrUnderscore, - isPrintable, - legalizeCharacters, - snakeCase, - splitIntoWords, - utf32ConcatMap -} from "../../support/Strings"; -import { TargetLanguage } from "../../TargetLanguage"; +import { snakeCase } from "../../support/Strings"; +import { type TargetLanguage } from "../../TargetLanguage"; import { ArrayType, type ClassProperty, @@ -36,97 +14,11 @@ import { type Type, type UnionType } from "../../Type"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; import { matchType, nullableFromUnion, removeNullFromUnion } from "../../TypeUtils"; -import * as keywords from "./keywords"; - -const forbiddenForObjectProperties = Array.from(new Set([...keywords.keywords, ...keywords.reservedProperties])); - -function unicodeEscape(codePoint: number): string { - return "\\u{" + intToHex(codePoint, 0) + "}"; -} - -const stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, unicodeEscape)); - -export enum Strictness { - Coercible = "Coercible::", - None = "Types::", - Strict = "Strict::" -} - -export const rubyOptions = { - justTypes: new BooleanOption("just-types", "Plain types only", false), - strictness: new EnumOption("strictness", "Type strictness", [ - ["strict", Strictness.Strict], - ["coercible", Strictness.Coercible], - ["none", Strictness.None] - ]), - namespace: new StringOption("namespace", "Specify a wrapping Namespace", "NAME", "", "secondary") -}; - -export class RubyTargetLanguage extends TargetLanguage { - public constructor() { - super("Ruby", ["ruby"], "rb"); - } - - protected getOptions(): Array> { - return [rubyOptions.justTypes, rubyOptions.strictness, rubyOptions.namespace]; - } - - public get supportsOptionalClassProperties(): boolean { - return true; - } - - protected get defaultIndentation(): string { - return " "; - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): RubyRenderer { - return new RubyRenderer(this, renderContext, getOptionValues(rubyOptions, untypedOptionValues)); - } -} - -const isStartCharacter = isLetterOrUnderscore; - -function isPartCharacter(utf16Unit: number): boolean { - const category: string = unicode.getCategory(utf16Unit); - return ["Nd", "Pc", "Mn", "Mc"].includes(category) || isStartCharacter(utf16Unit); -} - -const legalizeName = legalizeCharacters(isPartCharacter); - -function simpleNameStyle(original: string, uppercase: boolean): string { - if (/^[0-9]+$/.test(original)) { - original = original + "N"; - } - - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - uppercase ? firstUpperWordStyle : allLowerWordStyle, - uppercase ? firstUpperWordStyle : allLowerWordStyle, - allUpperWordStyle, - allUpperWordStyle, - "", - isStartCharacter - ); -} - -function memberNameStyle(original: string): string { - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - allLowerWordStyle, - allLowerWordStyle, - allLowerWordStyle, - allLowerWordStyle, - "_", - isStartCharacter - ); -} +import { globals } from "./constants"; +import { type rubyOptions } from "./language"; +import { Strictness, forbiddenForObjectProperties, memberNameStyle, simpleNameStyle, stringEscape } from "./utils"; export class RubyRenderer extends ConvenienceRenderer { public constructor( @@ -149,8 +41,8 @@ export class RubyRenderer extends ConvenienceRenderer { return "class" === t.kind; } - protected forbiddenNamesForGlobalNamespace(): string[] { - return keywords.globals.concat(["Types", "JSON", "Dry", "Constructor", "Self"]); + protected forbiddenNamesForGlobalNamespace(): readonly string[] { + return [...globals, "Types", "JSON", "Dry", "Constructor", "Self"] as const; } protected forbiddenForObjectProperties(_c: ClassType, _classNamed: Name): ForbiddenWordsInfo { diff --git a/packages/quicktype-core/src/language/ruby/keywords.ts b/packages/quicktype-core/src/language/Ruby/constants.ts similarity index 97% rename from packages/quicktype-core/src/language/ruby/keywords.ts rename to packages/quicktype-core/src/language/Ruby/constants.ts index 0229d9044..9848048f5 100644 --- a/packages/quicktype-core/src/language/ruby/keywords.ts +++ b/packages/quicktype-core/src/language/Ruby/constants.ts @@ -39,8 +39,8 @@ export const keywords = [ "until", "when", "while", - "yield", -]; + "yield" +] as const; const globalClasses = [ "ArgumentError", @@ -133,8 +133,8 @@ const globalClasses = [ "Undefined", "UnicodeNormalize", "Warning", - "ZeroDivisionError", -]; + "ZeroDivisionError" +] as const; const kernel = [ "__callee__", @@ -286,10 +286,10 @@ const kernel = [ "untrace_var", "untrust", "untrusted?", - "warn", -]; + "warn" +] as const; -export const globals = kernel.concat(globalClasses); +export const globals = [...kernel, ...globalClasses] as const; export const reservedProperties = [ "__id__", @@ -355,5 +355,5 @@ export const reservedProperties = [ "undef", "untrust", "while", - "with", -]; + "with" +] as const; diff --git a/packages/quicktype-core/src/language/Ruby/index.ts b/packages/quicktype-core/src/language/Ruby/index.ts new file mode 100644 index 000000000..13ba45f36 --- /dev/null +++ b/packages/quicktype-core/src/language/Ruby/index.ts @@ -0,0 +1,2 @@ +export { RubyTargetLanguage, rubyOptions } from "./language"; +export { RubyRenderer } from "./RubyRenderer"; diff --git a/packages/quicktype-core/src/language/Ruby/language.ts b/packages/quicktype-core/src/language/Ruby/language.ts new file mode 100644 index 000000000..e85598008 --- /dev/null +++ b/packages/quicktype-core/src/language/Ruby/language.ts @@ -0,0 +1,39 @@ +import { type RenderContext } from "../../Renderer"; +import { BooleanOption, EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; + +import { RubyRenderer } from "./RubyRenderer"; +import { Strictness } from "./utils"; + +export const rubyOptions = { + justTypes: new BooleanOption("just-types", "Plain types only", false), + strictness: new EnumOption("strictness", "Type strictness", [ + ["strict", Strictness.Strict], + ["coercible", Strictness.Coercible], + ["none", Strictness.None] + ]), + namespace: new StringOption("namespace", "Specify a wrapping Namespace", "NAME", "", "secondary") +}; + +export class RubyTargetLanguage extends TargetLanguage { + public constructor() { + super("Ruby", ["ruby"], "rb"); + } + + protected getOptions(): Array> { + return [rubyOptions.justTypes, rubyOptions.strictness, rubyOptions.namespace]; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + protected get defaultIndentation(): string { + return " "; + } + + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): RubyRenderer { + return new RubyRenderer(this, renderContext, getOptionValues(rubyOptions, untypedOptionValues)); + } +} diff --git a/packages/quicktype-core/src/language/Ruby/utils.ts b/packages/quicktype-core/src/language/Ruby/utils.ts new file mode 100644 index 000000000..1b78d957c --- /dev/null +++ b/packages/quicktype-core/src/language/Ruby/utils.ts @@ -0,0 +1,71 @@ +import unicode from "unicode-properties"; + +import { + allLowerWordStyle, + allUpperWordStyle, + combineWords, + escapeNonPrintableMapper, + firstUpperWordStyle, + intToHex, + isLetterOrUnderscore, + isPrintable, + legalizeCharacters, + splitIntoWords, + utf32ConcatMap +} from "../../support/Strings"; + +import * as keywords from "./constants"; + +export enum Strictness { + Strict = "Strict::", + Coercible = "Coercible::", + None = "Types::" +} + +export const forbiddenForObjectProperties = Array.from(new Set([...keywords.keywords, ...keywords.reservedProperties])); +function unicodeEscape(codePoint: number): string { + return "\\u{" + intToHex(codePoint, 0) + "}"; +} + +export const stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, unicodeEscape)); + +const isStartCharacter = isLetterOrUnderscore; + +function isPartCharacter(utf16Unit: number): boolean { + const category: string = unicode.getCategory(utf16Unit); + return ["Nd", "Pc", "Mn", "Mc"].includes(category) || isStartCharacter(utf16Unit); +} + +const legalizeName = legalizeCharacters(isPartCharacter); + +export function simpleNameStyle(original: string, uppercase: boolean): string { + if (/^[0-9]+$/.test(original)) { + original = original + "N"; + } + + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + uppercase ? firstUpperWordStyle : allLowerWordStyle, + uppercase ? firstUpperWordStyle : allLowerWordStyle, + allUpperWordStyle, + allUpperWordStyle, + "", + isStartCharacter + ); +} + +export function memberNameStyle(original: string): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + allLowerWordStyle, + allLowerWordStyle, + allLowerWordStyle, + allLowerWordStyle, + "_", + isStartCharacter + ); +} diff --git a/packages/quicktype-core/src/language/Rust.ts b/packages/quicktype-core/src/language/Rust/RustRenderer.ts similarity index 54% rename from packages/quicktype-core/src/language/Rust.ts rename to packages/quicktype-core/src/language/Rust/RustRenderer.ts index 8dcf5b93a..6e0a6653f 100644 --- a/packages/quicktype-core/src/language/Rust.ts +++ b/packages/quicktype-core/src/language/Rust/RustRenderer.ts @@ -1,267 +1,30 @@ /* eslint-disable @typescript-eslint/naming-convention */ import { mapFirst } from "collection-utils"; -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { type Name, type Namer, funPrefixNamer } from "../Naming"; -import { type RenderContext } from "../Renderer"; -import { BooleanOption, EnumOption, type Option, type OptionValues, getOptionValues } from "../RendererOptions"; -import { type Sourcelike, maybeAnnotated } from "../Source"; +import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../../Annotation"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../../ConvenienceRenderer"; +import { type Name, type Namer } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type Sourcelike, maybeAnnotated } from "../../Source"; +import { defined } from "../../support/Support"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { type ClassType, type EnumType, type Type, UnionType } from "../../Type"; +import { matchType, nullableFromUnion, removeNullFromUnion } from "../../TypeUtils"; + +import { keywords } from "./constants"; +import { type rustOptions } from "./language"; import { - allLowerWordStyle, - combineWords, - escapeNonPrintableMapper, - firstUpperWordStyle, - intToHex, - isAscii, - isLetterOrUnderscore, - isLetterOrUnderscoreOrDigit, - isPrintable, - legalizeCharacters, - splitIntoWords, - utf32ConcatMap -} from "../support/Strings"; -import { defined } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; -import { type ClassType, type EnumType, type Type, UnionType } from "../Type"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; -import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; - -export enum Density { - Normal = "Normal", - Dense = "Dense" -} - -export enum Visibility { - Private = "Private", - Crate = "Crate", - Public = "Public" -} - -export const rustOptions = { - density: new EnumOption("density", "Density", [ - ["normal", Density.Normal], - ["dense", Density.Dense] - ]), - visibility: new EnumOption("visibility", "Field visibility", [ - ["private", Visibility.Private], - ["crate", Visibility.Crate], - ["public", Visibility.Public] - ]), - deriveDebug: new BooleanOption("derive-debug", "Derive Debug impl", false), - deriveClone: new BooleanOption("derive-clone", "Derive Clone impl", false), - derivePartialEq: new BooleanOption("derive-partial-eq", "Derive PartialEq impl", false), - skipSerializingNone: new BooleanOption("skip-serializing-none", "Skip serializing empty Option fields", false), - edition2018: new BooleanOption("edition-2018", "Edition 2018", true), - leadingComments: new BooleanOption("leading-comments", "Leading Comments", true) -}; - -type NameToParts = (name: string) => string[]; -type PartsToName = (parts: string[]) => string; -interface NamingStyle { - fromParts: PartsToName; - regex: RegExp; - toParts: NameToParts; -} - -const namingStyles: Record = { - snake_case: { - regex: /^[a-z][a-z0-9]*(_[a-z0-9]+)*$/, - toParts: (name: string): string[] => name.split("_"), - fromParts: (parts: string[]): string => parts.map(p => p.toLowerCase()).join("_") - }, - SCREAMING_SNAKE_CASE: { - regex: /^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$/, - toParts: (name: string): string[] => name.split("_"), - fromParts: (parts: string[]): string => parts.map(p => p.toUpperCase()).join("_") - }, - camelCase: { - regex: /^[a-z]+([A-Z0-9][a-z]*)*$/, - toParts: (name: string): string[] => namingStyles.snake_case.toParts(name.replace(/(.)([A-Z])/g, "$1_$2")), - fromParts: (parts: string[]): string => - parts - .map((p, i) => - i === 0 ? p.toLowerCase() : p.substring(0, 1).toUpperCase() + p.substring(1).toLowerCase() - ) - .join("") - }, - PascalCase: { - regex: /^[A-Z][a-z]*([A-Z0-9][a-z]*)*$/, - toParts: (name: string): string[] => namingStyles.snake_case.toParts(name.replace(/(.)([A-Z])/g, "$1_$2")), - fromParts: (parts: string[]): string => - parts.map(p => p.substring(0, 1).toUpperCase() + p.substring(1).toLowerCase()).join("") - }, - "kebab-case": { - regex: /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/, - toParts: (name: string): string[] => name.split("-"), - fromParts: (parts: string[]): string => parts.map(p => p.toLowerCase()).join("-") - }, - "SCREAMING-KEBAB-CASE": { - regex: /^[A-Z][A-Z0-9]*(-[A-Z0-9]+)*$/, - toParts: (name: string): string[] => name.split("-"), - fromParts: (parts: string[]): string => parts.map(p => p.toUpperCase()).join("-") - }, - lowercase: { - regex: /^[a-z][a-z0-9]*$/, - toParts: (name: string): string[] => [name], - fromParts: (parts: string[]): string => parts.map(p => p.toLowerCase()).join("") - }, - UPPERCASE: { - regex: /^[A-Z][A-Z0-9]*$/, - toParts: (name: string): string[] => [name], - fromParts: (parts: string[]): string => parts.map(p => p.toUpperCase()).join("") - } -}; - -export class RustTargetLanguage extends TargetLanguage { - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): RustRenderer { - return new RustRenderer(this, renderContext, getOptionValues(rustOptions, untypedOptionValues)); - } - - public constructor() { - super("Rust", ["rust", "rs", "rustlang"], "rs"); - } - - protected getOptions(): Array> { - return [ - rustOptions.density, - rustOptions.visibility, - rustOptions.deriveDebug, - rustOptions.deriveClone, - rustOptions.derivePartialEq, - rustOptions.edition2018, - rustOptions.leadingComments, - rustOptions.skipSerializingNone - ]; - } -} - -const keywords = [ - "Serialize", - "Deserialize", - - // Special reserved identifiers used internally for elided lifetimes, - // unnamed method parameters, crate root module, error recovery etc. - "{{root}}", - "$crate", - - // Keywords used in the language. - "as", - "async", - "box", - "break", - "const", - "continue", - "crate", - "else", - "enum", - "extern", - "false", - "fn", - "for", - "if", - "impl", - "in", - "let", - "loop", - "match", - "mod", - "move", - "mut", - "pub", - "ref", - "return", - "self", - "Self", - "static", - "struct", - "super", - "trait", - "true", - "type", - "unsafe", - "use", - "where", - "while", - - // Keywords reserved for future use. - "abstract", - "alignof", - "become", - "do", - "final", - "macro", - "offsetof", - "override", - "priv", - "proc", - "pure", - "sizeof", - "typeof", - "unsized", - "virtual", - "yield", - - // Weak keywords, have special meaning only in specific contexts. - "catch", - "default", - "dyn", - "'static", - "union", - - // Conflict between `std::Option` and potentially generated Option - "option" -]; - -const isAsciiLetterOrUnderscoreOrDigit = (codePoint: number): boolean => { - if (!isAscii(codePoint)) { - return false; - } - - return isLetterOrUnderscoreOrDigit(codePoint); -}; - -const isAsciiLetterOrUnderscore = (codePoint: number): boolean => { - if (!isAscii(codePoint)) { - return false; - } - - return isLetterOrUnderscore(codePoint); -}; - -const legalizeName = legalizeCharacters(isAsciiLetterOrUnderscoreOrDigit); - -function rustStyle(original: string, isSnakeCase: boolean): string { - const words = splitIntoWords(original); - - const wordStyle = isSnakeCase ? allLowerWordStyle : firstUpperWordStyle; - - const combined = combineWords( - words, - legalizeName, - wordStyle, - wordStyle, - wordStyle, - wordStyle, - isSnakeCase ? "_" : "", - isAsciiLetterOrUnderscore - ); - - return combined === "_" ? "_underscore" : combined; -} - -const snakeNamingFunction = funPrefixNamer("default", (original: string) => rustStyle(original, true)); -const camelNamingFunction = funPrefixNamer("camel", (original: string) => rustStyle(original, false)); - -const standardUnicodeRustEscape = (codePoint: number): string => { - if (codePoint <= 0xffff) { - return "\\u{" + intToHex(codePoint, 4) + "}"; - } else { - return "\\u{" + intToHex(codePoint, 6) + "}"; - } -}; - -const rustStringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, standardUnicodeRustEscape)); + Density, + Visibility, + camelNamingFunction, + getPreferedNamingStyle, + listMatchingNamingStyles, + nameToNamingStyle, + namingStyles, + rustStringEscape, + snakeNamingFunction +} from "./utils"; export class RustRenderer extends ConvenienceRenderer { public constructor( @@ -288,7 +51,7 @@ export class RustRenderer extends ConvenienceRenderer { return camelNamingFunction; } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace(): readonly string[] { return keywords; } @@ -548,36 +311,3 @@ export class RustRenderer extends ConvenienceRenderer { ); } } - -function getPreferedNamingStyle(namingStyleOccurences: string[], defaultStyle: string): string { - const occurrences = Object.fromEntries(Object.keys(namingStyles).map(key => [key, 0])); - namingStyleOccurences.forEach(style => ++occurrences[style]); - const max = Math.max(...Object.values(occurrences)); - const preferedStyles = Object.entries(occurrences) - .filter(([_style, num]) => num === max) - .map(([style, _num]) => style); - if (preferedStyles.includes(defaultStyle)) { - return defaultStyle; - } - - return preferedStyles[0]; -} - -function listMatchingNamingStyles(name: string): string[] { - return Object.entries(namingStyles) - .filter(([_, { regex }]) => regex.test(name)) - .map(([namingStyle, _]) => namingStyle); -} - -function nameToNamingStyle(name: string, style: string): string { - if (namingStyles[style].regex.test(name)) { - return name; - } - - const fromStyle = listMatchingNamingStyles(name)[0]; - if (fromStyle === undefined) { - return name; - } - - return namingStyles[style].fromParts(namingStyles[fromStyle].toParts(name)); -} diff --git a/packages/quicktype-core/src/language/Rust/constants.ts b/packages/quicktype-core/src/language/Rust/constants.ts new file mode 100644 index 000000000..8ba3d3eb8 --- /dev/null +++ b/packages/quicktype-core/src/language/Rust/constants.ts @@ -0,0 +1,76 @@ +export const keywords = [ + "Serialize", + "Deserialize", + + // Special reserved identifiers used internally for elided lifetimes, + // unnamed method parameters, crate root module, error recovery etc. + "{{root}}", + "$crate", + + // Keywords used in the language. + "as", + "async", + "box", + "break", + "const", + "continue", + "crate", + "else", + "enum", + "extern", + "false", + "fn", + "for", + "if", + "impl", + "in", + "let", + "loop", + "match", + "mod", + "move", + "mut", + "pub", + "ref", + "return", + "self", + "Self", + "static", + "struct", + "super", + "trait", + "true", + "type", + "unsafe", + "use", + "where", + "while", + + // Keywords reserved for future use. + "abstract", + "alignof", + "become", + "do", + "final", + "macro", + "offsetof", + "override", + "priv", + "proc", + "pure", + "sizeof", + "typeof", + "unsized", + "virtual", + "yield", + + // Weak keywords, have special meaning only in specific contexts. + "catch", + "default", + "dyn", + "'static", + "union", + + // Conflict between `std::Option` and potentially generated Option + "option" +] as const; diff --git a/packages/quicktype-core/src/language/Rust/index.ts b/packages/quicktype-core/src/language/Rust/index.ts new file mode 100644 index 000000000..456ae1274 --- /dev/null +++ b/packages/quicktype-core/src/language/Rust/index.ts @@ -0,0 +1,2 @@ +export { RustTargetLanguage, rustOptions } from "./language"; +export { RustRenderer } from "./RustRenderer"; diff --git a/packages/quicktype-core/src/language/Rust/language.ts b/packages/quicktype-core/src/language/Rust/language.ts new file mode 100644 index 000000000..2f62883ea --- /dev/null +++ b/packages/quicktype-core/src/language/Rust/language.ts @@ -0,0 +1,48 @@ +import { type RenderContext } from "../../Renderer"; +import { BooleanOption, EnumOption, type Option, getOptionValues } from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; + +import { RustRenderer } from "./RustRenderer"; +import { Density, Visibility } from "./utils"; + +export const rustOptions = { + density: new EnumOption("density", "Density", [ + ["normal", Density.Normal], + ["dense", Density.Dense] + ]), + visibility: new EnumOption("visibility", "Field visibility", [ + ["private", Visibility.Private], + ["crate", Visibility.Crate], + ["public", Visibility.Public] + ]), + deriveDebug: new BooleanOption("derive-debug", "Derive Debug impl", false), + deriveClone: new BooleanOption("derive-clone", "Derive Clone impl", false), + derivePartialEq: new BooleanOption("derive-partial-eq", "Derive PartialEq impl", false), + skipSerializingNone: new BooleanOption("skip-serializing-none", "Skip serializing empty Option fields", false), + edition2018: new BooleanOption("edition-2018", "Edition 2018", true), + leadingComments: new BooleanOption("leading-comments", "Leading Comments", true) +}; + +export class RustTargetLanguage extends TargetLanguage { + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): RustRenderer { + return new RustRenderer(this, renderContext, getOptionValues(rustOptions, untypedOptionValues)); + } + + public constructor() { + super("Rust", ["rust", "rs", "rustlang"], "rs"); + } + + protected getOptions(): Array> { + return [ + rustOptions.density, + rustOptions.visibility, + rustOptions.deriveDebug, + rustOptions.deriveClone, + rustOptions.derivePartialEq, + rustOptions.edition2018, + rustOptions.leadingComments, + rustOptions.skipSerializingNone + ]; + } +} diff --git a/packages/quicktype-core/src/language/Rust/utils.ts b/packages/quicktype-core/src/language/Rust/utils.ts new file mode 100644 index 000000000..1b086f545 --- /dev/null +++ b/packages/quicktype-core/src/language/Rust/utils.ts @@ -0,0 +1,166 @@ +import { funPrefixNamer } from "../../Naming"; +import { + allLowerWordStyle, + combineWords, + escapeNonPrintableMapper, + firstUpperWordStyle, + intToHex, + isAscii, + isLetterOrUnderscore, + isLetterOrUnderscoreOrDigit, + isPrintable, + legalizeCharacters, + splitIntoWords, + utf32ConcatMap +} from "../../support/Strings"; + +export enum Density { + Normal = "Normal", + Dense = "Dense" +} + +export enum Visibility { + Private = "Private", + Crate = "Crate", + Public = "Public" +} + +type NameToParts = (name: string) => string[]; +type PartsToName = (parts: string[]) => string; +interface NamingStyle { + fromParts: PartsToName; + regex: RegExp; + toParts: NameToParts; +} + +export const namingStyles: Record = { + snake_case: { + regex: /^[a-z][a-z0-9]*(_[a-z0-9]+)*$/, + toParts: (name: string): string[] => name.split("_"), + fromParts: (parts: string[]): string => parts.map(p => p.toLowerCase()).join("_") + }, + SCREAMING_SNAKE_CASE: { + regex: /^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$/, + toParts: (name: string): string[] => name.split("_"), + fromParts: (parts: string[]): string => parts.map(p => p.toUpperCase()).join("_") + }, + camelCase: { + regex: /^[a-z]+([A-Z0-9][a-z]*)*$/, + toParts: (name: string): string[] => namingStyles.snake_case.toParts(name.replace(/(.)([A-Z])/g, "$1_$2")), + fromParts: (parts: string[]): string => + parts + .map((p, i) => + i === 0 ? p.toLowerCase() : p.substring(0, 1).toUpperCase() + p.substring(1).toLowerCase() + ) + .join("") + }, + PascalCase: { + regex: /^[A-Z][a-z]*([A-Z0-9][a-z]*)*$/, + toParts: (name: string): string[] => namingStyles.snake_case.toParts(name.replace(/(.)([A-Z])/g, "$1_$2")), + fromParts: (parts: string[]): string => + parts.map(p => p.substring(0, 1).toUpperCase() + p.substring(1).toLowerCase()).join("") + }, + "kebab-case": { + regex: /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/, + toParts: (name: string): string[] => name.split("-"), + fromParts: (parts: string[]): string => parts.map(p => p.toLowerCase()).join("-") + }, + "SCREAMING-KEBAB-CASE": { + regex: /^[A-Z][A-Z0-9]*(-[A-Z0-9]+)*$/, + toParts: (name: string): string[] => name.split("-"), + fromParts: (parts: string[]): string => parts.map(p => p.toUpperCase()).join("-") + }, + lowercase: { + regex: /^[a-z][a-z0-9]*$/, + toParts: (name: string): string[] => [name], + fromParts: (parts: string[]): string => parts.map(p => p.toLowerCase()).join("") + }, + UPPERCASE: { + regex: /^[A-Z][A-Z0-9]*$/, + toParts: (name: string): string[] => [name], + fromParts: (parts: string[]): string => parts.map(p => p.toUpperCase()).join("") + } +}; + +const isAsciiLetterOrUnderscoreOrDigit = (codePoint: number): boolean => { + if (!isAscii(codePoint)) { + return false; + } + + return isLetterOrUnderscoreOrDigit(codePoint); +}; + +const isAsciiLetterOrUnderscore = (codePoint: number): boolean => { + if (!isAscii(codePoint)) { + return false; + } + + return isLetterOrUnderscore(codePoint); +}; + +const legalizeName = legalizeCharacters(isAsciiLetterOrUnderscoreOrDigit); + +function rustStyle(original: string, isSnakeCase: boolean): string { + const words = splitIntoWords(original); + + const wordStyle = isSnakeCase ? allLowerWordStyle : firstUpperWordStyle; + + const combined = combineWords( + words, + legalizeName, + wordStyle, + wordStyle, + wordStyle, + wordStyle, + isSnakeCase ? "_" : "", + isAsciiLetterOrUnderscore + ); + + return combined === "_" ? "_underscore" : combined; +} + +export const snakeNamingFunction = funPrefixNamer("default", (original: string) => rustStyle(original, true)); +export const camelNamingFunction = funPrefixNamer("camel", (original: string) => rustStyle(original, false)); + +const standardUnicodeRustEscape = (codePoint: number): string => { + if (codePoint <= 0xffff) { + return "\\u{" + intToHex(codePoint, 4) + "}"; + } else { + return "\\u{" + intToHex(codePoint, 6) + "}"; + } +}; + +export const rustStringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, standardUnicodeRustEscape)); + +export function getPreferedNamingStyle(namingStyleOccurences: string[], defaultStyle: string): string { + const occurrences = Object.fromEntries(Object.keys(namingStyles).map(key => [key, 0])); + namingStyleOccurences.forEach(style => ++occurrences[style]); + const max = Math.max(...Object.values(occurrences)); + const preferedStyles = Object.entries(occurrences) + .filter(([_style, num]) => num === max) + .map(([style, _num]) => style); + if (preferedStyles.includes(defaultStyle)) { + return defaultStyle; + } + + return preferedStyles[0]; +} + +export function listMatchingNamingStyles(name: string): string[] { + return Object.entries(namingStyles) + .filter(([_, { regex }]) => regex.test(name)) + .map(([namingStyle, _]) => namingStyle); +} + +export function nameToNamingStyle(name: string, style: string): string { + if (namingStyles[style].regex.test(name)) { + return name; + } + + const fromStyle = listMatchingNamingStyles(name)[0]; + if (fromStyle === undefined) { + return name; + } + + return namingStyles[style].fromParts(namingStyles[fromStyle].toParts(name)); +} diff --git a/packages/quicktype-core/src/language/Scala3.ts b/packages/quicktype-core/src/language/Scala3.ts deleted file mode 100644 index 75da0773f..000000000 --- a/packages/quicktype-core/src/language/Scala3.ts +++ /dev/null @@ -1,721 +0,0 @@ -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { type Name, type Namer, funPrefixNamer } from "../Naming"; -import { type RenderContext } from "../Renderer"; -import { EnumOption, type Option, type OptionValues, StringOption, getOptionValues } from "../RendererOptions"; -import { type Sourcelike, maybeAnnotated } from "../Source"; -import { - allLowerWordStyle, - allUpperWordStyle, - combineWords, - firstUpperWordStyle, - isDigit, - isLetterOrUnderscore, - isNumeric, - legalizeCharacters, - splitIntoWords -} from "../support/Strings"; -import { assertNever } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; -import { - ArrayType, - type ClassProperty, - type ClassType, - type EnumType, - MapType, - type ObjectType, - type Type, - type UnionType -} from "../Type"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; -import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; - -export enum Framework { - None = "None", - Upickle = "Upickle", - Circe = "Circe" -} - -export const scala3Options = { - framework: new EnumOption( - "framework", - "Serialization framework", - [ - ["just-types", Framework.None], - ["circe", Framework.Circe], - ["upickle", Framework.Upickle] - ], - undefined - ), - packageName: new StringOption("package", "Package", "PACKAGE", "quicktype") -}; - -// Use backticks for param names with symbols -const invalidSymbols = [ - ":", - "-", - "+", - "!", - "@", - "#", - "$", - "%", - "^", - "&", - "*", - "(", - ")", - ">", - "<", - "/", - ";", - "'", - '"', - "{", - "}", - ":", - "~", - "`", - "." -]; - -const keywords = [ - "abstract", - "case", - "catch", - "class", - "def", - "do", - "else", - "enum", - "extends", - "export", - "false", - "final", - "finally", - "for", - "forSome", - "if", - "implicit", - "import", - "lazy", - "match", - "new", - "null", - "object", - "override", - "package", - "private", - "protected", - "return", - "sealed", - "super", - "this", - "then", - "throw", - "trait", - "try", - "true", - "type", - "val", - "var", - "while", - "with", - "yield", - "Any", - "Boolean", - "Double", - "Float", - "Long", - "Int", - "Short", - "System", - "Byte", - "String", - "Array", - "List", - "Map", - "Enum" -]; - -/** - * Check if given parameter name should be wrapped in a backtick - * @param paramName - */ -const shouldAddBacktick = (paramName: string): boolean => { - return ( - keywords.some(s => paramName === s) || - invalidSymbols.some(s => paramName.includes(s)) || - !isNaN(+parseFloat(paramName)) || - !isNaN(parseInt(paramName.charAt(0))) - ); -}; - -const wrapOption = (s: string, optional: boolean): string => { - if (optional) { - return "Option[" + s + "]"; - } else { - return s; - } -}; - -function isPartCharacter(codePoint: number): boolean { - return isLetterOrUnderscore(codePoint) || isNumeric(codePoint); -} - -function isStartCharacter(codePoint: number): boolean { - return isPartCharacter(codePoint) && !isDigit(codePoint); -} - -const legalizeName = legalizeCharacters(isPartCharacter); - -function scalaNameStyle(isUpper: boolean, original: string): string { - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - isUpper ? firstUpperWordStyle : allLowerWordStyle, - firstUpperWordStyle, - isUpper ? allUpperWordStyle : allLowerWordStyle, - allUpperWordStyle, - "", - isStartCharacter - ); -} - -/* function unicodeEscape(codePoint: number): string { - return "\\u" + intToHex(codePoint, 4); -} */ - -// const _stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, unicodeEscape)); - -/* function stringEscape(s: string): string { - // "$this" is a template string in Kotlin so we have to escape $ - return _stringEscape(s).replace(/\$/g, "\\$"); -} */ - -const upperNamingFunction = funPrefixNamer("upper", s => scalaNameStyle(true, s)); -const lowerNamingFunction = funPrefixNamer("lower", s => scalaNameStyle(false, s)); - -export class Scala3Renderer extends ConvenienceRenderer { - public constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - protected readonly _scalaOptions: OptionValues - ) { - super(targetLanguage, renderContext); - } - - protected forbiddenNamesForGlobalNamespace(): string[] { - return keywords; - } - - protected forbiddenForObjectProperties(_: ObjectType, _classNamed: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: true }; - } - - protected forbiddenForEnumCases(_: EnumType, _enumName: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: true }; - } - - protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: false }; - } - - protected topLevelNameStyle(rawName: string): string { - return scalaNameStyle(true, rawName); - } - - protected makeNamedTypeNamer(): Namer { - return upperNamingFunction; - } - - protected namerForObjectProperty(): Namer { - return lowerNamingFunction; - } - - protected makeUnionMemberNamer(): Namer { - return funPrefixNamer("upper", s => scalaNameStyle(true, s) + "Value"); - } - - protected makeEnumCaseNamer(): Namer { - return funPrefixNamer("upper", s => s.replace(" ", "")); // TODO - add backticks where appropriate - } - - protected emitDescriptionBlock(lines: Sourcelike[]): void { - this.emitCommentLines(lines, { lineStart: " * ", beforeComment: "/**", afterComment: " */" }); - } - - protected emitBlock( - line: Sourcelike, - f: () => void, - delimiter: "curly" | "paren" | "lambda" | "none" = "curly" - ): void { - const [open, close] = - delimiter === "curly" - ? ["{", "}"] - : delimiter === "paren" - ? ["(", ")"] - : delimiter === "none" - ? ["", ""] - : ["{", "})"]; - this.emitLine(line, " ", open); - this.indent(f); - this.emitLine(close); - } - - protected anySourceType(optional: boolean): Sourcelike { - return [wrapOption("Any", optional)]; - } - - // (asarazan): I've broken out the following two functions - // because some renderers, such as kotlinx, can cope with `any`, while some get mad. - protected arrayType(arrayType: ArrayType, withIssues = false): Sourcelike { - return ["Seq[", this.scalaType(arrayType.items, withIssues), "]"]; - } - - protected mapType(mapType: MapType, withIssues = false): Sourcelike { - return ["Map[String, ", this.scalaType(mapType.values, withIssues), "]"]; - } - - protected scalaType(t: Type, withIssues = false, noOptional = false): Sourcelike { - return matchType( - t, - _anyType => { - return maybeAnnotated(withIssues, anyTypeIssueAnnotation, this.anySourceType(!noOptional)); - }, - _nullType => { - // return "None.type" - return maybeAnnotated(withIssues, nullTypeIssueAnnotation, this.anySourceType(!noOptional)); - }, - _boolType => "Boolean", - _integerType => "Long", - _doubleType => "Double", - _stringType => "String", - arrayType => this.arrayType(arrayType, withIssues), - classType => this.nameForNamedType(classType), - mapType => this.mapType(mapType, withIssues), - enumType => this.nameForNamedType(enumType), - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) { - if (noOptional) { - return [this.scalaType(nullable, withIssues)]; - } else { - return ["Option[", this.scalaType(nullable, withIssues), "]"]; - } - } - - return this.nameForNamedType(unionType); - } - ); - } - - protected emitUsageHeader(): void { - // To be overridden - } - - protected emitHeader(): void { - if (this.leadingComments !== undefined) { - this.emitComments(this.leadingComments); - } else { - this.emitUsageHeader(); - } - - this.ensureBlankLine(); - this.emitLine("package ", this._scalaOptions.packageName); - this.ensureBlankLine(); - } - - protected emitTopLevelArray(t: ArrayType, name: Name): void { - const elementType = this.scalaType(t.items); - this.emitLine(["type ", name, " = List[", elementType, "]"]); - } - - protected emitTopLevelMap(t: MapType, name: Name): void { - const elementType = this.scalaType(t.values); - this.emitLine(["type ", name, " = Map[String, ", elementType, "]"]); - } - - protected emitEmptyClassDefinition(c: ClassType, className: Name): void { - this.emitDescription(this.descriptionForType(c)); - this.emitLine("case class ", className, "()"); - } - - protected emitClassDefinition(c: ClassType, className: Name): void { - if (c.getProperties().size === 0) { - this.emitEmptyClassDefinition(c, className); - return; - } - - const scalaType = (p: ClassProperty): Sourcelike => { - if (p.isOptional) { - return ["Option[", this.scalaType(p.type, true, true), "]"]; - } else { - return this.scalaType(p.type, true); - } - }; - - this.emitDescription(this.descriptionForType(c)); - this.emitLine("case class ", className, " ("); - this.indent(() => { - let count = c.getProperties().size; - let first = true; - this.forEachClassProperty(c, "none", (_, jsonName, p) => { - const nullable = p.type.kind === "union" && nullableFromUnion(p.type as UnionType) !== null; - const nullableOrOptional = p.isOptional || p.type.kind === "null" || nullable; - const last = --count === 0; - const meta: Array<() => void> = []; - - const description = this.descriptionForClassProperty(c, jsonName); - if (description !== undefined) { - meta.push(() => this.emitDescription(description)); - } - - if (meta.length > 0 && !first) { - this.ensureBlankLine(); - } - - for (const emit of meta) { - emit(); - } - - const nameNeedsBackticks = jsonName.endsWith("_") || shouldAddBacktick(jsonName); - const nameWithBackticks = nameNeedsBackticks ? "`" + jsonName + "`" : jsonName; - this.emitLine( - "val ", - nameWithBackticks, - " : ", - scalaType(p), - p.isOptional ? " = None" : nullableOrOptional ? " = None" : "", - last ? "" : "," - ); - - if (meta.length > 0 && !last) { - this.ensureBlankLine(); - } - - first = false; - }); - }); - - this.emitClassDefinitionMethods(); - } - - protected emitClassDefinitionMethods(): void { - this.emitLine(")"); - } - - protected emitEnumDefinition(e: EnumType, enumName: Name): void { - this.emitDescription(this.descriptionForType(e)); - - this.emitBlock( - ["enum ", enumName, " : "], - () => { - let count = e.cases.size; - if (count > 0) { - this.emitItem("\t case "); - } - - this.forEachEnumCase(e, "none", (name, jsonName) => { - if (!(jsonName == "")) { - const backticks = - shouldAddBacktick(jsonName) || - jsonName.includes(" ") || - !isNaN(parseInt(jsonName.charAt(0))); - if (backticks) { - this.emitItem("`"); - } - - this.emitItemOnce([name]); - if (backticks) { - this.emitItem("`"); - } - - if (--count > 0) this.emitItem([","]); - } else { - --count; - } - }); - }, - "none" - ); - } - - protected emitUnionDefinition(u: UnionType, unionName: Name): void { - function sortBy(t: Type): string { - const kind = t.kind; - if (kind === "class") return kind; - return "_" + kind; - } - - this.emitDescription(this.descriptionForType(u)); - - const [maybeNull, nonNulls] = removeNullFromUnion(u, sortBy); - const theTypes: Sourcelike[] = []; - this.forEachUnionMember(u, nonNulls, "none", null, (_, t) => { - theTypes.push(this.scalaType(t)); - }); - if (maybeNull !== null) { - theTypes.push(this.nameForUnionMember(u, maybeNull)); - } - - this.emitItem(["type ", unionName, " = "]); - theTypes.forEach((t, i) => { - this.emitItem(i === 0 ? t : [" | ", t]); - }); - this.ensureBlankLine(); - } - - protected emitSourceStructure(): void { - this.emitHeader(); - - // Top-level arrays, maps - this.forEachTopLevel("leading", (t, name) => { - if (t instanceof ArrayType) { - this.emitTopLevelArray(t, name); - } else if (t instanceof MapType) { - this.emitTopLevelMap(t, name); - } - }); - - this.forEachNamedType( - "leading-and-interposing", - (c: ClassType, n: Name) => this.emitClassDefinition(c, n), - (e, n) => this.emitEnumDefinition(e, n), - (u, n) => this.emitUnionDefinition(u, n) - ); - } -} - -export class UpickleRenderer extends Scala3Renderer { - protected emitClassDefinitionMethods(): void { - this.emitLine(") derives ReadWriter "); - } - - protected emitHeader(): void { - super.emitHeader(); - - this.emitLine("import upickle.default.*"); - this.ensureBlankLine(); - } -} - -export class CirceRenderer extends Scala3Renderer { - private seenUnionTypes: string[] = []; - - protected circeEncoderForType(t: Type, __ = false, noOptional = false, paramName: string = ""): Sourcelike { - return matchType( - t, - _anyType => ["Encoder.encodeJson(", paramName, ")"], - _nullType => ["Encoder.encodeNone(", paramName, ")"], - _boolType => ["Encoder.encodeBoolean(", paramName, ")"], - _integerType => ["Encoder.encodeLong(", paramName, ")"], - _doubleType => ["Encoder.encodeDouble(", paramName, ")"], - _stringType => ["Encoder.encodeString(", paramName, ")"], - arrayType => ["Encoder.encodeSeq[", this.scalaType(arrayType.items), "].apply(", paramName, ")"], - classType => ["Encoder.AsObject[", this.scalaType(classType), "].apply(", paramName, ")"], - mapType => ["Encoder.encodeMap[String,", this.scalaType(mapType.values), "].apply(", paramName, ")"], - _ => ["Encoder.encodeString(", paramName, ")"], - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) { - if (noOptional) { - return ["Encoder.AsObject[", this.nameForNamedType(nullable), "]"]; - } else { - return ["Encoder.AsObject[Option[", this.nameForNamedType(nullable), "]]"]; - } - } - - return ["Encoder.AsObject[", this.nameForNamedType(unionType), "]"]; - } - ); - } - - protected emitEmptyClassDefinition(c: ClassType, className: Name): void { - this.emitDescription(this.descriptionForType(c)); - this.ensureBlankLine(); - this.emitLine("case class ", className, "() derives Encoder.AsObject, Decoder"); - } - - protected anySourceType(optional: boolean): Sourcelike { - return [wrapOption("Json", optional)]; - } - - protected emitClassDefinitionMethods(): void { - this.emitLine(") derives Encoder.AsObject, Decoder"); - } - - protected emitEnumDefinition(e: EnumType, enumName: Name): void { - this.emitDescription(this.descriptionForType(e)); - - this.ensureBlankLine(); - this.emitItem(["type ", enumName, " = "]); - let count = e.cases.size; - this.forEachEnumCase(e, "none", (_, jsonName) => { - // if (!(jsonName == "")) { - /* const backticks = - shouldAddBacktick(jsonName) || - jsonName.includes(" ") || - !isNaN(parseInt(jsonName.charAt(0))) - if (backticks) {this.emitItem("`")} else */ - this.emitItem(['"', jsonName, '"']); - // if (backticks) {this.emitItem("`")} - if (--count > 0) this.emitItem([" | "]); - // } else { - // --count - // } - }); - this.ensureBlankLine(); - } - - protected emitHeader(): void { - super.emitHeader(); - - this.emitLine("import scala.util.Try"); - this.emitLine("import io.circe.syntax._"); - this.emitLine("import io.circe._"); - this.emitLine("import cats.syntax.functor._"); - this.ensureBlankLine(); - - this.emitLine("// For serialising string unions"); - this.emitLine( - "given [A <: Singleton](using A <:< String): Decoder[A] = Decoder.decodeString.emapTry(x => Try(x.asInstanceOf[A])) " - ); - this.emitLine( - "given [A <: Singleton](using ev: A <:< String): Encoder[A] = Encoder.encodeString.contramap(ev) " - ); - this.ensureBlankLine(); - this.emitLine("// If a union has a null in, then we'll need this too... "); - this.emitLine("type NullValue = None.type"); - } - - protected emitTopLevelArray(t: ArrayType, name: Name): void { - super.emitTopLevelArray(t, name); - const elementType = this.scalaType(t.items); - this.emitLine([ - "given (using ev : ", - elementType, - "): Encoder[Map[String,", - elementType, - "]] = Encoder.encodeMap[String, ", - elementType, - "]" - ]); - } - - protected emitTopLevelMap(t: MapType, name: Name): void { - super.emitTopLevelMap(t, name); - const elementType = this.scalaType(t.values); - this.ensureBlankLine(); - this.emitLine([ - "given (using ev : ", - elementType, - "): Encoder[Map[String, ", - elementType, - "]] = Encoder.encodeMap[String, ", - elementType, - "]" - ]); - } - - protected emitUnionDefinition(u: UnionType, unionName: Name): void { - function sortBy(t: Type): string { - const kind = t.kind; - if (kind === "class") return kind; - return "_" + kind; - } - - this.emitDescription(this.descriptionForType(u)); - - const [maybeNull, nonNulls] = removeNullFromUnion(u, sortBy); - const theTypes: Sourcelike[] = []; - this.forEachUnionMember(u, nonNulls, "none", null, (_, t) => { - theTypes.push(this.scalaType(t)); - }); - if (maybeNull !== null) { - theTypes.push(this.nameForUnionMember(u, maybeNull)); - } - - this.emitItem(["type ", unionName, " = "]); - theTypes.forEach((t, i) => { - this.emitItem(i === 0 ? t : [" | ", t]); - }); - const thisUnionType = theTypes.map(x => this.sourcelikeToString(x)).join(" | "); - - this.ensureBlankLine(); - if (!this.seenUnionTypes.some(y => y === thisUnionType)) { - this.seenUnionTypes.push(thisUnionType); - const sourceLikeTypes: Array<[Sourcelike, Type]> = []; - this.forEachUnionMember(u, nonNulls, "none", null, (_, t) => { - sourceLikeTypes.push([this.scalaType(t), t]); - }); - if (maybeNull !== null) { - sourceLikeTypes.push([this.nameForUnionMember(u, maybeNull), maybeNull]); - } - - this.emitLine(["given Decoder[", unionName, "] = {"]); - this.indent(() => { - this.emitLine(["List[Decoder[", unionName, "]]("]); - this.indent(() => { - sourceLikeTypes.forEach(t => { - this.emitLine(["Decoder[", t[0], "].widen,"]); - }); - }); - this.emitLine(").reduceLeft(_ or _)"); - }); - this.emitLine(["}"]); - - this.ensureBlankLine(); - - this.emitLine(["given Encoder[", unionName, "] = Encoder.instance {"]); - this.indent(() => { - sourceLikeTypes.forEach((t, i) => { - const paramTemp = `enc${i.toString()}`; - this.emitLine([ - "case ", - paramTemp, - " : ", - t[0], - " => ", - this.circeEncoderForType(t[1], false, false, paramTemp) - ]); - }); - }); - this.emitLine("}"); - } - } -} - -export class Scala3TargetLanguage extends TargetLanguage { - public constructor() { - super("Scala3", ["scala3"], "scala"); - } - - protected getOptions(): Array> { - return [scala3Options.framework, scala3Options.packageName]; - } - - public get supportsOptionalClassProperties(): boolean { - return true; - } - - public get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): ConvenienceRenderer { - const options = getOptionValues(scala3Options, untypedOptionValues); - - switch (options.framework) { - case Framework.None: - return new Scala3Renderer(this, renderContext, options); - case Framework.Upickle: - return new UpickleRenderer(this, renderContext, options); - case Framework.Circe: - return new CirceRenderer(this, renderContext, options); - default: - return assertNever(options.framework); - } - } -} diff --git a/packages/quicktype-core/src/language/Scala3/CirceRenderer.ts b/packages/quicktype-core/src/language/Scala3/CirceRenderer.ts new file mode 100644 index 000000000..8be6e660d --- /dev/null +++ b/packages/quicktype-core/src/language/Scala3/CirceRenderer.ts @@ -0,0 +1,193 @@ +import { type Name } from "../../Naming"; +import { type Sourcelike } from "../../Source"; +import { type ArrayType, type ClassType, type EnumType, type MapType, type Type, type UnionType } from "../../Type"; +import { matchType, nullableFromUnion, removeNullFromUnion } from "../../TypeUtils"; + +import { Scala3Renderer } from "./Scala3Renderer"; +import { wrapOption } from "./utils"; + +export class CirceRenderer extends Scala3Renderer { + private seenUnionTypes: string[] = []; + + protected circeEncoderForType(t: Type, __ = false, noOptional = false, paramName: string = ""): Sourcelike { + return matchType( + t, + _anyType => ["Encoder.encodeJson(", paramName, ")"], + _nullType => ["Encoder.encodeNone(", paramName, ")"], + _boolType => ["Encoder.encodeBoolean(", paramName, ")"], + _integerType => ["Encoder.encodeLong(", paramName, ")"], + _doubleType => ["Encoder.encodeDouble(", paramName, ")"], + _stringType => ["Encoder.encodeString(", paramName, ")"], + arrayType => ["Encoder.encodeSeq[", this.scalaType(arrayType.items), "].apply(", paramName, ")"], + classType => ["Encoder.AsObject[", this.scalaType(classType), "].apply(", paramName, ")"], + mapType => ["Encoder.encodeMap[String,", this.scalaType(mapType.values), "].apply(", paramName, ")"], + _ => ["Encoder.encodeString(", paramName, ")"], + unionType => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) { + if (noOptional) { + return ["Encoder.AsObject[", this.nameForNamedType(nullable), "]"]; + } else { + return ["Encoder.AsObject[Option[", this.nameForNamedType(nullable), "]]"]; + } + } + + return ["Encoder.AsObject[", this.nameForNamedType(unionType), "]"]; + } + ); + } + + protected emitEmptyClassDefinition(c: ClassType, className: Name): void { + this.emitDescription(this.descriptionForType(c)); + this.ensureBlankLine(); + this.emitLine("case class ", className, "() derives Encoder.AsObject, Decoder"); + } + + protected anySourceType(optional: boolean): Sourcelike { + return [wrapOption("Json", optional)]; + } + + protected emitClassDefinitionMethods(): void { + this.emitLine(") derives Encoder.AsObject, Decoder"); + } + + protected emitEnumDefinition(e: EnumType, enumName: Name): void { + this.emitDescription(this.descriptionForType(e)); + + this.ensureBlankLine(); + this.emitItem(["type ", enumName, " = "]); + let count = e.cases.size; + this.forEachEnumCase(e, "none", (_, jsonName) => { + // if (!(jsonName == "")) { + /* const backticks = + shouldAddBacktick(jsonName) || + jsonName.includes(" ") || + !isNaN(parseInt(jsonName.charAt(0))) + if (backticks) {this.emitItem("`")} else */ + this.emitItem(['"', jsonName, '"']); + // if (backticks) {this.emitItem("`")} + if (--count > 0) this.emitItem([" | "]); + // } else { + // --count + // } + }); + this.ensureBlankLine(); + } + + protected emitHeader(): void { + super.emitHeader(); + + this.emitLine("import scala.util.Try"); + this.emitLine("import io.circe.syntax._"); + this.emitLine("import io.circe._"); + this.emitLine("import cats.syntax.functor._"); + this.ensureBlankLine(); + + this.emitLine("// For serialising string unions"); + this.emitLine( + "given [A <: Singleton](using A <:< String): Decoder[A] = Decoder.decodeString.emapTry(x => Try(x.asInstanceOf[A])) " + ); + this.emitLine( + "given [A <: Singleton](using ev: A <:< String): Encoder[A] = Encoder.encodeString.contramap(ev) " + ); + this.ensureBlankLine(); + this.emitLine("// If a union has a null in, then we'll need this too... "); + this.emitLine("type NullValue = None.type"); + } + + protected emitTopLevelArray(t: ArrayType, name: Name): void { + super.emitTopLevelArray(t, name); + const elementType = this.scalaType(t.items); + this.emitLine([ + "given (using ev : ", + elementType, + "): Encoder[Map[String,", + elementType, + "]] = Encoder.encodeMap[String, ", + elementType, + "]" + ]); + } + + protected emitTopLevelMap(t: MapType, name: Name): void { + super.emitTopLevelMap(t, name); + const elementType = this.scalaType(t.values); + this.ensureBlankLine(); + this.emitLine([ + "given (using ev : ", + elementType, + "): Encoder[Map[String, ", + elementType, + "]] = Encoder.encodeMap[String, ", + elementType, + "]" + ]); + } + + protected emitUnionDefinition(u: UnionType, unionName: Name): void { + function sortBy(t: Type): string { + const kind = t.kind; + if (kind === "class") return kind; + return "_" + kind; + } + + this.emitDescription(this.descriptionForType(u)); + + const [maybeNull, nonNulls] = removeNullFromUnion(u, sortBy); + const theTypes: Sourcelike[] = []; + this.forEachUnionMember(u, nonNulls, "none", null, (_, t) => { + theTypes.push(this.scalaType(t)); + }); + if (maybeNull !== null) { + theTypes.push(this.nameForUnionMember(u, maybeNull)); + } + + this.emitItem(["type ", unionName, " = "]); + theTypes.forEach((t, i) => { + this.emitItem(i === 0 ? t : [" | ", t]); + }); + const thisUnionType = theTypes.map(x => this.sourcelikeToString(x)).join(" | "); + + this.ensureBlankLine(); + if (!this.seenUnionTypes.some(y => y === thisUnionType)) { + this.seenUnionTypes.push(thisUnionType); + const sourceLikeTypes: Array<[Sourcelike, Type]> = []; + this.forEachUnionMember(u, nonNulls, "none", null, (_, t) => { + sourceLikeTypes.push([this.scalaType(t), t]); + }); + if (maybeNull !== null) { + sourceLikeTypes.push([this.nameForUnionMember(u, maybeNull), maybeNull]); + } + + this.emitLine(["given Decoder[", unionName, "] = {"]); + this.indent(() => { + this.emitLine(["List[Decoder[", unionName, "]]("]); + this.indent(() => { + sourceLikeTypes.forEach(t => { + this.emitLine(["Decoder[", t[0], "].widen,"]); + }); + }); + this.emitLine(").reduceLeft(_ or _)"); + }); + this.emitLine(["}"]); + + this.ensureBlankLine(); + + this.emitLine(["given Encoder[", unionName, "] = Encoder.instance {"]); + this.indent(() => { + sourceLikeTypes.forEach((t, i) => { + const paramTemp = `enc${i.toString()}`; + this.emitLine([ + "case ", + paramTemp, + " : ", + t[0], + " => ", + this.circeEncoderForType(t[1], false, false, paramTemp) + ]); + }); + }); + this.emitLine("}"); + } + } +} diff --git a/packages/quicktype-core/src/language/Scala3/Scala3Renderer.ts b/packages/quicktype-core/src/language/Scala3/Scala3Renderer.ts new file mode 100644 index 000000000..bc5fe7a56 --- /dev/null +++ b/packages/quicktype-core/src/language/Scala3/Scala3Renderer.ts @@ -0,0 +1,313 @@ +import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../../Annotation"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type Sourcelike, maybeAnnotated } from "../../Source"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { + ArrayType, + type ClassProperty, + type ClassType, + type EnumType, + MapType, + type ObjectType, + type Type, + type UnionType +} from "../../Type"; +import { matchType, nullableFromUnion, removeNullFromUnion } from "../../TypeUtils"; + +import { keywords } from "./constants"; +import { type scala3Options } from "./language"; +import { lowerNamingFunction, scalaNameStyle, shouldAddBacktick, upperNamingFunction, wrapOption } from "./utils"; + +export class Scala3Renderer extends ConvenienceRenderer { + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + protected readonly _scalaOptions: OptionValues + ) { + super(targetLanguage, renderContext); + } + + protected forbiddenNamesForGlobalNamespace(): readonly string[] { + return keywords; + } + + protected forbiddenForObjectProperties(_: ObjectType, _classNamed: Name): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: true }; + } + + protected forbiddenForEnumCases(_: EnumType, _enumName: Name): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: true }; + } + + protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: false }; + } + + protected topLevelNameStyle(rawName: string): string { + return scalaNameStyle(true, rawName); + } + + protected makeNamedTypeNamer(): Namer { + return upperNamingFunction; + } + + protected namerForObjectProperty(): Namer { + return lowerNamingFunction; + } + + protected makeUnionMemberNamer(): Namer { + return funPrefixNamer("upper", s => scalaNameStyle(true, s) + "Value"); + } + + protected makeEnumCaseNamer(): Namer { + return funPrefixNamer("upper", s => s.replace(" ", "")); // TODO - add backticks where appropriate + } + + protected emitDescriptionBlock(lines: Sourcelike[]): void { + this.emitCommentLines(lines, { lineStart: " * ", beforeComment: "/**", afterComment: " */" }); + } + + protected emitBlock( + line: Sourcelike, + f: () => void, + delimiter: "curly" | "paren" | "lambda" | "none" = "curly" + ): void { + const [open, close] = + delimiter === "curly" + ? ["{", "}"] + : delimiter === "paren" + ? ["(", ")"] + : delimiter === "none" + ? ["", ""] + : ["{", "})"]; + this.emitLine(line, " ", open); + this.indent(f); + this.emitLine(close); + } + + protected anySourceType(optional: boolean): Sourcelike { + return [wrapOption("Any", optional)]; + } + + // (asarazan): I've broken out the following two functions + // because some renderers, such as kotlinx, can cope with `any`, while some get mad. + protected arrayType(arrayType: ArrayType, withIssues = false): Sourcelike { + return ["Seq[", this.scalaType(arrayType.items, withIssues), "]"]; + } + + protected mapType(mapType: MapType, withIssues = false): Sourcelike { + return ["Map[String, ", this.scalaType(mapType.values, withIssues), "]"]; + } + + protected scalaType(t: Type, withIssues = false, noOptional = false): Sourcelike { + return matchType( + t, + _anyType => { + return maybeAnnotated(withIssues, anyTypeIssueAnnotation, this.anySourceType(!noOptional)); + }, + _nullType => { + // return "None.type" + return maybeAnnotated(withIssues, nullTypeIssueAnnotation, this.anySourceType(!noOptional)); + }, + _boolType => "Boolean", + _integerType => "Long", + _doubleType => "Double", + _stringType => "String", + arrayType => this.arrayType(arrayType, withIssues), + classType => this.nameForNamedType(classType), + mapType => this.mapType(mapType, withIssues), + enumType => this.nameForNamedType(enumType), + unionType => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) { + if (noOptional) { + return [this.scalaType(nullable, withIssues)]; + } else { + return ["Option[", this.scalaType(nullable, withIssues), "]"]; + } + } + + return this.nameForNamedType(unionType); + } + ); + } + + protected emitUsageHeader(): void { + // To be overridden + } + + protected emitHeader(): void { + if (this.leadingComments !== undefined) { + this.emitComments(this.leadingComments); + } else { + this.emitUsageHeader(); + } + + this.ensureBlankLine(); + this.emitLine("package ", this._scalaOptions.packageName); + this.ensureBlankLine(); + } + + protected emitTopLevelArray(t: ArrayType, name: Name): void { + const elementType = this.scalaType(t.items); + this.emitLine(["type ", name, " = List[", elementType, "]"]); + } + + protected emitTopLevelMap(t: MapType, name: Name): void { + const elementType = this.scalaType(t.values); + this.emitLine(["type ", name, " = Map[String, ", elementType, "]"]); + } + + protected emitEmptyClassDefinition(c: ClassType, className: Name): void { + this.emitDescription(this.descriptionForType(c)); + this.emitLine("case class ", className, "()"); + } + + protected emitClassDefinition(c: ClassType, className: Name): void { + if (c.getProperties().size === 0) { + this.emitEmptyClassDefinition(c, className); + return; + } + + const scalaType = (p: ClassProperty): Sourcelike => { + if (p.isOptional) { + return ["Option[", this.scalaType(p.type, true, true), "]"]; + } else { + return this.scalaType(p.type, true); + } + }; + + this.emitDescription(this.descriptionForType(c)); + this.emitLine("case class ", className, " ("); + this.indent(() => { + let count = c.getProperties().size; + let first = true; + this.forEachClassProperty(c, "none", (_, jsonName, p) => { + const nullable = p.type.kind === "union" && nullableFromUnion(p.type as UnionType) !== null; + const nullableOrOptional = p.isOptional || p.type.kind === "null" || nullable; + const last = --count === 0; + const meta: Array<() => void> = []; + + const description = this.descriptionForClassProperty(c, jsonName); + if (description !== undefined) { + meta.push(() => this.emitDescription(description)); + } + + if (meta.length > 0 && !first) { + this.ensureBlankLine(); + } + + for (const emit of meta) { + emit(); + } + + const nameNeedsBackticks = jsonName.endsWith("_") || shouldAddBacktick(jsonName); + const nameWithBackticks = nameNeedsBackticks ? "`" + jsonName + "`" : jsonName; + this.emitLine( + "val ", + nameWithBackticks, + " : ", + scalaType(p), + p.isOptional ? " = None" : nullableOrOptional ? " = None" : "", + last ? "" : "," + ); + + if (meta.length > 0 && !last) { + this.ensureBlankLine(); + } + + first = false; + }); + }); + + this.emitClassDefinitionMethods(); + } + + protected emitClassDefinitionMethods(): void { + this.emitLine(")"); + } + + protected emitEnumDefinition(e: EnumType, enumName: Name): void { + this.emitDescription(this.descriptionForType(e)); + + this.emitBlock( + ["enum ", enumName, " : "], + () => { + let count = e.cases.size; + if (count > 0) { + this.emitItem("\t case "); + } + + this.forEachEnumCase(e, "none", (name, jsonName) => { + if (!(jsonName == "")) { + const backticks = + shouldAddBacktick(jsonName) || + jsonName.includes(" ") || + !isNaN(parseInt(jsonName.charAt(0))); + if (backticks) { + this.emitItem("`"); + } + + this.emitItemOnce([name]); + if (backticks) { + this.emitItem("`"); + } + + if (--count > 0) this.emitItem([","]); + } else { + --count; + } + }); + }, + "none" + ); + } + + protected emitUnionDefinition(u: UnionType, unionName: Name): void { + function sortBy(t: Type): string { + const kind = t.kind; + if (kind === "class") return kind; + return "_" + kind; + } + + this.emitDescription(this.descriptionForType(u)); + + const [maybeNull, nonNulls] = removeNullFromUnion(u, sortBy); + const theTypes: Sourcelike[] = []; + this.forEachUnionMember(u, nonNulls, "none", null, (_, t) => { + theTypes.push(this.scalaType(t)); + }); + if (maybeNull !== null) { + theTypes.push(this.nameForUnionMember(u, maybeNull)); + } + + this.emitItem(["type ", unionName, " = "]); + theTypes.forEach((t, i) => { + this.emitItem(i === 0 ? t : [" | ", t]); + }); + this.ensureBlankLine(); + } + + protected emitSourceStructure(): void { + this.emitHeader(); + + // Top-level arrays, maps + this.forEachTopLevel("leading", (t, name) => { + if (t instanceof ArrayType) { + this.emitTopLevelArray(t, name); + } else if (t instanceof MapType) { + this.emitTopLevelMap(t, name); + } + }); + + this.forEachNamedType( + "leading-and-interposing", + (c: ClassType, n: Name) => this.emitClassDefinition(c, n), + (e, n) => this.emitEnumDefinition(e, n), + (u, n) => this.emitUnionDefinition(u, n) + ); + } +} diff --git a/packages/quicktype-core/src/language/Scala3/UpickleRenderer.ts b/packages/quicktype-core/src/language/Scala3/UpickleRenderer.ts new file mode 100644 index 000000000..0eb5ce354 --- /dev/null +++ b/packages/quicktype-core/src/language/Scala3/UpickleRenderer.ts @@ -0,0 +1,14 @@ +import { Scala3Renderer } from "./Scala3Renderer"; + +export class UpickleRenderer extends Scala3Renderer { + protected emitClassDefinitionMethods(): void { + this.emitLine(") derives ReadWriter "); + } + + protected emitHeader(): void { + super.emitHeader(); + + this.emitLine("import upickle.default.*"); + this.ensureBlankLine(); + } +} diff --git a/packages/quicktype-core/src/language/Scala3/constants.ts b/packages/quicktype-core/src/language/Scala3/constants.ts new file mode 100644 index 000000000..b41844e78 --- /dev/null +++ b/packages/quicktype-core/src/language/Scala3/constants.ts @@ -0,0 +1,87 @@ +// Use backticks for param names with symbols +export const invalidSymbols = [ + ":", + "-", + "+", + "!", + "@", + "#", + "$", + "%", + "^", + "&", + "*", + "(", + ")", + ">", + "<", + "/", + ";", + "'", + '"', + "{", + "}", + ":", + "~", + "`", + "." +] as const; + +export const keywords = [ + "abstract", + "case", + "catch", + "class", + "def", + "do", + "else", + "enum", + "extends", + "export", + "false", + "final", + "finally", + "for", + "forSome", + "if", + "implicit", + "import", + "lazy", + "match", + "new", + "null", + "object", + "override", + "package", + "private", + "protected", + "return", + "sealed", + "super", + "this", + "then", + "throw", + "trait", + "try", + "true", + "type", + "val", + "var", + "while", + "with", + "yield", + "Any", + "Boolean", + "Double", + "Float", + "Long", + "Int", + "Short", + "System", + "Byte", + "String", + "Array", + "List", + "Map", + "Enum" +] as const; diff --git a/packages/quicktype-core/src/language/Scala3/index.ts b/packages/quicktype-core/src/language/Scala3/index.ts new file mode 100644 index 000000000..33c5960ae --- /dev/null +++ b/packages/quicktype-core/src/language/Scala3/index.ts @@ -0,0 +1,4 @@ +export { Scala3TargetLanguage, scala3Options } from "./language"; +export { Scala3Renderer } from "./Scala3Renderer"; +export { CirceRenderer } from "./CirceRenderer"; +export { UpickleRenderer } from "./UpickleRenderer"; diff --git a/packages/quicktype-core/src/language/Scala3/language.ts b/packages/quicktype-core/src/language/Scala3/language.ts new file mode 100644 index 000000000..3b00207d0 --- /dev/null +++ b/packages/quicktype-core/src/language/Scala3/language.ts @@ -0,0 +1,63 @@ +import { type ConvenienceRenderer } from "../../ConvenienceRenderer"; +import { type RenderContext } from "../../Renderer"; +import { EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { assertNever } from "../../support/Support"; +import { TargetLanguage } from "../../TargetLanguage"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; + +import { CirceRenderer } from "./CirceRenderer"; +import { Scala3Renderer } from "./Scala3Renderer"; +import { UpickleRenderer } from "./UpickleRenderer"; + +export enum Framework { + None = "None", + Upickle = "Upickle", + Circe = "Circe" +} + +export const scala3Options = { + framework: new EnumOption( + "framework", + "Serialization framework", + [ + ["just-types", Framework.None], + ["circe", Framework.Circe], + ["upickle", Framework.Upickle] + ], + undefined + ), + packageName: new StringOption("package", "Package", "PACKAGE", "quicktype") +}; + +export class Scala3TargetLanguage extends TargetLanguage { + public constructor() { + super("Scala3", ["scala3"], "scala"); + } + + protected getOptions(): Array> { + return [scala3Options.framework, scala3Options.packageName]; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): ConvenienceRenderer { + const options = getOptionValues(scala3Options, untypedOptionValues); + + switch (options.framework) { + case Framework.None: + return new Scala3Renderer(this, renderContext, options); + case Framework.Upickle: + return new UpickleRenderer(this, renderContext, options); + case Framework.Circe: + return new CirceRenderer(this, renderContext, options); + default: + return assertNever(options.framework); + } + } +} diff --git a/packages/quicktype-core/src/language/Scala3/utils.ts b/packages/quicktype-core/src/language/Scala3/utils.ts new file mode 100644 index 000000000..1de23bcb8 --- /dev/null +++ b/packages/quicktype-core/src/language/Scala3/utils.ts @@ -0,0 +1,73 @@ +import { funPrefixNamer } from "../../Naming"; +import { + allLowerWordStyle, + allUpperWordStyle, + combineWords, + firstUpperWordStyle, + isDigit, + isLetterOrUnderscore, + isNumeric, + legalizeCharacters, + splitIntoWords +} from "../../support/Strings"; + +import { invalidSymbols, keywords } from "./constants"; + +/** + * Check if given parameter name should be wrapped in a backtick + * @param paramName + */ +export const shouldAddBacktick = (paramName: string): boolean => { + return ( + keywords.some(s => paramName === s) || + invalidSymbols.some(s => paramName.includes(s)) || + !isNaN(+parseFloat(paramName)) || + !isNaN(parseInt(paramName.charAt(0))) + ); +}; + +export const wrapOption = (s: string, optional: boolean): string => { + if (optional) { + return "Option[" + s + "]"; + } else { + return s; + } +}; + +function isPartCharacter(codePoint: number): boolean { + return isLetterOrUnderscore(codePoint) || isNumeric(codePoint); +} + +function isStartCharacter(codePoint: number): boolean { + return isPartCharacter(codePoint) && !isDigit(codePoint); +} + +const legalizeName = legalizeCharacters(isPartCharacter); + +export function scalaNameStyle(isUpper: boolean, original: string): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + isUpper ? firstUpperWordStyle : allLowerWordStyle, + firstUpperWordStyle, + isUpper ? allUpperWordStyle : allLowerWordStyle, + allUpperWordStyle, + "", + isStartCharacter + ); +} + +/* function unicodeEscape(codePoint: number): string { + return "\\u" + intToHex(codePoint, 4); +} */ + +// const _stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, unicodeEscape)); + +/* function stringEscape(s: string): string { + // "$this" is a template string in Kotlin so we have to escape $ + return _stringEscape(s).replace(/\$/g, "\\$"); +} */ + +export const upperNamingFunction = funPrefixNamer("upper", s => scalaNameStyle(true, s)); +export const lowerNamingFunction = funPrefixNamer("lower", s => scalaNameStyle(false, s)); diff --git a/packages/quicktype-core/src/language/Smithy4s.ts b/packages/quicktype-core/src/language/Smithy4s/Smithy4sRenderer.ts similarity index 73% rename from packages/quicktype-core/src/language/Smithy4s.ts rename to packages/quicktype-core/src/language/Smithy4s/Smithy4sRenderer.ts index 163b33073..17fda57b2 100644 --- a/packages/quicktype-core/src/language/Smithy4s.ts +++ b/packages/quicktype-core/src/language/Smithy4s/Smithy4sRenderer.ts @@ -1,22 +1,10 @@ -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { type Name, type Namer, funPrefixNamer } from "../Naming"; -import { type RenderContext } from "../Renderer"; -import { EnumOption, type Option, type OptionValues, StringOption, getOptionValues } from "../RendererOptions"; -import { type Sourcelike, maybeAnnotated } from "../Source"; -import { - allLowerWordStyle, - allUpperWordStyle, - combineWords, - firstUpperWordStyle, - isDigit, - isLetterOrUnderscore, - isNumeric, - legalizeCharacters, - splitIntoWords -} from "../support/Strings"; -import { assertNever } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; +import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../../Annotation"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type Sourcelike, maybeAnnotated } from "../../Source"; +import { type TargetLanguage } from "../../TargetLanguage"; import { ArrayType, type ClassProperty, @@ -26,147 +14,23 @@ import { type ObjectType, type Type, type UnionType -} from "../Type"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; -import { matchCompoundType, matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; - -export enum Framework { - None = "None" -} +} from "../../Type"; +import { matchCompoundType, matchType, nullableFromUnion, removeNullFromUnion } from "../../TypeUtils"; -export const SmithyOptions = { - framework: new EnumOption("framework", "Serialization framework", [["just-types", Framework.None]], undefined), - packageName: new StringOption("package", "Package", "PACKAGE", "quicktype") -}; - -// Use backticks for param names with symbols -const invalidSymbols = [ - ":", - "-", - "+", - "!", - "@", - "#", - "%", - "^", - "&", - "*", - "(", - ")", - ">", - "<", - "/", - ";", - "'", - '"', - "{", - "}", - ":", - "~", - "`", - "." -]; - -const keywords = [ - "abstract", - "case", - "catch", - "do", - "else", - "export", - "false", - "final", - "finally", - "for", - "forSome", - "if", - "implicit", - "import", - "new", - "override", - "package", - "private", - "protected", - "return", - "sealed", - "super", - "this", - "then", - "throw", - "trait", - "try", - "true", - "val", - "var", - "while", - "with", - "yield", - "Any", - "Boolean", - "Double", - "Float", - "Long", - "Int", - "Short", - "System", - "Byte", - "String", - "Array", - "List", - "Map", - "Enum" -]; - -/** - * Check if given parameter name should be wrapped in a backtick - * @param paramName - */ -const shouldAddBacktick = (paramName: string): boolean => { - return ( - keywords.some(s => paramName === s) || - invalidSymbols.some(s => paramName.includes(s)) || - !isNaN(parseFloat(paramName)) || - !isNaN(parseInt(paramName.charAt(0))) - ); -}; - -function isPartCharacter(codePoint: number): boolean { - return isLetterOrUnderscore(codePoint) || isNumeric(codePoint); -} - -function isStartCharacter(codePoint: number): boolean { - return isPartCharacter(codePoint) && !isDigit(codePoint); -} - -const legalizeName = legalizeCharacters(isPartCharacter); - -function scalaNameStyle(isUpper: boolean, original: string): string { - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - isUpper ? firstUpperWordStyle : allLowerWordStyle, - firstUpperWordStyle, - isUpper ? allUpperWordStyle : allLowerWordStyle, - allUpperWordStyle, - "", - isStartCharacter - ); -} - -const upperNamingFunction = funPrefixNamer("upper", s => scalaNameStyle(true, s)); -const lowerNamingFunction = funPrefixNamer("lower", s => scalaNameStyle(false, s)); +import { keywords } from "./constants"; +import { type smithyOptions } from "./language"; +import { lowerNamingFunction, scalaNameStyle, shouldAddBacktick, upperNamingFunction } from "./utils"; export class Smithy4sRenderer extends ConvenienceRenderer { public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - protected readonly _scalaOptions: OptionValues + protected readonly _scalaOptions: OptionValues ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace(): readonly string[] { return keywords; } @@ -419,10 +283,10 @@ export class Smithy4sRenderer extends ConvenienceRenderer { this.forEachEnumCase(e, "none", (name, jsonName) => { // if (!(jsonName == "")) { /* const backticks = - shouldAddBacktick(jsonName) || - jsonName.includes(" ") || - !isNaN(parseInt(jsonName.charAt(0))) - if (backticks) {this.emitItem("`")} else */ + shouldAddBacktick(jsonName) || + jsonName.includes(" ") || + !isNaN(parseInt(jsonName.charAt(0))) + if (backticks) {this.emitItem("`")} else */ this.emitLine(); this.emitItem([name, ' = "', jsonName, '"']); @@ -524,32 +388,3 @@ export class Smithy4sRenderer extends ConvenienceRenderer { ); } } - -export class SmithyTargetLanguage extends TargetLanguage { - public constructor() { - super("Smithy", ["Smithy"], "smithy"); - } - - protected getOptions(): Array> { - return [SmithyOptions.framework, SmithyOptions.packageName]; - } - - public get supportsOptionalClassProperties(): boolean { - return true; - } - - public get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): ConvenienceRenderer { - const options = getOptionValues(SmithyOptions, untypedOptionValues); - - switch (options.framework) { - case Framework.None: - return new Smithy4sRenderer(this, renderContext, options); - default: - return assertNever(options.framework); - } - } -} diff --git a/packages/quicktype-core/src/language/Smithy4s/constants.ts b/packages/quicktype-core/src/language/Smithy4s/constants.ts new file mode 100644 index 000000000..e015b6ea8 --- /dev/null +++ b/packages/quicktype-core/src/language/Smithy4s/constants.ts @@ -0,0 +1,77 @@ +// Use backticks for param names with symbols +export const invalidSymbols = [ + ":", + "-", + "+", + "!", + "@", + "#", + "%", + "^", + "&", + "*", + "(", + ")", + ">", + "<", + "/", + ";", + "'", + '"', + "{", + "}", + ":", + "~", + "`", + "." +] as const; + +export const keywords = [ + "abstract", + "case", + "catch", + "do", + "else", + "export", + "false", + "final", + "finally", + "for", + "forSome", + "if", + "implicit", + "import", + "new", + "override", + "package", + "private", + "protected", + "return", + "sealed", + "super", + "this", + "then", + "throw", + "trait", + "try", + "true", + "val", + "var", + "while", + "with", + "yield", + "Any", + "Boolean", + "Double", + "Float", + "Long", + "Int", + "Short", + "System", + "Byte", + "String", + "Array", + "List", + "Map", + "Enum" +] as const; diff --git a/packages/quicktype-core/src/language/Smithy4s/index.ts b/packages/quicktype-core/src/language/Smithy4s/index.ts new file mode 100644 index 000000000..1dea97f90 --- /dev/null +++ b/packages/quicktype-core/src/language/Smithy4s/index.ts @@ -0,0 +1,2 @@ +export { SmithyTargetLanguage, smithyOptions } from "./language"; +export { Smithy4sRenderer } from "./Smithy4sRenderer"; diff --git a/packages/quicktype-core/src/language/Smithy4s/language.ts b/packages/quicktype-core/src/language/Smithy4s/language.ts new file mode 100644 index 000000000..2726d0ff5 --- /dev/null +++ b/packages/quicktype-core/src/language/Smithy4s/language.ts @@ -0,0 +1,46 @@ +import { type ConvenienceRenderer } from "../../ConvenienceRenderer"; +import { type RenderContext } from "../../Renderer"; +import { EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { assertNever } from "../../support/Support"; +import { TargetLanguage } from "../../TargetLanguage"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; + +import { Smithy4sRenderer } from "./Smithy4sRenderer"; + +export enum Framework { + None = "None" +} + +export const smithyOptions = { + framework: new EnumOption("framework", "Serialization framework", [["just-types", Framework.None]], undefined), + packageName: new StringOption("package", "Package", "PACKAGE", "quicktype") +}; + +export class SmithyTargetLanguage extends TargetLanguage { + public constructor() { + super("Smithy", ["Smithy"], "smithy"); + } + + protected getOptions(): Array> { + return [smithyOptions.framework, smithyOptions.packageName]; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): ConvenienceRenderer { + const options = getOptionValues(smithyOptions, untypedOptionValues); + + switch (options.framework) { + case Framework.None: + return new Smithy4sRenderer(this, renderContext, options); + default: + return assertNever(options.framework); + } + } +} diff --git a/packages/quicktype-core/src/language/Smithy4s/utils.ts b/packages/quicktype-core/src/language/Smithy4s/utils.ts new file mode 100644 index 000000000..7075f6627 --- /dev/null +++ b/packages/quicktype-core/src/language/Smithy4s/utils.ts @@ -0,0 +1,55 @@ +import { isDigit } from "unicode-properties"; + +import { funPrefixNamer } from "../../Naming"; +import { + allLowerWordStyle, + allUpperWordStyle, + combineWords, + firstUpperWordStyle, + isLetterOrUnderscore, + isNumeric, + legalizeCharacters, + splitIntoWords +} from "../../support/Strings"; + +import { invalidSymbols, keywords } from "./constants"; + +/** + * Check if given parameter name should be wrapped in a backtick + * @param paramName + */ +export const shouldAddBacktick = (paramName: string): boolean => { + return ( + keywords.some(s => paramName === s) || + invalidSymbols.some(s => paramName.includes(s)) || + !isNaN(parseFloat(paramName)) || + !isNaN(parseInt(paramName.charAt(0))) + ); +}; + +function isPartCharacter(codePoint: number): boolean { + return isLetterOrUnderscore(codePoint) || isNumeric(codePoint); +} + +function isStartCharacter(codePoint: number): boolean { + return isPartCharacter(codePoint) && !isDigit(codePoint); +} + +const legalizeName = legalizeCharacters(isPartCharacter); + +export function scalaNameStyle(isUpper: boolean, original: string): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + isUpper ? firstUpperWordStyle : allLowerWordStyle, + firstUpperWordStyle, + isUpper ? allUpperWordStyle : allLowerWordStyle, + allUpperWordStyle, + "", + isStartCharacter + ); +} + +export const upperNamingFunction = funPrefixNamer("upper", s => scalaNameStyle(true, s)); +export const lowerNamingFunction = funPrefixNamer("lower", s => scalaNameStyle(false, s)); diff --git a/packages/quicktype-core/src/language/Swift.ts b/packages/quicktype-core/src/language/Swift/SwiftRenderer.ts similarity index 66% rename from packages/quicktype-core/src/language/Swift.ts rename to packages/quicktype-core/src/language/Swift/SwiftRenderer.ts index cb801de2b..18cc7f281 100644 --- a/packages/quicktype-core/src/language/Swift.ts +++ b/packages/quicktype-core/src/language/Swift/SwiftRenderer.ts @@ -1,337 +1,30 @@ import { arrayIntercalate } from "collection-utils"; -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { type DateTimeRecognizer, DefaultDateTimeRecognizer } from "../DateTime"; -import { type Name, type Namer, funPrefixNamer } from "../Naming"; -import { type ForEachPosition, type RenderContext } from "../Renderer"; -import { - BooleanOption, - EnumOption, - type Option, - type OptionValues, - StringOption, - getOptionValues -} from "../RendererOptions"; -import { type Sourcelike, maybeAnnotated, modifySource } from "../Source"; -import { AcronymStyleOptions, acronymOption, acronymStyle } from "../support/Acronyms"; -import { - addPrefixIfNecessary, - allLowerWordStyle, - allUpperWordStyle, - camelCase, - combineWords, - escapeNonPrintableMapper, - firstUpperWordStyle, - intToHex, - isDigit, - isLetterOrUnderscore, - isNumeric, - isPrintable, - legalizeCharacters, - splitIntoWords, - utf32ConcatMap -} from "../support/Strings"; -import { assert, defined, panic } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; +import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../../Annotation"; +import { ConvenienceRenderer, type ForbiddenWordsInfo } from "../../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type Sourcelike, maybeAnnotated, modifySource } from "../../Source"; +import { acronymStyle } from "../../support/Acronyms"; +import { camelCase } from "../../support/Strings"; +import { assert, defined, panic } from "../../support/Support"; +import { type TargetLanguage } from "../../TargetLanguage"; import { ArrayType, type ClassProperty, type ClassType, EnumType, MapType, - type PrimitiveStringTypeKind, - type TransformedStringTypeKind, type Type, type TypeKind, type UnionType -} from "../Type"; -import { type StringTypeMapping } from "../TypeBuilder"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; -import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; - -const MAX_SAMELINE_PROPERTIES = 4; - -export const swiftOptions = { - justTypes: new BooleanOption("just-types", "Plain types only", false), - convenienceInitializers: new BooleanOption("initializers", "Generate initializers and mutators", true), - explicitCodingKeys: new BooleanOption("coding-keys", "Explicit CodingKey values in Codable types", true), - codingKeysProtocol: new StringOption( - "coding-keys-protocol", - "CodingKeys implements protocols", - "protocol1, protocol2...", - "", - "secondary" - ), - alamofire: new BooleanOption("alamofire", "Alamofire extensions", false), - namedTypePrefix: new StringOption("type-prefix", "Prefix for type names", "PREFIX", "", "secondary"), - useClasses: new EnumOption("struct-or-class", "Structs or classes", [ - ["struct", false], - ["class", true] - ]), - mutableProperties: new BooleanOption("mutable-properties", "Use var instead of let for object properties", false), - acronymStyle: acronymOption(AcronymStyleOptions.Pascal), - dense: new EnumOption( - "density", - "Code density", - [ - ["dense", true], - ["normal", false] - ], - "dense", - "secondary" - ), - linux: new BooleanOption("support-linux", "Support Linux", false, "secondary"), - objcSupport: new BooleanOption( - "objective-c-support", - "Objects inherit from NSObject and @objcMembers is added to classes", - false - ), - optionalEnums: new BooleanOption("optional-enums", "If no matching case is found enum value is set to null", false), - swift5Support: new BooleanOption("swift-5-support", "Renders output in a Swift 5 compatible mode", false), - sendable: new BooleanOption("sendable", "Mark generated models as Sendable", false), - multiFileOutput: new BooleanOption( - "multi-file-output", - "Renders each top-level object in its own Swift file", - false - ), - accessLevel: new EnumOption( - "access-level", - "Access level", - [ - ["internal", "internal"], - ["public", "public"] - ], - "internal", - "secondary" - ), - protocol: new EnumOption( - "protocol", - "Make types implement protocol", - [ - ["none", { equatable: false, hashable: false }], - ["equatable", { equatable: true, hashable: false }], - ["hashable", { equatable: false, hashable: true }] - ], - "none", - "secondary" - ) -}; - -// These are all recognized by Swift as ISO8601 date-times: -// -// 2018-08-14T02:45:50+00:00 -// 2018-08-14T02:45:50+00 -// 2018-08-14T02:45:50+1 -// 2018-08-14T02:45:50+1111 -// 2018-08-14T02:45:50+1111:1:33 -// 2018-08-14T02:45:50-00 -// 2018-08-14T02:45:50z -// 2018-00008-1T002:45:3Z - -const swiftDateTimeRegex = /^\d+-\d+-\d+T\d+:\d+:\d+([zZ]|[+-]\d+(:\d+)?)$/; - -class SwiftDateTimeRecognizer extends DefaultDateTimeRecognizer { - public isDateTime(str: string): boolean { - return swiftDateTimeRegex.exec(str) !== null; - } -} - -export interface SwiftProperty { - jsonName: string; - name: Name; - parameter: ClassProperty; - position: ForEachPosition; -} - -export class SwiftTargetLanguage extends TargetLanguage { - public constructor() { - super("Swift", ["swift", "swift4"], "swift"); - } - - protected getOptions(): Array> { - return [ - swiftOptions.justTypes, - swiftOptions.useClasses, - swiftOptions.dense, - swiftOptions.convenienceInitializers, - swiftOptions.explicitCodingKeys, - swiftOptions.codingKeysProtocol, - swiftOptions.accessLevel, - swiftOptions.alamofire, - swiftOptions.linux, - swiftOptions.namedTypePrefix, - swiftOptions.protocol, - swiftOptions.acronymStyle, - swiftOptions.objcSupport, - swiftOptions.optionalEnums, - swiftOptions.sendable, - swiftOptions.swift5Support, - swiftOptions.multiFileOutput, - swiftOptions.mutableProperties - ]; - } - - public get stringTypeMapping(): StringTypeMapping { - const mapping: Map = new Map(); - mapping.set("date-time", "date-time"); - return mapping; - } - - public get supportsOptionalClassProperties(): boolean { - return true; - } - - public get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): SwiftRenderer { - return new SwiftRenderer(this, renderContext, getOptionValues(swiftOptions, untypedOptionValues)); - } - - public get dateTimeRecognizer(): DateTimeRecognizer { - return new SwiftDateTimeRecognizer(); - } -} +} from "../../Type"; +import { matchType, nullableFromUnion, removeNullFromUnion } from "../../TypeUtils"; -const keywords = [ - "await", - "associatedtype", - "class", - "deinit", - "enum", - "extension", - "fileprivate", - "func", - "import", - "init", - "inout", - "internal", - "let", - "open", - "operator", - "private", - "protocol", - "public", - "static", - "struct", - "subscript", - "typealias", - "var", - "break", - "case", - "continue", - "default", - "defer", - "do", - "else", - "fallthrough", - "for", - "guard", - "if", - "in", - "repeat", - "return", - "switch", - "where", - "while", - "as", - "Any", - "catch", - "false", - "is", - "nil", - "rethrows", - "super", - "self", - "Self", - "throw", - "throws", - "true", - "try", - "_", - "associativity", - "convenience", - "dynamic", - "didSet", - "final", - "get", - "infix", - "indirect", - "lazy", - "left", - "mutating", - "nonmutating", - "optional", - "override", - "postfix", - "precedence", - "prefix", - "Protocol", - "required", - "right", - "set", - "Type", - "unowned", - "weak", - "willSet", - "String", - "Int", - "Double", - "Bool", - "Data", - "Date", - "URL", - "CommandLine", - "FileHandle", - "JSONSerialization", - "checkNull", - "removeNSNull", - "nilToNSNull", - "convertArray", - "convertOptional", - "convertDict", - "convertDouble", - "jsonString", - "jsonData" -]; - -function isPartCharacter(codePoint: number): boolean { - return isLetterOrUnderscore(codePoint) || isNumeric(codePoint); -} - -function isStartCharacter(codePoint: number): boolean { - return isPartCharacter(codePoint) && !isDigit(codePoint); -} - -const legalizeName = legalizeCharacters(isPartCharacter); - -function swiftNameStyle( - prefix: string, - isUpper: boolean, - original: string, - acronymsStyle: (s: string) => string = allUpperWordStyle -): string { - const words = splitIntoWords(original); - const combined = combineWords( - words, - legalizeName, - isUpper ? firstUpperWordStyle : allLowerWordStyle, - firstUpperWordStyle, - isUpper ? allUpperWordStyle : allLowerWordStyle, - acronymsStyle, - "", - isStartCharacter - ); - return addPrefixIfNecessary(prefix, combined); -} - -function unicodeEscape(codePoint: number): string { - return "\\u{" + intToHex(codePoint, 0) + "}"; -} - -const stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, unicodeEscape)); +import { keywords } from "./constants"; +import { type swiftOptions } from "./language"; +import { MAX_SAMELINE_PROPERTIES, type SwiftProperty, stringEscape, swiftNameStyle } from "./utils"; export class SwiftRenderer extends ConvenienceRenderer { private _currentFilename: string | undefined; @@ -348,9 +41,9 @@ export class SwiftRenderer extends ConvenienceRenderer { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace(): readonly string[] { if (this._options.alamofire) { - return ["DataRequest", ...keywords]; + return ["DataRequest", ...keywords] as const; } return keywords; @@ -859,22 +552,22 @@ export class SwiftRenderer extends ConvenienceRenderer { }); } else { this.emitMultiline(`decoder.dateDecodingStrategy = .custom({ (decoder) -> Date in - let container = try decoder.singleValueContainer() - let dateStr = try container.decode(String.self) - - let formatter = DateFormatter() - formatter.calendar = Calendar(identifier: .iso8601) - formatter.locale = Locale(identifier: "en_US_POSIX") - formatter.timeZone = TimeZone(secondsFromGMT: 0) - formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX" - if let date = formatter.date(from: dateStr) { - return date - } - formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXXXX" - if let date = formatter.date(from: dateStr) { - return date - } - throw DecodingError.typeMismatch(Date.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Could not decode date")) + let container = try decoder.singleValueContainer() + let dateStr = try container.decode(String.self) + + let formatter = DateFormatter() + formatter.calendar = Calendar(identifier: .iso8601) + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.timeZone = TimeZone(secondsFromGMT: 0) + formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX" + if let date = formatter.date(from: dateStr) { + return date + } + formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXXXX" + if let date = formatter.date(from: dateStr) { + return date + } + throw DecodingError.typeMismatch(Date.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Could not decode date")) })`); } @@ -1148,20 +841,20 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); this.ensureBlankLine(); this.emitMultiline(` public static func == (lhs: JSONNull, rhs: JSONNull) -> Bool { - return true - }`); + return true + }`); if (this._options.objcSupport === false) { this.ensureBlankLine(); this.emitMultiline(` public var hashValue: Int { - return 0 - }`); + return 0 + }`); if (this._options.swift5Support) { this.ensureBlankLine(); this.emitMultiline(` public func hash(into hasher: inout Hasher) { - // No-op - }`); + // No-op + }`); } } @@ -1173,41 +866,41 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); } this.emitMultiline(`public init() {} - - public required init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - if !container.decodeNil() { - throw DecodingError.typeMismatch(JSONNull.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for JSONNull")) - } - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - try container.encodeNil() - } + + public required init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + if !container.decodeNil() { + throw DecodingError.typeMismatch(JSONNull.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for JSONNull")) + } + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + try container.encodeNil() + } }`); } if (this._needAny) { this.ensureBlankLine(); this.emitMultiline(`class JSONCodingKey: CodingKey { - let key: String - - required init?(intValue: Int) { - return nil - } - - required init?(stringValue: String) { - key = stringValue - } - - var intValue: Int? { - return nil - } - - var stringValue: String { - return key - } + let key: String + + required init?(intValue: Int) { + return nil + } + + required init?(stringValue: String) { + key = stringValue + } + + var intValue: Int? { + return nil + } + + var stringValue: String { + return key + } }`); this.ensureBlankLine(); @@ -1219,196 +912,196 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); this.ensureBlankLine(); this.emitMultiline(` ${this.accessLevel}let value: Any - - static func decodingError(forCodingPath codingPath: [CodingKey]) -> DecodingError { - let context = DecodingError.Context(codingPath: codingPath, debugDescription: "Cannot decode JSONAny") - return DecodingError.typeMismatch(JSONAny.self, context) - } - - static func encodingError(forValue value: Any, codingPath: [CodingKey]) -> EncodingError { - let context = EncodingError.Context(codingPath: codingPath, debugDescription: "Cannot encode JSONAny") - return EncodingError.invalidValue(value, context) - } - - static func decode(from container: SingleValueDecodingContainer) throws -> Any { - if let value = try? container.decode(Bool.self) { - return value - } - if let value = try? container.decode(Int64.self) { - return value - } - if let value = try? container.decode(Double.self) { - return value - } - if let value = try? container.decode(String.self) { - return value - } - if container.decodeNil() { - return JSONNull() - } - throw decodingError(forCodingPath: container.codingPath) - } - - static func decode(from container: inout UnkeyedDecodingContainer) throws -> Any { - if let value = try? container.decode(Bool.self) { - return value - } - if let value = try? container.decode(Int64.self) { - return value - } - if let value = try? container.decode(Double.self) { - return value - } - if let value = try? container.decode(String.self) { - return value - } - if let value = try? container.decodeNil() { - if value { - return JSONNull() - } - } - if var container = try? container.nestedUnkeyedContainer() { - return try decodeArray(from: &container) - } - if var container = try? container.nestedContainer(keyedBy: JSONCodingKey.self) { - return try decodeDictionary(from: &container) - } - throw decodingError(forCodingPath: container.codingPath) - } - - static func decode(from container: inout KeyedDecodingContainer, forKey key: JSONCodingKey) throws -> Any { - if let value = try? container.decode(Bool.self, forKey: key) { - return value - } - if let value = try? container.decode(Int64.self, forKey: key) { - return value - } - if let value = try? container.decode(Double.self, forKey: key) { - return value - } - if let value = try? container.decode(String.self, forKey: key) { - return value - } - if let value = try? container.decodeNil(forKey: key) { - if value { - return JSONNull() - } - } - if var container = try? container.nestedUnkeyedContainer(forKey: key) { - return try decodeArray(from: &container) - } - if var container = try? container.nestedContainer(keyedBy: JSONCodingKey.self, forKey: key) { - return try decodeDictionary(from: &container) - } - throw decodingError(forCodingPath: container.codingPath) - } - - static func decodeArray(from container: inout UnkeyedDecodingContainer) throws -> [Any] { - var arr: [Any] = [] - while !container.isAtEnd { - let value = try decode(from: &container) - arr.append(value) - } - return arr - } - - static func decodeDictionary(from container: inout KeyedDecodingContainer) throws -> [String: Any] { - var dict = [String: Any]() - for key in container.allKeys { - let value = try decode(from: &container, forKey: key) - dict[key.stringValue] = value - } - return dict - } - - static func encode(to container: inout UnkeyedEncodingContainer, array: [Any]) throws { - for value in array { - if let value = value as? Bool { - try container.encode(value) - } else if let value = value as? Int64 { - try container.encode(value) - } else if let value = value as? Double { - try container.encode(value) - } else if let value = value as? String { - try container.encode(value) - } else if value is JSONNull { - try container.encodeNil() - } else if let value = value as? [Any] { - var container = container.nestedUnkeyedContainer() - try encode(to: &container, array: value) - } else if let value = value as? [String: Any] { - var container = container.nestedContainer(keyedBy: JSONCodingKey.self) - try encode(to: &container, dictionary: value) - } else { - throw encodingError(forValue: value, codingPath: container.codingPath) - } - } - } - - static func encode(to container: inout KeyedEncodingContainer, dictionary: [String: Any]) throws { - for (key, value) in dictionary { - let key = JSONCodingKey(stringValue: key)! - if let value = value as? Bool { - try container.encode(value, forKey: key) - } else if let value = value as? Int64 { - try container.encode(value, forKey: key) - } else if let value = value as? Double { - try container.encode(value, forKey: key) - } else if let value = value as? String { - try container.encode(value, forKey: key) - } else if value is JSONNull { - try container.encodeNil(forKey: key) - } else if let value = value as? [Any] { - var container = container.nestedUnkeyedContainer(forKey: key) - try encode(to: &container, array: value) - } else if let value = value as? [String: Any] { - var container = container.nestedContainer(keyedBy: JSONCodingKey.self, forKey: key) - try encode(to: &container, dictionary: value) - } else { - throw encodingError(forValue: value, codingPath: container.codingPath) - } - } - } - - static func encode(to container: inout SingleValueEncodingContainer, value: Any) throws { - if let value = value as? Bool { - try container.encode(value) - } else if let value = value as? Int64 { - try container.encode(value) - } else if let value = value as? Double { - try container.encode(value) - } else if let value = value as? String { - try container.encode(value) - } else if value is JSONNull { - try container.encodeNil() - } else { - throw encodingError(forValue: value, codingPath: container.codingPath) - } - } - - public required init(from decoder: Decoder) throws { - if var arrayContainer = try? decoder.unkeyedContainer() { - self.value = try JSONAny.decodeArray(from: &arrayContainer) - } else if var container = try? decoder.container(keyedBy: JSONCodingKey.self) { - self.value = try JSONAny.decodeDictionary(from: &container) - } else { - let container = try decoder.singleValueContainer() - self.value = try JSONAny.decode(from: container) - } - } - - public func encode(to encoder: Encoder) throws { - if let arr = self.value as? [Any] { - var container = encoder.unkeyedContainer() - try JSONAny.encode(to: &container, array: arr) - } else if let dict = self.value as? [String: Any] { - var container = encoder.container(keyedBy: JSONCodingKey.self) - try JSONAny.encode(to: &container, dictionary: dict) - } else { - var container = encoder.singleValueContainer() - try JSONAny.encode(to: &container, value: self.value) - } - } + + static func decodingError(forCodingPath codingPath: [CodingKey]) -> DecodingError { + let context = DecodingError.Context(codingPath: codingPath, debugDescription: "Cannot decode JSONAny") + return DecodingError.typeMismatch(JSONAny.self, context) + } + + static func encodingError(forValue value: Any, codingPath: [CodingKey]) -> EncodingError { + let context = EncodingError.Context(codingPath: codingPath, debugDescription: "Cannot encode JSONAny") + return EncodingError.invalidValue(value, context) + } + + static func decode(from container: SingleValueDecodingContainer) throws -> Any { + if let value = try? container.decode(Bool.self) { + return value + } + if let value = try? container.decode(Int64.self) { + return value + } + if let value = try? container.decode(Double.self) { + return value + } + if let value = try? container.decode(String.self) { + return value + } + if container.decodeNil() { + return JSONNull() + } + throw decodingError(forCodingPath: container.codingPath) + } + + static func decode(from container: inout UnkeyedDecodingContainer) throws -> Any { + if let value = try? container.decode(Bool.self) { + return value + } + if let value = try? container.decode(Int64.self) { + return value + } + if let value = try? container.decode(Double.self) { + return value + } + if let value = try? container.decode(String.self) { + return value + } + if let value = try? container.decodeNil() { + if value { + return JSONNull() + } + } + if var container = try? container.nestedUnkeyedContainer() { + return try decodeArray(from: &container) + } + if var container = try? container.nestedContainer(keyedBy: JSONCodingKey.self) { + return try decodeDictionary(from: &container) + } + throw decodingError(forCodingPath: container.codingPath) + } + + static func decode(from container: inout KeyedDecodingContainer, forKey key: JSONCodingKey) throws -> Any { + if let value = try? container.decode(Bool.self, forKey: key) { + return value + } + if let value = try? container.decode(Int64.self, forKey: key) { + return value + } + if let value = try? container.decode(Double.self, forKey: key) { + return value + } + if let value = try? container.decode(String.self, forKey: key) { + return value + } + if let value = try? container.decodeNil(forKey: key) { + if value { + return JSONNull() + } + } + if var container = try? container.nestedUnkeyedContainer(forKey: key) { + return try decodeArray(from: &container) + } + if var container = try? container.nestedContainer(keyedBy: JSONCodingKey.self, forKey: key) { + return try decodeDictionary(from: &container) + } + throw decodingError(forCodingPath: container.codingPath) + } + + static func decodeArray(from container: inout UnkeyedDecodingContainer) throws -> [Any] { + var arr: [Any] = [] + while !container.isAtEnd { + let value = try decode(from: &container) + arr.append(value) + } + return arr + } + + static func decodeDictionary(from container: inout KeyedDecodingContainer) throws -> [String: Any] { + var dict = [String: Any]() + for key in container.allKeys { + let value = try decode(from: &container, forKey: key) + dict[key.stringValue] = value + } + return dict + } + + static func encode(to container: inout UnkeyedEncodingContainer, array: [Any]) throws { + for value in array { + if let value = value as? Bool { + try container.encode(value) + } else if let value = value as? Int64 { + try container.encode(value) + } else if let value = value as? Double { + try container.encode(value) + } else if let value = value as? String { + try container.encode(value) + } else if value is JSONNull { + try container.encodeNil() + } else if let value = value as? [Any] { + var container = container.nestedUnkeyedContainer() + try encode(to: &container, array: value) + } else if let value = value as? [String: Any] { + var container = container.nestedContainer(keyedBy: JSONCodingKey.self) + try encode(to: &container, dictionary: value) + } else { + throw encodingError(forValue: value, codingPath: container.codingPath) + } + } + } + + static func encode(to container: inout KeyedEncodingContainer, dictionary: [String: Any]) throws { + for (key, value) in dictionary { + let key = JSONCodingKey(stringValue: key)! + if let value = value as? Bool { + try container.encode(value, forKey: key) + } else if let value = value as? Int64 { + try container.encode(value, forKey: key) + } else if let value = value as? Double { + try container.encode(value, forKey: key) + } else if let value = value as? String { + try container.encode(value, forKey: key) + } else if value is JSONNull { + try container.encodeNil(forKey: key) + } else if let value = value as? [Any] { + var container = container.nestedUnkeyedContainer(forKey: key) + try encode(to: &container, array: value) + } else if let value = value as? [String: Any] { + var container = container.nestedContainer(keyedBy: JSONCodingKey.self, forKey: key) + try encode(to: &container, dictionary: value) + } else { + throw encodingError(forValue: value, codingPath: container.codingPath) + } + } + } + + static func encode(to container: inout SingleValueEncodingContainer, value: Any) throws { + if let value = value as? Bool { + try container.encode(value) + } else if let value = value as? Int64 { + try container.encode(value) + } else if let value = value as? Double { + try container.encode(value) + } else if let value = value as? String { + try container.encode(value) + } else if value is JSONNull { + try container.encodeNil() + } else { + throw encodingError(forValue: value, codingPath: container.codingPath) + } + } + + public required init(from decoder: Decoder) throws { + if var arrayContainer = try? decoder.unkeyedContainer() { + self.value = try JSONAny.decodeArray(from: &arrayContainer) + } else if var container = try? decoder.container(keyedBy: JSONCodingKey.self) { + self.value = try JSONAny.decodeDictionary(from: &container) + } else { + let container = try decoder.singleValueContainer() + self.value = try JSONAny.decode(from: container) + } + } + + public func encode(to encoder: Encoder) throws { + if let arr = self.value as? [Any] { + var container = encoder.unkeyedContainer() + try JSONAny.encode(to: &container, array: arr) + } else if let dict = self.value as? [String: Any] { + var container = encoder.container(keyedBy: JSONCodingKey.self) + try JSONAny.encode(to: &container, dictionary: dict) + } else { + var container = encoder.singleValueContainer() + try JSONAny.encode(to: &container, value: self.value) + } + } }`); } @@ -1472,20 +1165,20 @@ encoder.dateEncodingStrategy = .formatted(formatter)`); this.emitBlockWithAccess("extension DataRequest", () => { this .emitMultiline(`fileprivate func decodableResponseSerializer() -> DataResponseSerializer { - return DataResponseSerializer { _, response, data, error in - guard error == nil else { return .failure(error!) } - - guard let data = data else { - return .failure(AFError.responseSerializationFailed(reason: .inputDataNil)) - } - - return Result { try newJSONDecoder().decode(T.self, from: data) } - } + return DataResponseSerializer { _, response, data, error in + guard error == nil else { return .failure(error!) } + + guard let data = data else { + return .failure(AFError.responseSerializationFailed(reason: .inputDataNil)) + } + + return Result { try newJSONDecoder().decode(T.self, from: data) } + } } @discardableResult fileprivate func responseDecodable(queue: DispatchQueue? = nil, completionHandler: @escaping (DataResponse) -> Void) -> Self { - return response(queue: queue, responseSerializer: decodableResponseSerializer(), completionHandler: completionHandler) + return response(queue: queue, responseSerializer: decodableResponseSerializer(), completionHandler: completionHandler) }`); this.ensureBlankLine(); this.forEachTopLevel("leading-and-interposing", (_, name) => { diff --git a/packages/quicktype-core/src/language/Swift/constants.ts b/packages/quicktype-core/src/language/Swift/constants.ts new file mode 100644 index 000000000..4a8c4ee2f --- /dev/null +++ b/packages/quicktype-core/src/language/Swift/constants.ts @@ -0,0 +1,101 @@ +export const keywords = [ + "await", + "associatedtype", + "class", + "deinit", + "enum", + "extension", + "fileprivate", + "func", + "import", + "init", + "inout", + "internal", + "let", + "open", + "operator", + "private", + "protocol", + "public", + "static", + "struct", + "subscript", + "typealias", + "var", + "break", + "case", + "continue", + "default", + "defer", + "do", + "else", + "fallthrough", + "for", + "guard", + "if", + "in", + "repeat", + "return", + "switch", + "where", + "while", + "as", + "Any", + "catch", + "false", + "is", + "nil", + "rethrows", + "super", + "self", + "Self", + "throw", + "throws", + "true", + "try", + "_", + "associativity", + "convenience", + "dynamic", + "didSet", + "final", + "get", + "infix", + "indirect", + "lazy", + "left", + "mutating", + "nonmutating", + "optional", + "override", + "postfix", + "precedence", + "prefix", + "Protocol", + "required", + "right", + "set", + "Type", + "unowned", + "weak", + "willSet", + "String", + "Int", + "Double", + "Bool", + "Data", + "Date", + "URL", + "CommandLine", + "FileHandle", + "JSONSerialization", + "checkNull", + "removeNSNull", + "nilToNSNull", + "convertArray", + "convertOptional", + "convertDict", + "convertDouble", + "jsonString", + "jsonData" +] as const; diff --git a/packages/quicktype-core/src/language/Swift/index.ts b/packages/quicktype-core/src/language/Swift/index.ts new file mode 100644 index 000000000..902d4fff7 --- /dev/null +++ b/packages/quicktype-core/src/language/Swift/index.ts @@ -0,0 +1,2 @@ +export { SwiftTargetLanguage, swiftOptions } from "./language"; +export { SwiftRenderer } from "./SwiftRenderer"; diff --git a/packages/quicktype-core/src/language/Swift/language.ts b/packages/quicktype-core/src/language/Swift/language.ts new file mode 100644 index 000000000..152e932af --- /dev/null +++ b/packages/quicktype-core/src/language/Swift/language.ts @@ -0,0 +1,128 @@ +import { type DateTimeRecognizer } from "../../DateTime"; +import { type RenderContext } from "../../Renderer"; +import { BooleanOption, EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { AcronymStyleOptions, acronymOption } from "../../support/Acronyms"; +import { TargetLanguage } from "../../TargetLanguage"; +import { type PrimitiveStringTypeKind, type TransformedStringTypeKind } from "../../Type"; +import { type StringTypeMapping } from "../../TypeBuilder"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; + +import { SwiftRenderer } from "./SwiftRenderer"; +import { SwiftDateTimeRecognizer } from "./utils"; + +export const swiftOptions = { + justTypes: new BooleanOption("just-types", "Plain types only", false), + convenienceInitializers: new BooleanOption("initializers", "Generate initializers and mutators", true), + explicitCodingKeys: new BooleanOption("coding-keys", "Explicit CodingKey values in Codable types", true), + codingKeysProtocol: new StringOption( + "coding-keys-protocol", + "CodingKeys implements protocols", + "protocol1, protocol2...", + "", + "secondary" + ), + alamofire: new BooleanOption("alamofire", "Alamofire extensions", false), + namedTypePrefix: new StringOption("type-prefix", "Prefix for type names", "PREFIX", "", "secondary"), + useClasses: new EnumOption("struct-or-class", "Structs or classes", [ + ["struct", false], + ["class", true] + ]), + mutableProperties: new BooleanOption("mutable-properties", "Use var instead of let for object properties", false), + acronymStyle: acronymOption(AcronymStyleOptions.Pascal), + dense: new EnumOption( + "density", + "Code density", + [ + ["dense", true], + ["normal", false] + ], + "dense", + "secondary" + ), + linux: new BooleanOption("support-linux", "Support Linux", false, "secondary"), + objcSupport: new BooleanOption( + "objective-c-support", + "Objects inherit from NSObject and @objcMembers is added to classes", + false + ), + optionalEnums: new BooleanOption("optional-enums", "If no matching case is found enum value is set to null", false), + swift5Support: new BooleanOption("swift-5-support", "Renders output in a Swift 5 compatible mode", false), + sendable: new BooleanOption("sendable", "Mark generated models as Sendable", false), + multiFileOutput: new BooleanOption( + "multi-file-output", + "Renders each top-level object in its own Swift file", + false + ), + accessLevel: new EnumOption( + "access-level", + "Access level", + [ + ["internal", "internal"], + ["public", "public"] + ], + "internal", + "secondary" + ), + protocol: new EnumOption( + "protocol", + "Make types implement protocol", + [ + ["none", { equatable: false, hashable: false }], + ["equatable", { equatable: true, hashable: false }], + ["hashable", { equatable: false, hashable: true }] + ], + "none", + "secondary" + ) +}; + +export class SwiftTargetLanguage extends TargetLanguage { + public constructor() { + super("Swift", ["swift", "swift4"], "swift"); + } + + protected getOptions(): Array> { + return [ + swiftOptions.justTypes, + swiftOptions.useClasses, + swiftOptions.dense, + swiftOptions.convenienceInitializers, + swiftOptions.explicitCodingKeys, + swiftOptions.codingKeysProtocol, + swiftOptions.accessLevel, + swiftOptions.alamofire, + swiftOptions.linux, + swiftOptions.namedTypePrefix, + swiftOptions.protocol, + swiftOptions.acronymStyle, + swiftOptions.objcSupport, + swiftOptions.optionalEnums, + swiftOptions.sendable, + swiftOptions.swift5Support, + swiftOptions.multiFileOutput, + swiftOptions.mutableProperties + ]; + } + + public get stringTypeMapping(): StringTypeMapping { + const mapping: Map = new Map(); + mapping.set("date-time", "date-time"); + return mapping; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): SwiftRenderer { + return new SwiftRenderer(this, renderContext, getOptionValues(swiftOptions, untypedOptionValues)); + } + + public get dateTimeRecognizer(): DateTimeRecognizer { + return new SwiftDateTimeRecognizer(); + } +} diff --git a/packages/quicktype-core/src/language/Swift/utils.ts b/packages/quicktype-core/src/language/Swift/utils.ts new file mode 100644 index 000000000..ce4e2fa8b --- /dev/null +++ b/packages/quicktype-core/src/language/Swift/utils.ts @@ -0,0 +1,84 @@ +import { DefaultDateTimeRecognizer } from "../../DateTime"; +import { type Name } from "../../Naming"; +import { type ForEachPosition } from "../../Renderer"; +import { + addPrefixIfNecessary, + allLowerWordStyle, + allUpperWordStyle, + combineWords, + escapeNonPrintableMapper, + firstUpperWordStyle, + intToHex, + isDigit, + isLetterOrUnderscore, + isNumeric, + isPrintable, + legalizeCharacters, + splitIntoWords, + utf32ConcatMap +} from "../../support/Strings"; +import { type ClassProperty } from "../../Type"; + +export const MAX_SAMELINE_PROPERTIES = 4; + +// These are all recognized by Swift as ISO8601 date-times: +// +// 2018-08-14T02:45:50+00:00 +// 2018-08-14T02:45:50+00 +// 2018-08-14T02:45:50+1 +// 2018-08-14T02:45:50+1111 +// 2018-08-14T02:45:50+1111:1:33 +// 2018-08-14T02:45:50-00 +// 2018-08-14T02:45:50z +// 2018-00008-1T002:45:3Z + +const swiftDateTimeRegex = /^\d+-\d+-\d+T\d+:\d+:\d+([zZ]|[+-]\d+(:\d+)?)$/; + +export class SwiftDateTimeRecognizer extends DefaultDateTimeRecognizer { + public isDateTime(str: string): boolean { + return swiftDateTimeRegex.exec(str) !== null; + } +} + +export interface SwiftProperty { + jsonName: string; + name: Name; + parameter: ClassProperty; + position: ForEachPosition; +} + +function isPartCharacter(codePoint: number): boolean { + return isLetterOrUnderscore(codePoint) || isNumeric(codePoint); +} + +function isStartCharacter(codePoint: number): boolean { + return isPartCharacter(codePoint) && !isDigit(codePoint); +} + +const legalizeName = legalizeCharacters(isPartCharacter); + +export function swiftNameStyle( + prefix: string, + isUpper: boolean, + original: string, + acronymsStyle: (s: string) => string = allUpperWordStyle +): string { + const words = splitIntoWords(original); + const combined = combineWords( + words, + legalizeName, + isUpper ? firstUpperWordStyle : allLowerWordStyle, + firstUpperWordStyle, + isUpper ? allUpperWordStyle : allLowerWordStyle, + acronymsStyle, + "", + isStartCharacter + ); + return addPrefixIfNecessary(prefix, combined); +} + +function unicodeEscape(codePoint: number): string { + return "\\u{" + intToHex(codePoint, 0) + "}"; +} + +export const stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, unicodeEscape)); diff --git a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts b/packages/quicktype-core/src/language/TypeScriptEffectSchema/TypeScriptEffectSchemaRenderer.ts similarity index 82% rename from packages/quicktype-core/src/language/TypeScriptEffectSchema.ts rename to packages/quicktype-core/src/language/TypeScriptEffectSchema/TypeScriptEffectSchemaRenderer.ts index c3844d847..f06807a39 100644 --- a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts +++ b/packages/quicktype-core/src/language/TypeScriptEffectSchema/TypeScriptEffectSchemaRenderer.ts @@ -1,11 +1,11 @@ import { arrayIntercalate } from "collection-utils"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Name, type Namer, funPrefixNamer } from "../Naming"; -import { type RenderContext } from "../Renderer"; -import { BooleanOption, type Option, type OptionValues, getOptionValues } from "../RendererOptions"; -import { type Sourcelike } from "../Source"; -import { AcronymStyleOptions, acronymStyle } from "../support/Acronyms"; +import { ConvenienceRenderer } from "../../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type Sourcelike } from "../../Source"; +import { AcronymStyleOptions, acronymStyle } from "../../support/Acronyms"; import { allLowerWordStyle, capitalize, @@ -15,43 +15,14 @@ import { splitIntoWords, stringEscape, utf16StringEscape -} from "../support/Strings"; -import { panic } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; -import { ArrayType, type ClassProperty, EnumType, MapType, type ObjectType, type Type } from "../Type"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; -import { matchType } from "../TypeUtils"; - -import { legalizeName } from "./JavaScript"; - -export const typeScriptEffectSchemaOptions = { - justSchema: new BooleanOption("just-schema", "Schema only", false) -}; - -export class TypeScriptEffectSchemaTargetLanguage extends TargetLanguage { - protected getOptions(): Array> { - return []; - } - - public constructor( - displayName: string = "TypeScript Effect Schema", - names: string[] = ["typescript-effect-schema"], - extension: string = "ts" - ) { - super(displayName, names, extension); - } - - protected makeRenderer( - renderContext: RenderContext, - untypedOptionValues: FixMeOptionsType - ): TypeScriptEffectSchemaRenderer { - return new TypeScriptEffectSchemaRenderer( - this, - renderContext, - getOptionValues(typeScriptEffectSchemaOptions, untypedOptionValues) - ); - } -} +} from "../../support/Strings"; +import { panic } from "../../support/Support"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { ArrayType, type ClassProperty, EnumType, MapType, type ObjectType, type Type } from "../../Type"; +import { matchType } from "../../TypeUtils"; +import { legalizeName } from "../JavaScript/utils"; + +import { type typeScriptEffectSchemaOptions } from "./language"; export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { private emittedObjects = new Set(); diff --git a/packages/quicktype-core/src/language/TypeScriptEffectSchema/index.ts b/packages/quicktype-core/src/language/TypeScriptEffectSchema/index.ts new file mode 100644 index 000000000..ea8cf8149 --- /dev/null +++ b/packages/quicktype-core/src/language/TypeScriptEffectSchema/index.ts @@ -0,0 +1,2 @@ +export { TypeScriptEffectSchemaTargetLanguage, typeScriptEffectSchemaOptions } from "./language"; +export { TypeScriptEffectSchemaRenderer } from "./TypeScriptEffectSchemaRenderer"; diff --git a/packages/quicktype-core/src/language/TypeScriptEffectSchema/language.ts b/packages/quicktype-core/src/language/TypeScriptEffectSchema/language.ts new file mode 100644 index 000000000..5e311edb0 --- /dev/null +++ b/packages/quicktype-core/src/language/TypeScriptEffectSchema/language.ts @@ -0,0 +1,35 @@ +import { type RenderContext } from "../../Renderer"; +import { BooleanOption, type Option, getOptionValues } from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; + +import { TypeScriptEffectSchemaRenderer } from "./TypeScriptEffectSchemaRenderer"; + +export const typeScriptEffectSchemaOptions = { + justSchema: new BooleanOption("just-schema", "Schema only", false) +}; + +export class TypeScriptEffectSchemaTargetLanguage extends TargetLanguage { + protected getOptions(): Array> { + return []; + } + + public constructor( + displayName: string = "TypeScript Effect Schema", + names: string[] = ["typescript-effect-schema"], + extension: string = "ts" + ) { + super(displayName, names, extension); + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: FixMeOptionsType + ): TypeScriptEffectSchemaRenderer { + return new TypeScriptEffectSchemaRenderer( + this, + renderContext, + getOptionValues(typeScriptEffectSchemaOptions, untypedOptionValues) + ); + } +} diff --git a/packages/quicktype-core/src/language/TypeScriptFlow.ts b/packages/quicktype-core/src/language/TypeScriptFlow.ts deleted file mode 100644 index 202b95b4e..000000000 --- a/packages/quicktype-core/src/language/TypeScriptFlow.ts +++ /dev/null @@ -1,406 +0,0 @@ -import { type Name, type Namer, funPrefixNamer } from "../Naming"; -import { type RenderContext } from "../Renderer"; -import { BooleanOption, type Option, type OptionValues, getOptionValues } from "../RendererOptions"; -import { type MultiWord, type Sourcelike, modifySource, multiWord, parenIfNeeded, singleWord } from "../Source"; -import { camelCase, utf16StringEscape } from "../support/Strings"; -import { defined, panic } from "../support/Support"; -import { type TargetLanguage } from "../TargetLanguage"; -import { ArrayType, type ClassType, EnumType, type Type, UnionType } from "../Type"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; -import { isNamedType, matchType, nullableFromUnion } from "../TypeUtils"; - -import { - JavaScriptRenderer, - JavaScriptTargetLanguage, - type JavaScriptTypeAnnotations, - javaScriptOptions, - legalizeName -} from "./JavaScript"; -import { isES3IdentifierStart } from "./JavaScriptUnicodeMaps"; - -export const tsFlowOptions = Object.assign({}, javaScriptOptions, { - justTypes: new BooleanOption("just-types", "Interfaces only", false), - nicePropertyNames: new BooleanOption("nice-property-names", "Transform property names to be JavaScripty", false), - declareUnions: new BooleanOption("explicit-unions", "Explicitly name unions", false), - preferUnions: new BooleanOption("prefer-unions", "Use union type instead of enum", false), - preferTypes: new BooleanOption("prefer-types", "Use types instead of interfaces", false), - preferConstValues: new BooleanOption( - "prefer-const-values", - "Use string instead of enum for string enums with single value", - false - ), - readonly: new BooleanOption("readonly", "Use readonly type members", false) -}); - -const tsFlowTypeAnnotations = { - any: ": any", - anyArray: ": any[]", - anyMap: ": { [k: string]: any }", - string: ": string", - stringArray: ": string[]", - boolean: ": boolean" -}; - -export abstract class TypeScriptFlowBaseTargetLanguage extends JavaScriptTargetLanguage { - protected getOptions(): Array> { - return [ - tsFlowOptions.justTypes, - tsFlowOptions.nicePropertyNames, - tsFlowOptions.declareUnions, - tsFlowOptions.runtimeTypecheck, - tsFlowOptions.runtimeTypecheckIgnoreUnknownProperties, - tsFlowOptions.acronymStyle, - tsFlowOptions.converters, - tsFlowOptions.rawType, - tsFlowOptions.preferUnions, - tsFlowOptions.preferTypes, - tsFlowOptions.preferConstValues, - tsFlowOptions.readonly - ]; - } - - public get supportsOptionalClassProperties(): boolean { - return true; - } - - protected abstract makeRenderer( - renderContext: RenderContext, - untypedOptionValues: FixMeOptionsType - ): JavaScriptRenderer; -} - -export class TypeScriptTargetLanguage extends TypeScriptFlowBaseTargetLanguage { - public constructor() { - super("TypeScript", ["typescript", "ts", "tsx"], "ts"); - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): TypeScriptRenderer { - return new TypeScriptRenderer(this, renderContext, getOptionValues(tsFlowOptions, untypedOptionValues)); - } -} - -function quotePropertyName(original: string): string { - const escaped = utf16StringEscape(original); - const quoted = `"${escaped}"`; - - if (original.length === 0) { - return quoted; - } else if (!isES3IdentifierStart(original.codePointAt(0) as number)) { - return quoted; - } else if (escaped !== original) { - return quoted; - } else if (legalizeName(original) !== original) { - return quoted; - } else { - return original; - } -} - -export abstract class TypeScriptFlowBaseRenderer extends JavaScriptRenderer { - public constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - protected readonly _tsFlowOptions: OptionValues - ) { - super(targetLanguage, renderContext, _tsFlowOptions); - } - - protected namerForObjectProperty(): Namer { - if (this._tsFlowOptions.nicePropertyNames) { - return funPrefixNamer("properties", s => this.nameStyle(s, false)); - } else { - return super.namerForObjectProperty(); - } - } - - protected sourceFor(t: Type): MultiWord { - if (this._tsFlowOptions.preferConstValues && t.kind === "enum" && t instanceof EnumType && t.cases.size === 1) { - const item = t.cases.values().next().value; - return singleWord(`"${utf16StringEscape(item)}"`); - } - - if (["class", "object", "enum"].includes(t.kind)) { - return singleWord(this.nameForNamedType(t)); - } - - return matchType( - t, - _anyType => singleWord("any"), - _nullType => singleWord("null"), - _boolType => singleWord("boolean"), - _integerType => singleWord("number"), - _doubleType => singleWord("number"), - _stringType => singleWord("string"), - arrayType => { - const itemType = this.sourceFor(arrayType.items); - if ( - (arrayType.items instanceof UnionType && !this._tsFlowOptions.declareUnions) || - arrayType.items instanceof ArrayType - ) { - return singleWord(["Array<", itemType.source, ">"]); - } else { - return singleWord([parenIfNeeded(itemType), "[]"]); - } - }, - _classType => panic("We handled this above"), - mapType => singleWord(["{ [key: string]: ", this.sourceFor(mapType.values).source, " }"]), - _enumType => panic("We handled this above"), - unionType => { - if (!this._tsFlowOptions.declareUnions || nullableFromUnion(unionType) !== null) { - const children = Array.from(unionType.getChildren()).map(c => parenIfNeeded(this.sourceFor(c))); - return multiWord(" | ", ...children); - } else { - return singleWord(this.nameForNamedType(unionType)); - } - }, - transformedStringType => { - if (transformedStringType.kind === "date-time") { - return singleWord("Date"); - } - - return singleWord("string"); - } - ); - } - - protected abstract emitEnum(e: EnumType, enumName: Name): void; - - protected abstract emitClassBlock(c: ClassType, className: Name): void; - - protected emitClassBlockBody(c: ClassType): void { - this.emitPropertyTable(c, (name, _jsonName, p) => { - const t = p.type; - - let propertyName: Sourcelike = name; - propertyName = modifySource(quotePropertyName, name); - - if (this._tsFlowOptions.readonly) { - propertyName = modifySource(_propertyName => "readonly " + _propertyName, propertyName); - } - - return [ - [propertyName, p.isOptional ? "?" : "", ": "], - [this.sourceFor(t).source, ";"] - ]; - }); - - const additionalProperties = c.getAdditionalProperties(); - if (additionalProperties) { - this.emitTable([["[property: string]", ": ", this.sourceFor(additionalProperties).source, ";"]]); - } - } - - private emitClass(c: ClassType, className: Name): void { - this.emitDescription(this.descriptionForType(c)); - this.emitClassBlock(c, className); - } - - protected emitUnion(u: UnionType, unionName: Name): void { - if (!this._tsFlowOptions.declareUnions) { - return; - } - - this.emitDescription(this.descriptionForType(u)); - - const children = multiWord(" | ", ...Array.from(u.getChildren()).map(c => parenIfNeeded(this.sourceFor(c)))); - this.emitLine("export type ", unionName, " = ", children.source, ";"); - } - - protected emitTypes(): void { - // emit primitive top levels - this.forEachTopLevel("none", (t, name) => { - if (!t.isPrimitive()) { - return; - } - - this.ensureBlankLine(); - this.emitDescription(this.descriptionForType(t)); - this.emitLine("type ", name, " = ", this.sourceFor(t).source, ";"); - }); - - this.forEachNamedType( - "leading-and-interposing", - (c: ClassType, n: Name) => this.emitClass(c, n), - (e, n) => this.emitEnum(e, n), - (u, n) => this.emitUnion(u, n) - ); - } - - protected emitUsageComments(): void { - if (this._tsFlowOptions.justTypes) return; - super.emitUsageComments(); - } - - protected deserializerFunctionLine(t: Type, name: Name): Sourcelike { - const jsonType = this._tsFlowOptions.rawType === "json" ? "string" : "any"; - return ["function to", name, "(json: ", jsonType, "): ", this.sourceFor(t).source]; - } - - protected serializerFunctionLine(t: Type, name: Name): Sourcelike { - const camelCaseName = modifySource(camelCase, name); - const returnType = this._tsFlowOptions.rawType === "json" ? "string" : "any"; - return ["function ", camelCaseName, "ToJson(value: ", this.sourceFor(t).source, "): ", returnType]; - } - - protected get moduleLine(): string | undefined { - return undefined; - } - - protected get castFunctionLines(): [string, string] { - return ["function cast(val: any, typ: any): T", "function uncast(val: T, typ: any): any"]; - } - - protected get typeAnnotations(): JavaScriptTypeAnnotations { - throw new Error("not implemented"); - } - - protected emitConvertModule(): void { - if (this._tsFlowOptions.justTypes) return; - super.emitConvertModule(); - } - - protected emitConvertModuleHelpers(): void { - if (this._tsFlowOptions.justTypes) return; - super.emitConvertModuleHelpers(); - } - - protected emitModuleExports(): void { - if (this._tsFlowOptions.justTypes) { - return; - } else { - super.emitModuleExports(); - } - } -} - -export class TypeScriptRenderer extends TypeScriptFlowBaseRenderer { - protected forbiddenNamesForGlobalNamespace(): string[] { - return ["Array", "Date"]; - } - - protected deserializerFunctionLine(t: Type, name: Name): Sourcelike { - const jsonType = this._tsFlowOptions.rawType === "json" ? "string" : "any"; - return ["public static to", name, "(json: ", jsonType, "): ", this.sourceFor(t).source]; - } - - protected serializerFunctionLine(t: Type, name: Name): Sourcelike { - const camelCaseName = modifySource(camelCase, name); - const returnType = this._tsFlowOptions.rawType === "json" ? "string" : "any"; - return ["public static ", camelCaseName, "ToJson(value: ", this.sourceFor(t).source, "): ", returnType]; - } - - protected get moduleLine(): string | undefined { - return "export class Convert"; - } - - protected get typeAnnotations(): JavaScriptTypeAnnotations { - return Object.assign({ never: ": never" }, tsFlowTypeAnnotations); - } - - protected emitModuleExports(): void { - return; - } - - protected emitUsageImportComment(): void { - const topLevelNames: Sourcelike[] = []; - this.forEachTopLevel( - "none", - (_t, name) => { - topLevelNames.push(", ", name); - }, - isNamedType - ); - this.emitLine("// import { Convert", topLevelNames, ' } from "./file";'); - } - - protected emitEnum(e: EnumType, enumName: Name): void { - this.emitDescription(this.descriptionForType(e)); - - // enums with only one value are emitted as constants - if (this._tsFlowOptions.preferConstValues && e.cases.size === 1) return; - - if (this._tsFlowOptions.preferUnions) { - let items = ""; - e.cases.forEach(item => { - if (items === "") { - items += `"${utf16StringEscape(item)}"`; - return; - } - - items += ` | "${utf16StringEscape(item)}"`; - }); - this.emitLine("export type ", enumName, " = ", items, ";"); - } else { - this.emitBlock(["export enum ", enumName, " "], "", () => { - this.forEachEnumCase(e, "none", (name, jsonName) => { - this.emitLine(name, ` = "${utf16StringEscape(jsonName)}",`); - }); - }); - } - } - - protected emitClassBlock(c: ClassType, className: Name): void { - this.emitBlock( - this._tsFlowOptions.preferTypes - ? ["export type ", className, " = "] - : ["export interface ", className, " "], - "", - () => { - this.emitClassBlockBody(c); - } - ); - } - - protected emitSourceStructure() { - super.emitSourceStructure(); - } -} - -export class FlowTargetLanguage extends TypeScriptFlowBaseTargetLanguage { - public constructor() { - super("Flow", ["flow"], "js"); - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): FlowRenderer { - return new FlowRenderer(this, renderContext, getOptionValues(tsFlowOptions, untypedOptionValues)); - } -} - -export class FlowRenderer extends TypeScriptFlowBaseRenderer { - protected forbiddenNamesForGlobalNamespace(): string[] { - return ["Class", "Date", "Object", "String", "Array", "JSON", "Error"]; - } - - protected get typeAnnotations(): JavaScriptTypeAnnotations { - return Object.assign({ never: "" }, tsFlowTypeAnnotations); - } - - protected emitEnum(e: EnumType, enumName: Name): void { - this.emitDescription(this.descriptionForType(e)); - const lines: string[][] = []; - this.forEachEnumCase(e, "none", (_, jsonName) => { - const maybeOr = lines.length === 0 ? " " : "| "; - lines.push([maybeOr, '"', utf16StringEscape(jsonName), '"']); - }); - defined(lines[lines.length - 1]).push(";"); - - this.emitLine("export type ", enumName, " ="); - this.indent(() => { - for (const line of lines) { - this.emitLine(line); - } - }); - } - - protected emitClassBlock(c: ClassType, className: Name): void { - this.emitBlock(["export type ", className, " = "], ";", () => { - this.emitClassBlockBody(c); - }); - } - - protected emitSourceStructure(): void { - this.emitLine("// @flow"); - this.ensureBlankLine(); - super.emitSourceStructure(); - } -} diff --git a/packages/quicktype-core/src/language/TypeScriptFlow/FlowRenderer.ts b/packages/quicktype-core/src/language/TypeScriptFlow/FlowRenderer.ts new file mode 100644 index 000000000..eb4695583 --- /dev/null +++ b/packages/quicktype-core/src/language/TypeScriptFlow/FlowRenderer.ts @@ -0,0 +1,47 @@ +import { type Name } from "../../Naming"; +import { utf16StringEscape } from "../../support/Strings"; +import { defined } from "../../support/Support"; +import { type ClassType, type EnumType } from "../../Type"; +import { type JavaScriptTypeAnnotations } from "../JavaScript"; + +import { TypeScriptFlowBaseRenderer } from "./TypeScriptFlowBaseRenderer"; +import { tsFlowTypeAnnotations } from "./utils"; + +export class FlowRenderer extends TypeScriptFlowBaseRenderer { + protected forbiddenNamesForGlobalNamespace(): string[] { + return ["Class", "Date", "Object", "String", "Array", "JSON", "Error"]; + } + + protected get typeAnnotations(): JavaScriptTypeAnnotations { + return Object.assign({ never: "" }, tsFlowTypeAnnotations); + } + + protected emitEnum(e: EnumType, enumName: Name): void { + this.emitDescription(this.descriptionForType(e)); + const lines: string[][] = []; + this.forEachEnumCase(e, "none", (_, jsonName) => { + const maybeOr = lines.length === 0 ? " " : "| "; + lines.push([maybeOr, '"', utf16StringEscape(jsonName), '"']); + }); + defined(lines[lines.length - 1]).push(";"); + + this.emitLine("export type ", enumName, " ="); + this.indent(() => { + for (const line of lines) { + this.emitLine(line); + } + }); + } + + protected emitClassBlock(c: ClassType, className: Name): void { + this.emitBlock(["export type ", className, " = "], ";", () => { + this.emitClassBlockBody(c); + }); + } + + protected emitSourceStructure(): void { + this.emitLine("// @flow"); + this.ensureBlankLine(); + super.emitSourceStructure(); + } +} diff --git a/packages/quicktype-core/src/language/TypeScriptFlow/TypeScriptFlowBaseRenderer.ts b/packages/quicktype-core/src/language/TypeScriptFlow/TypeScriptFlowBaseRenderer.ts new file mode 100644 index 000000000..3cc9b09bf --- /dev/null +++ b/packages/quicktype-core/src/language/TypeScriptFlow/TypeScriptFlowBaseRenderer.ts @@ -0,0 +1,190 @@ +import { type Name, type Namer, funPrefixNamer } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type MultiWord, type Sourcelike, modifySource, multiWord, parenIfNeeded, singleWord } from "../../Source"; +import { camelCase, utf16StringEscape } from "../../support/Strings"; +import { panic } from "../../support/Support"; +import { type TargetLanguage } from "../../TargetLanguage"; +import { ArrayType, type ClassType, EnumType, type Type, UnionType } from "../../Type"; +import { matchType, nullableFromUnion } from "../../TypeUtils"; +import { JavaScriptRenderer, type JavaScriptTypeAnnotations } from "../JavaScript"; + +import { type tsFlowOptions } from "./language"; +import { quotePropertyName } from "./utils"; + +export abstract class TypeScriptFlowBaseRenderer extends JavaScriptRenderer { + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + protected readonly _tsFlowOptions: OptionValues + ) { + super(targetLanguage, renderContext, _tsFlowOptions); + } + + protected namerForObjectProperty(): Namer { + if (this._tsFlowOptions.nicePropertyNames) { + return funPrefixNamer("properties", s => this.nameStyle(s, false)); + } else { + return super.namerForObjectProperty(); + } + } + + protected sourceFor(t: Type): MultiWord { + if (this._tsFlowOptions.preferConstValues && t.kind === "enum" && t instanceof EnumType && t.cases.size === 1) { + const item = t.cases.values().next().value; + return singleWord(`"${utf16StringEscape(item)}"`); + } + + if (["class", "object", "enum"].includes(t.kind)) { + return singleWord(this.nameForNamedType(t)); + } + + return matchType( + t, + _anyType => singleWord("any"), + _nullType => singleWord("null"), + _boolType => singleWord("boolean"), + _integerType => singleWord("number"), + _doubleType => singleWord("number"), + _stringType => singleWord("string"), + arrayType => { + const itemType = this.sourceFor(arrayType.items); + if ( + (arrayType.items instanceof UnionType && !this._tsFlowOptions.declareUnions) || + arrayType.items instanceof ArrayType + ) { + return singleWord(["Array<", itemType.source, ">"]); + } else { + return singleWord([parenIfNeeded(itemType), "[]"]); + } + }, + _classType => panic("We handled this above"), + mapType => singleWord(["{ [key: string]: ", this.sourceFor(mapType.values).source, " }"]), + _enumType => panic("We handled this above"), + unionType => { + if (!this._tsFlowOptions.declareUnions || nullableFromUnion(unionType) !== null) { + const children = Array.from(unionType.getChildren()).map(c => parenIfNeeded(this.sourceFor(c))); + return multiWord(" | ", ...children); + } else { + return singleWord(this.nameForNamedType(unionType)); + } + }, + transformedStringType => { + if (transformedStringType.kind === "date-time") { + return singleWord("Date"); + } + + return singleWord("string"); + } + ); + } + + protected abstract emitEnum(e: EnumType, enumName: Name): void; + + protected abstract emitClassBlock(c: ClassType, className: Name): void; + + protected emitClassBlockBody(c: ClassType): void { + this.emitPropertyTable(c, (name, _jsonName, p) => { + const t = p.type; + + let propertyName: Sourcelike = name; + propertyName = modifySource(quotePropertyName, name); + + if (this._tsFlowOptions.readonly) { + propertyName = modifySource(_propertyName => "readonly " + _propertyName, propertyName); + } + + return [ + [propertyName, p.isOptional ? "?" : "", ": "], + [this.sourceFor(t).source, ";"] + ]; + }); + + const additionalProperties = c.getAdditionalProperties(); + if (additionalProperties) { + this.emitTable([["[property: string]", ": ", this.sourceFor(additionalProperties).source, ";"]]); + } + } + + private emitClass(c: ClassType, className: Name): void { + this.emitDescription(this.descriptionForType(c)); + this.emitClassBlock(c, className); + } + + protected emitUnion(u: UnionType, unionName: Name): void { + if (!this._tsFlowOptions.declareUnions) { + return; + } + + this.emitDescription(this.descriptionForType(u)); + + const children = multiWord(" | ", ...Array.from(u.getChildren()).map(c => parenIfNeeded(this.sourceFor(c)))); + this.emitLine("export type ", unionName, " = ", children.source, ";"); + } + + protected emitTypes(): void { + // emit primitive top levels + this.forEachTopLevel("none", (t, name) => { + if (!t.isPrimitive()) { + return; + } + + this.ensureBlankLine(); + this.emitDescription(this.descriptionForType(t)); + this.emitLine("type ", name, " = ", this.sourceFor(t).source, ";"); + }); + + this.forEachNamedType( + "leading-and-interposing", + (c: ClassType, n: Name) => this.emitClass(c, n), + (e, n) => this.emitEnum(e, n), + (u, n) => this.emitUnion(u, n) + ); + } + + protected emitUsageComments(): void { + if (this._tsFlowOptions.justTypes) return; + super.emitUsageComments(); + } + + protected deserializerFunctionLine(t: Type, name: Name): Sourcelike { + const jsonType = this._tsFlowOptions.rawType === "json" ? "string" : "any"; + return ["function to", name, "(json: ", jsonType, "): ", this.sourceFor(t).source]; + } + + protected serializerFunctionLine(t: Type, name: Name): Sourcelike { + const camelCaseName = modifySource(camelCase, name); + const returnType = this._tsFlowOptions.rawType === "json" ? "string" : "any"; + return ["function ", camelCaseName, "ToJson(value: ", this.sourceFor(t).source, "): ", returnType]; + } + + protected get moduleLine(): string | undefined { + return undefined; + } + + protected get castFunctionLines(): [string, string] { + return ["function cast(val: any, typ: any): T", "function uncast(val: T, typ: any): any"]; + } + + protected get typeAnnotations(): JavaScriptTypeAnnotations { + throw new Error("not implemented"); + } + + protected emitConvertModule(): void { + if (this._tsFlowOptions.justTypes) return; + super.emitConvertModule(); + } + + protected emitConvertModuleHelpers(): void { + if (this._tsFlowOptions.justTypes) return; + super.emitConvertModuleHelpers(); + } + + protected emitModuleExports(): void { + if (this._tsFlowOptions.justTypes) { + return; + } else { + super.emitModuleExports(); + } + } +} diff --git a/packages/quicktype-core/src/language/TypeScriptFlow/TypeScriptRenderer.ts b/packages/quicktype-core/src/language/TypeScriptFlow/TypeScriptRenderer.ts new file mode 100644 index 000000000..74edd55ed --- /dev/null +++ b/packages/quicktype-core/src/language/TypeScriptFlow/TypeScriptRenderer.ts @@ -0,0 +1,88 @@ +import { type Name } from "../../Naming"; +import { type Sourcelike, modifySource } from "../../Source"; +import { camelCase, utf16StringEscape } from "../../support/Strings"; +import { type ClassType, type EnumType, type Type } from "../../Type"; +import { isNamedType } from "../../TypeUtils"; +import { type JavaScriptTypeAnnotations } from "../JavaScript"; + +import { TypeScriptFlowBaseRenderer } from "./TypeScriptFlowBaseRenderer"; +import { tsFlowTypeAnnotations } from "./utils"; + +export class TypeScriptRenderer extends TypeScriptFlowBaseRenderer { + protected forbiddenNamesForGlobalNamespace(): string[] { + return ["Array", "Date"]; + } + + protected deserializerFunctionLine(t: Type, name: Name): Sourcelike { + const jsonType = this._tsFlowOptions.rawType === "json" ? "string" : "any"; + return ["public static to", name, "(json: ", jsonType, "): ", this.sourceFor(t).source]; + } + + protected serializerFunctionLine(t: Type, name: Name): Sourcelike { + const camelCaseName = modifySource(camelCase, name); + const returnType = this._tsFlowOptions.rawType === "json" ? "string" : "any"; + return ["public static ", camelCaseName, "ToJson(value: ", this.sourceFor(t).source, "): ", returnType]; + } + + protected get moduleLine(): string | undefined { + return "export class Convert"; + } + + protected get typeAnnotations(): JavaScriptTypeAnnotations { + return Object.assign({ never: ": never" }, tsFlowTypeAnnotations); + } + + protected emitModuleExports(): void { + return; + } + + protected emitUsageImportComment(): void { + const topLevelNames: Sourcelike[] = []; + this.forEachTopLevel( + "none", + (_t, name) => { + topLevelNames.push(", ", name); + }, + isNamedType + ); + this.emitLine("// import { Convert", topLevelNames, ' } from "./file";'); + } + + protected emitEnum(e: EnumType, enumName: Name): void { + this.emitDescription(this.descriptionForType(e)); + + // enums with only one value are emitted as constants + if (this._tsFlowOptions.preferConstValues && e.cases.size === 1) return; + + if (this._tsFlowOptions.preferUnions) { + let items = ""; + e.cases.forEach(item => { + if (items === "") { + items += `"${utf16StringEscape(item)}"`; + return; + } + + items += ` | "${utf16StringEscape(item)}"`; + }); + this.emitLine("export type ", enumName, " = ", items, ";"); + } else { + this.emitBlock(["export enum ", enumName, " "], "", () => { + this.forEachEnumCase(e, "none", (name, jsonName) => { + this.emitLine(name, ` = "${utf16StringEscape(jsonName)}",`); + }); + }); + } + } + + protected emitClassBlock(c: ClassType, className: Name): void { + this.emitBlock( + this._tsFlowOptions.preferTypes + ? ["export type ", className, " = "] + : ["export interface ", className, " "], + "", + () => { + this.emitClassBlockBody(c); + } + ); + } +} diff --git a/packages/quicktype-core/src/language/TypeScriptFlow/index.ts b/packages/quicktype-core/src/language/TypeScriptFlow/index.ts new file mode 100644 index 000000000..681acaa34 --- /dev/null +++ b/packages/quicktype-core/src/language/TypeScriptFlow/index.ts @@ -0,0 +1,3 @@ +export { FlowRenderer } from "./FlowRenderer"; +export { TypeScriptRenderer } from "./TypeScriptRenderer"; +export { FlowTargetLanguage, TypeScriptTargetLanguage, tsFlowOptions } from "./language"; diff --git a/packages/quicktype-core/src/language/TypeScriptFlow/language.ts b/packages/quicktype-core/src/language/TypeScriptFlow/language.ts new file mode 100644 index 000000000..8f8c37af5 --- /dev/null +++ b/packages/quicktype-core/src/language/TypeScriptFlow/language.ts @@ -0,0 +1,68 @@ +import { type RenderContext } from "../../Renderer"; +import { BooleanOption, type Option, getOptionValues } from "../../RendererOptions"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; +import { type JavaScriptRenderer, JavaScriptTargetLanguage, javaScriptOptions } from "../JavaScript"; + +import { FlowRenderer } from "./FlowRenderer"; +import { TypeScriptRenderer } from "./TypeScriptRenderer"; + +export const tsFlowOptions = Object.assign({}, javaScriptOptions, { + justTypes: new BooleanOption("just-types", "Interfaces only", false), + nicePropertyNames: new BooleanOption("nice-property-names", "Transform property names to be JavaScripty", false), + declareUnions: new BooleanOption("explicit-unions", "Explicitly name unions", false), + preferUnions: new BooleanOption("prefer-unions", "Use union type instead of enum", false), + preferTypes: new BooleanOption("prefer-types", "Use types instead of interfaces", false), + preferConstValues: new BooleanOption( + "prefer-const-values", + "Use string instead of enum for string enums with single value", + false + ), + readonly: new BooleanOption("readonly", "Use readonly type members", false) +}); + +export abstract class TypeScriptFlowBaseTargetLanguage extends JavaScriptTargetLanguage { + protected getOptions(): Array> { + return [ + tsFlowOptions.justTypes, + tsFlowOptions.nicePropertyNames, + tsFlowOptions.declareUnions, + tsFlowOptions.runtimeTypecheck, + tsFlowOptions.runtimeTypecheckIgnoreUnknownProperties, + tsFlowOptions.acronymStyle, + tsFlowOptions.converters, + tsFlowOptions.rawType, + tsFlowOptions.preferUnions, + tsFlowOptions.preferTypes, + tsFlowOptions.preferConstValues, + tsFlowOptions.readonly + ]; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + protected abstract makeRenderer( + renderContext: RenderContext, + untypedOptionValues: FixMeOptionsType + ): JavaScriptRenderer; +} + +export class TypeScriptTargetLanguage extends TypeScriptFlowBaseTargetLanguage { + public constructor() { + super("TypeScript", ["typescript", "ts", "tsx"], "ts"); + } + + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): TypeScriptRenderer { + return new TypeScriptRenderer(this, renderContext, getOptionValues(tsFlowOptions, untypedOptionValues)); + } +} +export class FlowTargetLanguage extends TypeScriptFlowBaseTargetLanguage { + public constructor() { + super("Flow", ["flow"], "js"); + } + + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): FlowRenderer { + return new FlowRenderer(this, renderContext, getOptionValues(tsFlowOptions, untypedOptionValues)); + } +} diff --git a/packages/quicktype-core/src/language/TypeScriptFlow/utils.ts b/packages/quicktype-core/src/language/TypeScriptFlow/utils.ts new file mode 100644 index 000000000..b15b7eb1d --- /dev/null +++ b/packages/quicktype-core/src/language/TypeScriptFlow/utils.ts @@ -0,0 +1,29 @@ +import { utf16StringEscape } from "../../support/Strings"; +import { isES3IdentifierStart } from "../JavaScript/unicodeMaps"; +import { legalizeName } from "../JavaScript/utils"; + +export const tsFlowTypeAnnotations = { + any: ": any", + anyArray: ": any[]", + anyMap: ": { [k: string]: any }", + string: ": string", + stringArray: ": string[]", + boolean: ": boolean" +}; + +export function quotePropertyName(original: string): string { + const escaped = utf16StringEscape(original); + const quoted = `"${escaped}"`; + + if (original.length === 0) { + return quoted; + } else if (!isES3IdentifierStart(original.codePointAt(0) as number)) { + return quoted; + } else if (escaped !== original) { + return quoted; + } else if (legalizeName(original) !== original) { + return quoted; + } else { + return original; + } +} diff --git a/packages/quicktype-core/src/language/TypeScriptZod.ts b/packages/quicktype-core/src/language/TypeScriptZod/TypeScriptZodRenderer.ts similarity index 85% rename from packages/quicktype-core/src/language/TypeScriptZod.ts rename to packages/quicktype-core/src/language/TypeScriptZod/TypeScriptZodRenderer.ts index ada7494a9..a886288aa 100644 --- a/packages/quicktype-core/src/language/TypeScriptZod.ts +++ b/packages/quicktype-core/src/language/TypeScriptZod/TypeScriptZodRenderer.ts @@ -1,11 +1,11 @@ import { arrayIntercalate } from "collection-utils"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { type Name, type Namer, funPrefixNamer } from "../Naming"; -import { type RenderContext } from "../Renderer"; -import { BooleanOption, type Option, type OptionValues, getOptionValues } from "../RendererOptions"; -import { type Sourcelike } from "../Source"; -import { AcronymStyleOptions, acronymStyle } from "../support/Acronyms"; +import { ConvenienceRenderer } from "../../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../../Naming"; +import { type RenderContext } from "../../Renderer"; +import { type OptionValues } from "../../RendererOptions"; +import { type Sourcelike } from "../../Source"; +import { AcronymStyleOptions, acronymStyle } from "../../support/Acronyms"; import { allLowerWordStyle, capitalize, @@ -15,62 +15,22 @@ import { splitIntoWords, stringEscape, utf16StringEscape -} from "../support/Strings"; -import { panic } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; +} from "../../support/Strings"; +import { panic } from "../../support/Support"; +import { type TargetLanguage } from "../../TargetLanguage"; import { ArrayType, type ClassProperty, ClassType, type EnumType, ObjectType, - type PrimitiveStringTypeKind, SetOperationType, - type TransformedStringTypeKind, type Type -} from "../Type"; -import { type StringTypeMapping } from "../TypeBuilder"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../types"; -import { matchType } from "../TypeUtils"; +} from "../../Type"; +import { matchType } from "../../TypeUtils"; +import { legalizeName } from "../JavaScript/utils"; -import { legalizeName } from "./JavaScript"; - -export const typeScriptZodOptions = { - justSchema: new BooleanOption("just-schema", "Schema only", false) -}; - -export class TypeScriptZodTargetLanguage extends TargetLanguage { - protected getOptions(): Array> { - return []; - } - - public constructor( - displayName: string = "TypeScript Zod", - names: string[] = ["typescript-zod"], - extension: string = "ts" - ) { - super(displayName, names, extension); - } - - public get stringTypeMapping(): StringTypeMapping { - const mapping: Map = new Map(); - const dateTimeType = "date-time"; - mapping.set("date-time", dateTimeType); - return mapping; - } - - public get supportsOptionalClassProperties(): boolean { - return true; - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): TypeScriptZodRenderer { - return new TypeScriptZodRenderer( - this, - renderContext, - getOptionValues(typeScriptZodOptions, untypedOptionValues) - ); - } -} +import { type typeScriptZodOptions } from "./language"; export class TypeScriptZodRenderer extends ConvenienceRenderer { public constructor( diff --git a/packages/quicktype-core/src/language/TypeScriptZod/index.ts b/packages/quicktype-core/src/language/TypeScriptZod/index.ts new file mode 100644 index 000000000..657c2f91c --- /dev/null +++ b/packages/quicktype-core/src/language/TypeScriptZod/index.ts @@ -0,0 +1,2 @@ +export { TypeScriptZodTargetLanguage, typeScriptZodOptions } from "./language"; +export { TypeScriptZodRenderer } from "./TypeScriptZodRenderer"; diff --git a/packages/quicktype-core/src/language/TypeScriptZod/language.ts b/packages/quicktype-core/src/language/TypeScriptZod/language.ts new file mode 100644 index 000000000..a22f1298a --- /dev/null +++ b/packages/quicktype-core/src/language/TypeScriptZod/language.ts @@ -0,0 +1,45 @@ +import { type RenderContext } from "../../Renderer"; +import { BooleanOption, type Option, getOptionValues } from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import { type PrimitiveStringTypeKind, type TransformedStringTypeKind } from "../../Type"; +import { type StringTypeMapping } from "../../TypeBuilder"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; + +import { TypeScriptZodRenderer } from "./TypeScriptZodRenderer"; + +export const typeScriptZodOptions = { + justSchema: new BooleanOption("just-schema", "Schema only", false) +}; + +export class TypeScriptZodTargetLanguage extends TargetLanguage { + protected getOptions(): Array> { + return []; + } + + public constructor( + displayName: string = "TypeScript Zod", + names: string[] = ["typescript-zod"], + extension: string = "ts" + ) { + super(displayName, names, extension); + } + + public get stringTypeMapping(): StringTypeMapping { + const mapping: Map = new Map(); + const dateTimeType = "date-time"; + mapping.set("date-time", dateTimeType); + return mapping; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): TypeScriptZodRenderer { + return new TypeScriptZodRenderer( + this, + renderContext, + getOptionValues(typeScriptZodOptions, untypedOptionValues) + ); + } +} diff --git a/packages/quicktype-core/src/language/index.ts b/packages/quicktype-core/src/language/index.ts new file mode 100644 index 000000000..024a52494 --- /dev/null +++ b/packages/quicktype-core/src/language/index.ts @@ -0,0 +1,26 @@ +export * from "./CJSON"; +export * from "./CPlusPlus"; +export * from "./Crystal"; +export * from "./CSharp"; +export * from "./Dart"; +export * from "./Elixir"; +export * from "./Elm"; +export * from "./Golang"; +export * from "./Haskell"; +export * from "./Java"; +export * from "./JavaScript"; +export * from "./JavaScriptPropTypes"; +export * from "./JSONSchema"; +export * from "./Kotlin"; +export * from "./Objective-C"; +export * from "./Php"; +export * from "./Pike"; +export * from "./Python"; +export * from "./Ruby"; +export * from "./Rust"; +export * from "./Scala3"; +export * from "./Smithy4s"; +export * from "./Swift"; +export * from "./TypeScriptFlow"; +export * from "./TypeScriptEffectSchema"; +export * from "./TypeScriptZod"; diff --git a/test/languages.ts b/test/languages.ts index 51f76bb4a..f1890a7d5 100644 --- a/test/languages.ts +++ b/test/languages.ts @@ -70,7 +70,7 @@ export const CSharpLanguage: Language = { { "number-type": "decimal" }, { "any-type": "dynamic" } ], - sourceFiles: ["src/language/CSharp.ts"] + sourceFiles: ["src/language/CSharp/index.ts"] }; export const CSharpLanguageSystemTextJson: Language = { @@ -102,7 +102,7 @@ export const CSharpLanguageSystemTextJson: Language = { { "number-type": "decimal" }, { "any-type": "dynamic" } ], - sourceFiles: ["src/language/CSharp.ts"] + sourceFiles: ["src/language/CSharp/index.ts"] }; export const JavaLanguage: Language = { @@ -125,7 +125,7 @@ export const JavaLanguage: Language = { skipSchema: ["keyword-unions.schema"], // generates classes with names that are case-insensitively equal rendererOptions: {}, quickTestRendererOptions: [{ "array-type": "list" }], - sourceFiles: ["src/language/Java.ts"] + sourceFiles: ["src/language/Java/index.ts"] }; export const JavaLanguageWithLegacyDateTime: Language = { @@ -182,7 +182,7 @@ export const PythonLanguage: Language = { ], rendererOptions: {}, quickTestRendererOptions: [{ "python-version": "3.5" }], - sourceFiles: ["src/language/Python.ts"] + sourceFiles: ["src/language/Python/index.ts"] }; export const RustLanguage: Language = { @@ -224,7 +224,7 @@ export const RustLanguage: Language = { { visibility: "private" }, { visibility: "public" } ], - sourceFiles: ["src/language/Rust.ts"] + sourceFiles: ["src/language/Rust/index.ts"] }; export const CrystalLanguage: Language = { @@ -263,7 +263,7 @@ export const CrystalLanguage: Language = { skipMiscJSON: false, rendererOptions: {}, quickTestRendererOptions: [], - sourceFiles: ["src/language/Crystal.ts"] + sourceFiles: ["src/language/Crystal/index.ts"] }; export const RubyLanguage: Language = { @@ -405,7 +405,7 @@ export const GoLanguage: Language = { ], rendererOptions: {}, quickTestRendererOptions: [], - sourceFiles: ["src/language/Golang.ts"] + sourceFiles: ["src/language/Golang/index.ts"] }; export const CJSONLanguage: Language = { @@ -483,7 +483,7 @@ export const CJSONLanguage: Language = { ], rendererOptions: {}, quickTestRendererOptions: [{ "source-style": "single-source" }], - sourceFiles: ["src/language/CJSON.ts"] + sourceFiles: ["src/language/CJSON/index.ts"] }; export const CPlusPlusLanguage: Language = { @@ -542,7 +542,7 @@ export const CPlusPlusLanguage: Language = { { "const-style": "east-const" }, { boost: "false" } ], - sourceFiles: ["src/language/CPlusPlus.ts"] + sourceFiles: ["src/language/CPlusPlus/index.ts"] }; export const ElmLanguage: Language = { @@ -614,7 +614,7 @@ export const ElmLanguage: Language = { ], rendererOptions: {}, quickTestRendererOptions: [{ "array-type": "list" }], - sourceFiles: ["src/language/Elm.ts"] + sourceFiles: ["src/language/Elm/index.ts"] }; export const SwiftLanguage: Language = { @@ -702,7 +702,7 @@ export const SwiftLanguage: Language = { { protocol: "equatable" }, ["simple-object.json", { protocol: "hashable" }] ], - sourceFiles: ["src/language/Swift.ts"] + sourceFiles: ["src/language/Swift/index.ts"] }; export const ObjectiveCLanguage: Language = { @@ -740,7 +740,7 @@ export const ObjectiveCLanguage: Language = { skipSchema: [], rendererOptions: { functions: "true" }, quickTestRendererOptions: [], - sourceFiles: ["src/language/Objective-C.ts"] + sourceFiles: ["src/language/Objective-C/index.ts"] }; export const TypeScriptLanguage: Language = { @@ -788,7 +788,7 @@ export const TypeScriptLanguage: Language = { { converters: "all-objects" }, { readonly: "true" } ], - sourceFiles: ["src/language/TypeScript.ts"] + sourceFiles: ["src/language/TypeScript/index.ts"] }; export const JavaScriptLanguage: Language = { @@ -815,7 +815,7 @@ export const JavaScriptLanguage: Language = { { "runtime-typecheck-ignore-unknown-properties": "true" }, { converters: "top-level" } ], - sourceFiles: ["src/language/JavaScript.ts"] + sourceFiles: ["src/language/JavaScript/index.ts"] }; export const JavaScriptPropTypesLanguage: Language = { @@ -847,7 +847,7 @@ export const JavaScriptPropTypesLanguage: Language = { { "runtime-typecheck-ignore-unknown-properties": "true" }, { converters: "top-level" } ], - sourceFiles: ["src/Language/JavaScriptPropTypes.ts"] + sourceFiles: ["src/language/JavaScriptPropTypes/index.ts"] }; export const FlowLanguage: Language = { @@ -876,7 +876,7 @@ export const FlowLanguage: Language = { { "nice-property-names": "true" }, { "declare-unions": "true" } ], - sourceFiles: ["src/language/Flow.ts"] + sourceFiles: ["src/language/Flow/index.ts"] }; export const Scala3Language: Language = { @@ -956,7 +956,7 @@ I havea no idea how to encode these tests correctly. skipMiscJSON: false, rendererOptions: { framework: "circe" }, quickTestRendererOptions: [], - sourceFiles: ["src/Language/Scala3.ts"] + sourceFiles: ["src/language/Scala3/index.ts"] }; export const Smithy4sLanguage: Language = { @@ -1022,7 +1022,7 @@ I havea no idea how to encode these tests correctly. skipMiscJSON: false, rendererOptions: { framework: "just-types" }, quickTestRendererOptions: [], - sourceFiles: ["src/Language/Smithy4s.ts"] + sourceFiles: ["src/language/Smithy4s/index.ts"] }; export const KotlinLanguage: Language = { @@ -1107,7 +1107,7 @@ export const KotlinLanguage: Language = { skipMiscJSON: false, rendererOptions: {}, quickTestRendererOptions: [], - sourceFiles: ["src/Language/Kotlin.ts"] + sourceFiles: ["src/language/Kotlin/index.ts"] }; export const KotlinJacksonLanguage: Language = { @@ -1191,7 +1191,7 @@ export const KotlinJacksonLanguage: Language = { skipMiscJSON: false, rendererOptions: { framework: "jackson" }, quickTestRendererOptions: [], - sourceFiles: ["src/Language/Kotlin.ts"] + sourceFiles: ["src/language/Kotlin/index.ts"] }; export const DartLanguage: Language = { @@ -1241,7 +1241,7 @@ export const DartLanguage: Language = { skipMiscJSON: true, rendererOptions: {}, quickTestRendererOptions: [], - sourceFiles: ["src/Language/Dart.ts"] + sourceFiles: ["src/language/Dart/index.ts"] }; export const PikeLanguage: Language = { @@ -1294,7 +1294,7 @@ export const PikeLanguage: Language = { ], rendererOptions: {}, quickTestRendererOptions: [], - sourceFiles: ["src/Language/Pike.ts"] + sourceFiles: ["src/language/Pike/index.ts"] }; export const HaskellLanguage: Language = { @@ -1383,7 +1383,7 @@ export const HaskellLanguage: Language = { ], rendererOptions: {}, quickTestRendererOptions: [{ "array-type": "list" }], - sourceFiles: ["src/language/Haskell.ts"] + sourceFiles: ["src/language/Haskell/index.ts"] }; export const PHPLanguage: Language = { @@ -1401,7 +1401,7 @@ export const PHPLanguage: Language = { skipSchema: [], rendererOptions: {}, quickTestRendererOptions: [], - sourceFiles: ["src/Language/Php.ts"] + sourceFiles: ["src/language/Php/index.ts"] }; export const TypeScriptZodLanguage: Language = { @@ -1519,7 +1519,7 @@ export const TypeScriptZodLanguage: Language = { ], rendererOptions: {}, quickTestRendererOptions: [{ "array-type": "list" }], - sourceFiles: ["src/language/TypeScriptZod.ts"] + sourceFiles: ["src/language/TypeScriptZod/index.ts"] }; export const TypeScriptEffectSchemaLanguage: Language = { @@ -1635,7 +1635,7 @@ export const TypeScriptEffectSchemaLanguage: Language = { ], rendererOptions: {}, quickTestRendererOptions: [{ "array-type": "list" }], - sourceFiles: ["src/language/TypeScriptEffectSchema.ts"] + sourceFiles: ["src/language/TypeScriptEffectSchema/index.ts"] }; export const ElixirLanguage: Language = { @@ -1696,5 +1696,5 @@ export const ElixirLanguage: Language = { ], rendererOptions: {}, quickTestRendererOptions: [], - sourceFiles: ["src/language/Elixir.ts"] + sourceFiles: ["src/language/Elixir/index.ts"] }; From 23e74d3209b01f83f28aedfd43da93a2792e82a0 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Fri, 10 May 2024 08:15:11 -0700 Subject: [PATCH 62/94] fix package-lock --- package-lock.json | 1708 +++++++++++++++++++++++---------------------- 1 file changed, 855 insertions(+), 853 deletions(-) diff --git a/package-lock.json b/package-lock.json index 10734e7b7..1dd564e76 100644 --- a/package-lock.json +++ b/package-lock.json @@ -91,6 +91,7 @@ }, "node_modules/@aashutoshrathi/word-wrap": { "version": "1.2.6", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -109,6 +110,16 @@ "node": ">=6.0.0" } }, + "node_modules/@ampproject/remapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@ardatan/sync-fetch": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/@ardatan/sync-fetch/-/sync-fetch-0.0.1.tgz", @@ -125,6 +136,7 @@ "version": "7.24.2", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "dev": true, "dependencies": { "@babel/highlight": "^7.24.2", "picocolors": "^1.0.0" @@ -248,6 +260,16 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@babel/helper-annotate-as-pure": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", @@ -412,6 +434,7 @@ "version": "7.24.5", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz", "integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==", + "dev": true, "engines": { "node": ">=6.9.0" } @@ -443,6 +466,7 @@ "version": "7.24.5", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.5.tgz", "integrity": "sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==", + "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.24.5", "chalk": "^2.4.2", @@ -457,6 +481,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -549,6 +574,7 @@ "version": "7.24.5", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.5.tgz", "integrity": "sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==", + "dev": true, "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -560,6 +586,7 @@ "version": "7.24.5", "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.24.5.tgz", "integrity": "sha512-GWO0mgzNMLWaSYM4z4NVIuY0Cd1fl8cPnuetuddu5w/qGuvt5Y7oUi/kvvQGK9xgOkFJDQX2heIvTRn/OQ1XTg==", + "dev": true, "dependencies": { "core-js-pure": "^3.30.2", "regenerator-runtime": "^0.14.0" @@ -635,11 +662,10 @@ "version": "0.8.1", "license": "MIT", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" + "@jridgewell/trace-mapping": "0.3.9" }, "engines": { - "node": ">=6.0.0" + "node": ">=12" } }, "node_modules/@es-joy/jsdoccomment": { @@ -673,6 +699,7 @@ }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", + "dev": true, "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.3.0" @@ -686,6 +713,7 @@ }, "node_modules/@eslint-community/regexpp": { "version": "4.10.0", + "dev": true, "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -693,6 +721,7 @@ }, "node_modules/@eslint/eslintrc": { "version": "2.1.4", + "dev": true, "license": "MIT", "dependencies": { "ajv": "^6.12.4", @@ -714,6 +743,7 @@ }, "node_modules/@eslint/eslintrc/node_modules/ajv": { "version": "6.12.6", + "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -726,12 +756,19 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "dev": true, + "license": "Python-2.0" + }, "node_modules/@eslint/eslintrc/node_modules/fast-deep-equal": { "version": "3.1.3", + "dev": true, "license": "MIT" }, "node_modules/@eslint/eslintrc/node_modules/js-yaml": { "version": "4.1.0", + "dev": true, "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -742,10 +779,12 @@ }, "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { "version": "0.4.1", + "dev": true, "license": "MIT" }, "node_modules/@eslint/js": { "version": "8.57.0", + "dev": true, "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -753,8 +792,7 @@ }, "node_modules/@glideapps/ts-necessities": { "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@glideapps/ts-necessities/-/ts-necessities-2.2.3.tgz", - "integrity": "sha512-gXi0awOZLHk3TbW55GZLCPP6O+y/b5X1pBXKBVckFONSwF1z1E5ND2BGJsghQFah+pW7pkkyFb2VhUQI2qhL5w==" + "license": "MIT" }, "node_modules/@graphql-eslint/eslint-plugin": { "version": "3.20.1", @@ -844,6 +882,7 @@ }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.14", + "dev": true, "license": "Apache-2.0", "dependencies": { "@humanwhocodes/object-schema": "^2.0.2", @@ -856,6 +895,7 @@ }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=12.22" @@ -867,6 +907,7 @@ }, "node_modules/@humanwhocodes/object-schema": { "version": "2.0.3", + "dev": true, "license": "BSD-3-Clause" }, "node_modules/@isaacs/cliui": { @@ -970,6 +1011,7 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -979,6 +1021,16 @@ "node": ">=6.0.0" } }, + "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.0", "license": "MIT", @@ -990,6 +1042,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, "engines": { "node": ">=6.0.0" } @@ -999,12 +1052,11 @@ "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "version": "0.3.9", + "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" } }, "node_modules/@mark.probst/typescript-json-schema": { @@ -1101,6 +1153,7 @@ }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", + "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", @@ -1112,6 +1165,7 @@ }, "node_modules/@nodelib/fs.stat": { "version": "2.0.5", + "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -1119,6 +1173,7 @@ }, "node_modules/@nodelib/fs.walk": { "version": "1.2.8", + "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", @@ -1198,6 +1253,7 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, "engines": { "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, @@ -1258,9 +1314,8 @@ }, "node_modules/@types/command-line-usage": { "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@types/command-line-usage/-/command-line-usage-5.0.4.tgz", - "integrity": "sha512-BwR5KP3Es/CSht0xqBcUXS3qCAUVXwpRKsV2+arxeb65atasuXG9LykC9Ab10Cw3s2raH92ZqOeILaQbsB2ACg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/glob": { "version": "7.2.0", @@ -1294,12 +1349,13 @@ "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true }, "node_modules/@types/lodash": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.1.tgz", - "integrity": "sha512-X+2qazGS3jxLAIz5JDXDzglAF3KpijdhFxlf/V1+hEsOUc+HnWi81L/uv/EvGuV90WY+7mPGFCUDGfQC3Gj95Q==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.0.tgz", + "integrity": "sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==", "dev": true }, "node_modules/@types/minimatch": { @@ -1314,8 +1370,7 @@ }, "node_modules/@types/node": { "version": "18.19.31", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.31.tgz", - "integrity": "sha512-ArgCD39YpyyrtFKIqMDvjz79jto5fcI/SVUs2HwB+f0dAzq68yqOdyaSivLiLugSziTpNXLQrVb7RZFmdZzbhA==", + "license": "MIT", "dependencies": { "undici-types": "~5.26.4" } @@ -1331,7 +1386,8 @@ "node_modules/@types/normalize-package-data": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==" + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true }, "node_modules/@types/pako": { "version": "1.0.0", @@ -1354,6 +1410,7 @@ }, "node_modules/@types/semver": { "version": "7.5.8", + "dev": true, "license": "MIT" }, "node_modules/@types/shelljs": { @@ -1415,7 +1472,7 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", - "devOptional": true, + "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", "@typescript-eslint/scope-manager": "6.21.0", @@ -1606,6 +1663,7 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "dev": true, "dependencies": { "@typescript-eslint/scope-manager": "6.21.0", "@typescript-eslint/types": "6.21.0", @@ -1633,6 +1691,7 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dev": true, "dependencies": { "@typescript-eslint/types": "6.21.0", "@typescript-eslint/visitor-keys": "6.21.0" @@ -1649,7 +1708,7 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", - "devOptional": true, + "dev": true, "dependencies": { "@typescript-eslint/typescript-estree": "6.21.0", "@typescript-eslint/utils": "6.21.0", @@ -1676,6 +1735,7 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" }, @@ -1688,6 +1748,7 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dev": true, "dependencies": { "@typescript-eslint/types": "6.21.0", "@typescript-eslint/visitor-keys": "6.21.0", @@ -1715,6 +1776,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -1723,6 +1785,7 @@ "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -1737,7 +1800,7 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", - "devOptional": true, + "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", @@ -1762,6 +1825,7 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dev": true, "dependencies": { "@typescript-eslint/types": "6.21.0", "eslint-visitor-keys": "^3.4.1" @@ -1776,6 +1840,7 @@ }, "node_modules/@ungap/structured-clone": { "version": "1.2.0", + "dev": true, "license": "ISC" }, "node_modules/@vscode/test-cli": { @@ -1999,6 +2064,14 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/acorn-walk": { "version": "8.2.0", "license": "MIT", @@ -2045,6 +2118,7 @@ }, "node_modules/ansi-styles": { "version": "3.2.1", + "dev": true, "license": "MIT", "dependencies": { "color-convert": "^1.9.0" @@ -2078,15 +2152,11 @@ "version": "4.1.3", "license": "MIT" }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, "node_modules/aria-query": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, "dependencies": { "dequal": "^2.0.3" } @@ -2102,6 +2172,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, "dependencies": { "call-bind": "^1.0.5", "is-array-buffer": "^3.0.4" @@ -2117,6 +2188,7 @@ "version": "3.1.8", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -2132,10 +2204,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/array.prototype.findlast": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -2155,6 +2237,7 @@ "version": "1.2.5", "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -2174,6 +2257,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -2191,6 +2275,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -2208,6 +2293,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -2219,6 +2305,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz", "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==", + "dev": true, "dependencies": { "call-bind": "^1.0.5", "define-properties": "^1.2.1", @@ -2231,6 +2318,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.5", @@ -2292,7 +2380,8 @@ "node_modules/ast-types-flow": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", - "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==" + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true }, "node_modules/ast-types/node_modules/tslib": { "version": "2.6.2", @@ -2300,8 +2389,14 @@ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "dev": true }, + "node_modules/asynckit": { + "version": "0.4.0", + "dev": true, + "license": "MIT" + }, "node_modules/available-typed-arrays": { "version": "1.0.7", + "dev": true, "license": "MIT", "dependencies": { "possible-typed-array-names": "^1.0.0" @@ -2317,6 +2412,7 @@ "version": "4.7.0", "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz", "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==", + "dev": true, "engines": { "node": ">=4" } @@ -2325,6 +2421,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", + "dev": true, "dependencies": { "dequal": "^2.0.3" } @@ -2465,7 +2562,7 @@ } }, "node_modules/browser-or-node": { - "version": "1.2.1", + "version": "3.0.0", "license": "MIT" }, "node_modules/browser-stdout": { @@ -2603,6 +2700,7 @@ }, "node_modules/call-bind": { "version": "1.0.7", + "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", @@ -2618,6 +2716,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/callsites": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/camelcase": { "version": "6.3.0", "dev": true, @@ -2791,6 +2897,7 @@ "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, "funding": [ { "type": "github", @@ -2805,6 +2912,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", "integrity": "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==", + "dev": true, "dependencies": { "escape-string-regexp": "^1.0.5" }, @@ -2847,6 +2955,7 @@ }, "node_modules/color-convert": { "version": "1.9.3", + "dev": true, "license": "MIT", "dependencies": { "color-name": "1.1.3" @@ -2854,12 +2963,24 @@ }, "node_modules/color-convert/node_modules/color-name": { "version": "1.1.3", + "dev": true, "license": "MIT" }, "node_modules/color-name": { "version": "1.1.4", "license": "MIT" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/command-line-args": { "version": "5.2.1", "license": "MIT", @@ -2950,6 +3071,7 @@ "version": "3.37.0", "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.37.0.tgz", "integrity": "sha512-d3BrpyFr5eD4KcbRvQ3FTUx/KWmaDesr7+a3+1+P46IUnNoEt+oiLijPINZMEon7w9oGkIINWxrBAU9DEciwFQ==", + "dev": true, "hasInstallScript": true, "funding": { "type": "opencollective", @@ -2975,6 +3097,12 @@ "node": ">=14" } }, + "node_modules/cosmiconfig/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, "node_modules/cosmiconfig/node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -3012,6 +3140,7 @@ }, "node_modules/cross-spawn": { "version": "7.0.3", + "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -3051,12 +3180,14 @@ "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==" + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true }, "node_modules/data-view-buffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -3073,6 +3204,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -3089,6 +3221,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -3109,6 +3242,7 @@ }, "node_modules/debug": { "version": "4.3.4", + "dev": true, "license": "MIT", "dependencies": { "ms": "2.1.2" @@ -3195,10 +3329,12 @@ }, "node_modules/deep-is": { "version": "0.1.4", + "dev": true, "license": "MIT" }, "node_modules/define-data-property": { "version": "1.1.4", + "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", @@ -3214,6 +3350,7 @@ }, "node_modules/define-properties": { "version": "1.2.1", + "dev": true, "license": "MIT", "dependencies": { "define-data-property": "^1.0.1", @@ -3227,10 +3364,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, "engines": { "node": ">=6" } @@ -3251,8 +3397,21 @@ "node": ">=0.3.1" } }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/doctrine": { "version": "3.0.0", + "dev": true, "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" @@ -3349,9 +3508,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.4.762", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.762.tgz", - "integrity": "sha512-rrFvGweLxPwwSwJOjIopy3Vr+J3cIPtZzuc74bmlvmBIgQO3VYJDvVrlj94iKZ3ukXUH64Ex31hSfRTLqvjYJQ==", + "version": "1.4.751", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.751.tgz", + "integrity": "sha512-2DEPi++qa89SMGRhufWTiLmzqyuGmNF3SK4+PQetW1JKiZdEpF4XQonJXJCzyuYSA6mauiMhbyVhqYAP45Hvfw==", "dev": true }, "node_modules/emoji-regex": { @@ -3378,6 +3537,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/enhance-visitors/-/enhance-visitors-1.0.0.tgz", "integrity": "sha512-+29eJLiUixTEDRaZ35Vu8jP3gPLNcQQkQkOQjLp2X+6cZGGPDD/uasbFzvLsJKnGZnvmyZ0srxudwOtskHeIDA==", + "dev": true, "dependencies": { "lodash": "^4.13.1" }, @@ -3412,6 +3572,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, "dependencies": { "is-arrayish": "^0.2.1" } @@ -3420,6 +3581,7 @@ "version": "1.23.3", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.1", "arraybuffer.prototype.slice": "^1.0.3", @@ -3477,6 +3639,7 @@ }, "node_modules/es-define-property": { "version": "1.0.0", + "dev": true, "license": "MIT", "dependencies": { "get-intrinsic": "^1.2.4" @@ -3487,6 +3650,7 @@ }, "node_modules/es-errors": { "version": "1.3.0", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -3520,6 +3684,7 @@ "version": "1.0.19", "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -3544,6 +3709,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, "dependencies": { "es-errors": "^1.3.0" }, @@ -3555,6 +3721,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, "dependencies": { "get-intrinsic": "^1.2.4", "has-tostringtag": "^1.0.2", @@ -3568,6 +3735,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, "dependencies": { "hasown": "^2.0.0" } @@ -3576,6 +3744,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, "dependencies": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -3626,15 +3795,15 @@ } }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.1.1", + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/escape-string-regexp": { "version": "1.0.5", + "dev": true, "license": "MIT", "engines": { "node": ">=0.8.0" @@ -3717,6 +3886,7 @@ }, "node_modules/eslint": { "version": "8.57.0", + "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", @@ -3944,7 +4114,7 @@ "version": "6.15.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz", "integrity": "sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw==", - "devOptional": true, + "dev": true, "dependencies": { "get-stdin": "^6.0.0" }, @@ -3959,6 +4129,7 @@ "version": "0.3.9", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", @@ -3969,6 +4140,7 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, "dependencies": { "ms": "^2.1.1" } @@ -4002,6 +4174,7 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "dev": true, "dependencies": { "debug": "^3.2.7" }, @@ -4018,6 +4191,7 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, "dependencies": { "ms": "^2.1.1" } @@ -4044,6 +4218,15 @@ "eslint": ">=8.26.0" } }, + "node_modules/eslint-plugin-ava/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/eslint-plugin-canonical": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/eslint-plugin-canonical/-/eslint-plugin-canonical-3.4.0.tgz", @@ -5012,19 +5195,24 @@ }, "node_modules/eslint-scope": { "version": "7.2.2", + "dev": true, "license": "BSD-2-Clause", "dependencies": { - "lodash.get": "^4.4.2", - "lodash.zip": "^4.2.0" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">=4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-utils": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, "dependencies": { "eslint-visitor-keys": "^2.0.0" }, @@ -5042,22 +5230,25 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, "engines": { "node": ">=10" } }, "node_modules/eslint-visitor-keys": { "version": "3.4.3", + "dev": true, "license": "Apache-2.0", "engines": { - "node": ">=12" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "peerDependencies": { - "eslint": ">=6.0.0" + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/ajv": { "version": "6.12.6", + "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -5065,79 +5256,73 @@ "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" }, - "peerDependencies": { - "eslint": ">=7.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/eslint/node_modules/argparse": { + "version": "2.0.1", + "dev": true, + "license": "Python-2.0" + }, "node_modules/eslint/node_modules/escape-string-regexp": { "version": "4.0.0", + "dev": true, "license": "MIT", "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": ">=10" }, "funding": { - "url": "https://opencollective.com/eslint-plugin-prettier" - }, - "peerDependencies": { - "@types/eslint": ">=8.0.0", - "eslint": ">=8.0.0", - "eslint-config-prettier": "*", - "prettier": ">=3.0.0" - }, - "peerDependenciesMeta": { - "@types/eslint": { - "optional": true - }, - "eslint-config-prettier": { - "optional": true - } + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/eslint/node_modules/fast-deep-equal": { "version": "3.1.3", + "dev": true, "license": "MIT" }, "node_modules/eslint/node_modules/glob-parent": { "version": "6.0.2", + "dev": true, "license": "ISC", "dependencies": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" + "is-glob": "^4.0.3" }, "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" + "node": ">=10.13.0" } }, "node_modules/eslint/node_modules/js-yaml": { "version": "4.1.0", + "dev": true, "license": "MIT", "dependencies": { - "get-stdin": "^6.0.0" + "argparse": "^2.0.1" }, "bin": { - "eslint-config-prettier-check": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=3.14.1" + "js-yaml": "bin/js-yaml.js" } }, "node_modules/eslint/node_modules/json-schema-traverse": { "version": "0.4.1", + "dev": true, "license": "MIT" }, - "node_modules/eslint/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - }, "node_modules/espree": { "version": "9.6.1", + "dev": true, "license": "BSD-2-Clause", "dependencies": { - "ms": "^2.1.1" + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/esprima": { @@ -5150,64 +5335,47 @@ }, "engines": { "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } } }, "node_modules/espurify": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/espurify/-/espurify-2.1.1.tgz", - "integrity": "sha512-zttWvnkhcDyGOhSH4vO2qCBILpdCMv/MX8lp4cqgRkQoDRGK2oZxi2GfWhlP2dIXmk7BaKeOTuzbHhyC68o8XQ==" + "integrity": "sha512-zttWvnkhcDyGOhSH4vO2qCBILpdCMv/MX8lp4cqgRkQoDRGK2oZxi2GfWhlP2dIXmk7BaKeOTuzbHhyC68o8XQ==", + "dev": true }, "node_modules/esquery": { "version": "1.5.0", + "dev": true, "license": "BSD-3-Clause", "dependencies": { - "ms": "^2.1.1" + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" } }, "node_modules/esrecurse": { "version": "4.3.0", + "dev": true, "license": "BSD-2-Clause", "dependencies": { - "enhance-visitors": "^1.0.0", - "eslint-utils": "^3.0.0", - "espree": "^9.0.0", - "espurify": "^2.1.1", - "import-modules": "^2.1.0", - "micro-spelling-correcter": "^1.1.1", - "pkg-dir": "^5.0.0", - "resolve-from": "^5.0.0" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=14.17 <15 || >=16.4" - }, - "peerDependencies": { - "eslint": ">=8.26.0" + "node": ">=4.0" } }, "node_modules/estraverse": { "version": "5.3.0", + "dev": true, "license": "BSD-2-Clause", "engines": { - "node": ">=8" + "node": ">=4.0" } }, "node_modules/esutils": { "version": "2.0.2", - "dependencies": { - "is-get-set-prop": "^1.0.0", - "is-js-type": "^2.0.0", - "is-obj-prop": "^1.0.0", - "is-proto-prop": "^2.0.0", - "lodash": "^4.17.21", - "natural-compare": "^1.4.0", - "ts-unused-exports": "^9.0.3", - "xregexp": "^5.1.1" - }, + "dev": true, "engines": { "node": ">=0.10.0" } @@ -5231,63 +5399,14 @@ "dev": true, "license": "MIT", "dependencies": { - "eslint-utils": "^2.0.0", - "regexpp": "^3.0.0" - }, - "engines": { - "node": ">=8.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=4.19.1" - } - }, - "node_modules/exec-sh/node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/exec-sh/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" + "merge": "^1.1.3" } }, "node_modules/exit": { "version": "0.1.2", "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/exit/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, "engines": { - "node": ">=4" + "node": ">= 0.8.0" } }, "node_modules/expand-template": { @@ -5296,7 +5415,7 @@ "license": "(MIT OR WTFPL)", "optional": true, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/extract-files": { @@ -5316,19 +5435,29 @@ "dev": true, "license": "MIT", "dependencies": { - "escape-string-regexp": "^1.0.5", - "ignore": "^5.0.5" + "acorn": "^7.1.1", + "isarray": "^2.0.1" }, "engines": { - "node": ">=6.5.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" + "node": ">=0.4.0" + } + }, + "node_modules/falafel/node_modules/acorn": { + "version": "7.4.1", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" }, - "peerDependencies": { - "eslint": ">=4.19.1" + "engines": { + "node": ">=0.4.0" } }, + "node_modules/falafel/node_modules/isarray": { + "version": "2.0.5", + "dev": true, + "license": "MIT" + }, "node_modules/fast-decode-uri-component": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", @@ -5348,27 +5477,28 @@ }, "node_modules/fast-glob": { "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, - "license": "MIT", "dependencies": { - "create-eslint-index": "^1.0.0", - "eslint-ast-utils": "^1.0.0", - "lodash": "^4.13.1", - "req-all": "^0.1.0" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" }, "engines": { - "node": ">=4.0.0" - }, - "peerDependencies": { - "eslint": ">=3" + "node": ">=8.6.0" } }, "node_modules/fast-json-stable-stringify": { "version": "2.0.0", + "dev": true, "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", + "dev": true, "license": "MIT" }, "node_modules/fast-printf": { @@ -5403,424 +5533,105 @@ }, "node_modules/fast-url-parser/node_modules/punycode": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.17.1", - "license": "ISC", - "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", - "semver": "^6.3.1", - "tsconfig-paths": "^3.15.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/fastq/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/fastq/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fastq/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "license": "MIT", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-replace": { - "version": "3.0.0", - "license": "MIT", - "dependencies": { - "@typescript-eslint/utils": "^5.10.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0 || ^7.0.0", - "eslint": "^7.0.0 || ^8.0.0", - "jest": "*" - }, - "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - }, - "jest": { - "optional": true - } - } - }, - "node_modules/find-replace/node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/find-replace/node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/find-replace/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/find-replace/node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/find-replace/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/find-replace/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/find-replace/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/find-replace/node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/find-up/node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/find-up/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true }, - "node_modules/flat": { - "version": "5.0.2", + "node_modules/fastq": { + "version": "1.17.1", "dev": true, - "license": "BSD-3-Clause", - "bin": { - "flat": "cli.js" + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" } }, - "node_modules/for-each": { - "version": "0.3.3", + "node_modules/fd-slicer": { + "version": "1.1.0", + "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "pend": "~1.2.0" } }, - "node_modules/for-each/node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "node_modules/file-entry-cache": { + "version": "6.0.1", + "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" + "flat-cache": "^3.0.4" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/for-each/node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node_modules/fill-range": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "engines": { + "node": ">=8" } }, - "node_modules/for-each/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "node_modules/find-replace": { + "version": "3.0.0", + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "array-back": "^3.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=4.0.0" } }, - "node_modules/for-each/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "node_modules/find-up": { + "version": "5.0.0", + "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/for-each/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "node_modules/flat": { + "version": "5.0.2", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "dev": true, + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" }, "engines": { - "node": ">=8.0.0" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/for-each/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "engines": { - "node": ">=4.0" - } + "node_modules/flatted": { + "version": "3.3.1", + "dev": true, + "license": "ISC" }, - "node_modules/for-each/node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "node_modules/for-each": { + "version": "0.3.3", + "dev": true, + "license": "MIT", "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + "is-callable": "^1.1.3" } }, "node_modules/foreground-child": { @@ -5828,15 +5639,14 @@ "dev": true, "license": "ISC", "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=14" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/form-data": { @@ -5844,11 +5654,12 @@ "dev": true, "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" }, "engines": { - "node": ">=8.0.0" + "node": ">= 6" } }, "node_modules/fs-constants": { @@ -5859,11 +5670,11 @@ }, "node_modules/fs.realpath": { "version": "1.0.0", - "dev": true, "license": "ISC" }, "node_modules/function-bind": { "version": "1.1.2", + "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5873,6 +5684,7 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -5888,6 +5700,7 @@ }, "node_modules/functions-have-names": { "version": "1.2.3", + "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5906,14 +5719,12 @@ "version": "2.0.5", "license": "ISC", "engines": { - "node": ">=16" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" + "node": "6.* || 8.* || >= 10.*" } }, "node_modules/get-intrinsic": { "version": "1.2.4", + "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -5923,16 +5734,17 @@ "hasown": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/get-set-props": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-set-props/-/get-set-props-0.1.0.tgz", "integrity": "sha512-7oKuKzAGKj0ag+eWZwcGw2fjiZ78tXnXQoBgY0aU7ZOxTu4bB7hSuQSDgtKy978EDH062P5FmD2EWiDpQS9K9Q==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -5941,6 +5753,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "dev": true, "engines": { "node": ">=4" } @@ -5949,6 +5762,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, "dependencies": { "call-bind": "^1.0.5", "es-errors": "^1.3.0", @@ -5962,9 +5776,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz", - "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==", + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.3.tgz", + "integrity": "sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==", "dev": true, "dependencies": { "resolve-pkg-maps": "^1.0.0" @@ -5983,11 +5797,18 @@ "version": "7.2.3", "license": "ISC", "dependencies": { - "lodash": "^4.17.21", - "vscode-json-languageservice": "^4.1.6" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=12.0" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/glob-parent": { @@ -5995,61 +5816,31 @@ "dev": true, "license": "ISC", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "eslint-compat-utils": "^0.5.0", - "espree": "^9.6.1", - "graphemer": "^1.4.0", - "jsonc-eslint-parser": "^2.0.4", - "natural-compare": "^1.4.0", - "synckit": "^0.6.0" + "is-glob": "^4.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ota-meshi" - }, - "peerDependencies": { - "eslint": ">=6.0.0" + "node": ">= 6" } }, "node_modules/globals": { "version": "13.24.0", + "dev": true, "license": "MIT", "dependencies": { - "@babel/runtime": "^7.23.2", - "aria-query": "^5.3.0", - "array-includes": "^3.1.7", - "array.prototype.flatmap": "^1.3.2", - "ast-types-flow": "^0.0.8", - "axe-core": "=4.7.0", - "axobject-query": "^3.2.1", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "es-iterator-helpers": "^1.0.15", - "hasown": "^2.0.0", - "jsx-ast-utils": "^3.3.5", - "language-tags": "^1.0.9", - "minimatch": "^3.1.2", - "object.entries": "^1.1.7", - "object.fromentries": "^2.0.7" + "type-fest": "^0.20.2" }, "engines": { - "node": ">=4.0" + "node": ">=8" }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globals/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, "node_modules/globalthis": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" @@ -6063,30 +5854,33 @@ }, "node_modules/globby": { "version": "11.1.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, "dependencies": { - "lodash": "^4.17.21" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" }, "engines": { "node": ">=10" }, - "peerDependencies": { - "eslint": ">=2" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/gopd": { "version": "1.0.1", + "dev": true, "license": "MIT", "dependencies": { - "eslint-utils": "^3.0.0", - "globals": "^13.24.0", - "rambda": "^7.4.0" + "get-intrinsic": "^1.1.3" }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "eslint": ">=7.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/graceful-fs": { @@ -6102,16 +5896,14 @@ }, "node_modules/graphemer": { "version": "1.4.0", + "dev": true, "license": "MIT" }, "node_modules/graphql": { "version": "0.11.7", "license": "MIT", "dependencies": { - "requireindex": "~1.1.0" - }, - "engines": { - "node": ">=0.10.0" + "iterall": "1.1.3" } }, "node_modules/graphql-config": { @@ -6427,7 +6219,16 @@ "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=10" + "node": ">=10" + } + }, + "node_modules/graphql-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" } }, "node_modules/graphql-config/node_modules/tslib": { @@ -6489,29 +6290,23 @@ "dev": true, "license": "MIT", "dependencies": { - "eslint-plugin-es": "^3.0.0", - "eslint-utils": "^2.0.0", - "ignore": "^5.1.1", - "minimatch": "^3.0.4", - "resolve": "^1.10.1", - "semver": "^6.1.0" + "function-bind": "^1.1.1" }, "engines": { - "node": ">=8.10.0" - }, - "peerDependencies": { - "eslint": ">=5.16.0" + "node": ">= 0.4.0" } }, "node_modules/has-bigints": { "version": "1.0.2", + "dev": true, "license": "MIT", "funding": { - "url": "https://github.com/sponsors/mysticatea" + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-flag": { "version": "3.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -6519,6 +6314,7 @@ }, "node_modules/has-property-descriptors": { "version": "1.0.2", + "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" @@ -6531,6 +6327,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -6540,114 +6337,32 @@ }, "node_modules/has-symbols": { "version": "1.0.3", + "dev": true, "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 0.4" }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-tostringtag": { "version": "1.0.2", + "dev": true, "license": "MIT", "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlast": "^1.2.4", - "array.prototype.flatmap": "^1.3.2", - "array.prototype.toreversed": "^1.1.2", - "array.prototype.tosorted": "^1.1.3", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.17", - "estraverse": "^5.3.0", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.7", - "object.fromentries": "^2.0.7", - "object.hasown": "^1.1.3", - "object.values": "^1.1.7", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.5", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.10" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/has-tostringtag/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dependencies": { - "esutils": "^2.0.2" + "has-symbols": "^1.0.3" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-tostringtag/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-tostringtag/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/has/node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/has/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/has/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/hasown": { "version": "2.0.2", + "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -6669,10 +6384,10 @@ "dev": true, "license": "ISC", "dependencies": { - "esutils": "^2.0.2" + "lru-cache": "^6.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, "node_modules/html-escaper": { @@ -6683,17 +6398,19 @@ "node_modules/htmlparser2": { "version": "8.0.2", "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], "license": "MIT", "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" } }, "node_modules/http-proxy-agent": { @@ -6714,14 +6431,8 @@ "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "comment-parser": "^1.1.2", - "grapheme-splitter": "^1.0.4", - "jsdoctypeparser": "^9.0.0", - "refa": "^0.11.0", - "regexp-ast-analysis": "^0.6.0", - "scslre": "^0.2.0" + "agent-base": "6", + "debug": "4" }, "engines": { "node": ">= 6" @@ -6733,8 +6444,8 @@ "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, - "peerDependencies": { - "eslint": ">=6.0.0" + "engines": { + "node": ">=0.10.0" } }, "node_modules/ieee754": { @@ -6757,14 +6468,10 @@ }, "node_modules/ignore": { "version": "5.3.1", + "dev": true, "license": "MIT", "engines": { - "node": ">= 16" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^6 || ^7", - "eslint": "^7 || ^8", - "typescript": "^3 || ^4 || ^5" + "node": ">= 4" } }, "node_modules/immediate": { @@ -6774,57 +6481,24 @@ }, "node_modules/import-fresh": { "version": "3.3.0", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", - "@eslint-community/eslint-utils": "^4.4.0", - "ci-info": "^3.8.0", - "clean-regexp": "^1.0.0", - "esquery": "^1.5.0", - "indent-string": "^4.0.0", - "is-builtin-module": "^3.2.1", - "jsesc": "^3.0.2", - "lodash": "^4.17.21", - "pluralize": "^8.0.0", - "read-pkg-up": "^7.0.1", - "regexp-tree": "^0.1.27", - "regjsparser": "^0.10.0", - "semver": "^7.5.4", - "strip-indent": "^3.0.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { - "node": ">=16" + "node": ">=6" }, "funding": { - "url": "https://github.com/sindresorhus/eslint-plugin-unicorn?sponsor=1" - }, - "peerDependencies": { - "eslint": ">=8.44.0" - } - }, - "node_modules/import-fresh/node_modules/jsesc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/import-fresh/node_modules/pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", - "engines": { - "node": ">=4" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/import-modules": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/import-modules/-/import-modules-2.1.0.tgz", "integrity": "sha512-8HEWcnkbGpovH9yInoisxaSoIg9Brbul+Ju3Kqe2UsYDUBJD/iQjSgEj0zPcTDPKfPp2fs5xlv1i+JSye/m1/A==", + "dev": true, "engines": { "node": ">=8" }, @@ -6834,6 +6508,7 @@ }, "node_modules/imurmurhash": { "version": "0.1.4", + "dev": true, "license": "MIT", "engines": { "node": ">=0.8.19" @@ -6843,13 +6518,13 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, "engines": { "node": ">=8" } }, "node_modules/inflight": { "version": "1.0.6", - "dev": true, "license": "ISC", "dependencies": { "once": "^1.3.0", @@ -6870,6 +6545,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.0", @@ -6903,6 +6579,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.2.1" @@ -6917,12 +6594,14 @@ "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true }, "node_modules/is-async-function": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -6935,6 +6614,7 @@ }, "node_modules/is-bigint": { "version": "1.0.4", + "dev": true, "license": "MIT", "dependencies": { "has-bigints": "^1.0.1" @@ -6956,6 +6636,7 @@ }, "node_modules/is-boolean-object": { "version": "1.1.2", + "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.2", @@ -6972,6 +6653,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "dev": true, "dependencies": { "builtin-modules": "^3.3.0" }, @@ -6986,6 +6668,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true, "engines": { "node": ">=6" }, @@ -6995,6 +6678,7 @@ }, "node_modules/is-callable": { "version": "1.2.7", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -7007,6 +6691,7 @@ "version": "2.13.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, "dependencies": { "hasown": "^2.0.0" }, @@ -7018,6 +6703,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, "dependencies": { "is-typed-array": "^1.1.13" }, @@ -7030,6 +6716,7 @@ }, "node_modules/is-date-object": { "version": "1.0.5", + "dev": true, "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" @@ -7043,6 +6730,7 @@ }, "node_modules/is-extglob": { "version": "2.1.1", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -7052,6 +6740,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, "dependencies": { "call-bind": "^1.0.2" }, @@ -7070,6 +6759,7 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -7084,6 +6774,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-get-set-prop/-/is-get-set-prop-1.0.0.tgz", "integrity": "sha512-DvAYZ1ZgGUz4lzxKMPYlt08qAUqyG9ckSg2pIjfvcQ7+pkVNUHk8yVLXOnCLe5WKXhLop8oorWFBJHpwWQpszQ==", + "dev": true, "dependencies": { "get-set-props": "^0.1.0", "lowercase-keys": "^1.0.0" @@ -7091,6 +6782,7 @@ }, "node_modules/is-glob": { "version": "4.0.3", + "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -7103,12 +6795,14 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-js-type/-/is-js-type-2.0.0.tgz", "integrity": "sha512-Aj13l47+uyTjlQNHtXBV8Cji3jb037vxwMWCgopRR8h6xocgBGW3qG8qGlIOEmbXQtkKShKuBM9e8AA1OeQ+xw==", + "dev": true, "dependencies": { "js-types": "^1.0.0" } }, "node_modules/is-map": { "version": "2.0.2", + "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7118,6 +6812,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -7135,6 +6830,7 @@ }, "node_modules/is-number-object": { "version": "1.0.7", + "dev": true, "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" @@ -7150,6 +6846,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-obj-prop/-/is-obj-prop-1.0.0.tgz", "integrity": "sha512-5Idb61slRlJlsAzi0Wsfwbp+zZY+9LXKUAZpvT/1ySw+NxKLRWfa0Bzj+wXI3fX5O9hiddm5c3DAaRSNP/yl2w==", + "dev": true, "dependencies": { "lowercase-keys": "^1.0.0", "obj-props": "^1.0.0" @@ -7157,6 +6854,7 @@ }, "node_modules/is-path-inside": { "version": "3.0.3", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -7174,6 +6872,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-proto-prop/-/is-proto-prop-2.0.0.tgz", "integrity": "sha512-jl3NbQ/fGLv5Jhan4uX+Ge9ohnemqyblWVVCpAvtTQzNFvV2xhJq+esnkIbYQ9F1nITXoLfDDQLp7LBw/zzncg==", + "dev": true, "dependencies": { "lowercase-keys": "^1.0.0", "proto-props": "^2.0.0" @@ -7181,6 +6880,7 @@ }, "node_modules/is-regex": { "version": "1.1.4", + "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.2", @@ -7195,6 +6895,7 @@ }, "node_modules/is-set": { "version": "2.0.2", + "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7204,6 +6905,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, "dependencies": { "call-bind": "^1.0.7" }, @@ -7223,6 +6925,7 @@ }, "node_modules/is-string": { "version": "1.0.7", + "dev": true, "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" @@ -7236,6 +6939,7 @@ }, "node_modules/is-symbol": { "version": "1.0.4", + "dev": true, "license": "MIT", "dependencies": { "has-symbols": "^1.0.2" @@ -7251,6 +6955,7 @@ "version": "1.1.13", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, "dependencies": { "which-typed-array": "^1.1.14" }, @@ -7278,6 +6983,7 @@ }, "node_modules/is-weakmap": { "version": "2.0.1", + "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7287,6 +6993,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.2" }, @@ -7296,6 +7003,7 @@ }, "node_modules/is-weakset": { "version": "2.0.2", + "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.2", @@ -7311,6 +7019,7 @@ }, "node_modules/isexe": { "version": "2.0.0", + "dev": true, "license": "ISC" }, "node_modules/isomorphic-ws": { @@ -7374,10 +7083,15 @@ "node": ">=8" } }, + "node_modules/iterall": { + "version": "1.1.3", + "license": "MIT" + }, "node_modules/iterator.prototype": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "dev": true, "dependencies": { "define-properties": "^1.2.1", "get-intrinsic": "^1.2.1", @@ -7413,18 +7127,20 @@ } }, "node_modules/js-base64": { - "version": "2.4.3", + "version": "3.7.7", "license": "BSD-3-Clause" }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true }, "node_modules/js-types": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/js-types/-/js-types-1.0.0.tgz", "integrity": "sha512-bfwqBW9cC/Lp7xcRpug7YrXm0IVw+T9e3g4mCYnv0Pjr3zIzU9PCQElYU9oSGAWzXlbdl9X5SAMPejO9sxkeUw==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -7462,10 +7178,16 @@ "node": ">=4" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "dev": true, + "license": "MIT" + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true }, "node_modules/json-schema": { "version": "0.4.0", @@ -7480,6 +7202,7 @@ }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", + "dev": true, "license": "MIT" }, "node_modules/json5": { @@ -7514,12 +7237,14 @@ }, "node_modules/jsonc-parser": { "version": "3.2.1", + "dev": true, "license": "MIT" }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", @@ -7566,15 +7291,25 @@ "prebuild-install": "^7.0.1" } }, + "node_modules/keyv": { + "version": "4.5.4", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/language-subtag-registry": { "version": "0.3.22", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", - "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==" + "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==", + "dev": true }, "node_modules/language-tags": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, "dependencies": { "language-subtag-registry": "^0.3.20" }, @@ -7592,6 +7327,7 @@ }, "node_modules/levn": { "version": "0.4.1", + "dev": true, "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", @@ -7612,7 +7348,8 @@ "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true }, "node_modules/linkify-it": { "version": "3.0.3", @@ -7622,6 +7359,20 @@ "uc.micro": "^1.0.1" } }, + "node_modules/locate-path": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/lodash": { "version": "4.17.21", "license": "MIT" @@ -7637,7 +7388,8 @@ "node_modules/lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "dev": true }, "node_modules/lodash.lowercase": { "version": "4.3.0", @@ -7647,12 +7399,14 @@ }, "node_modules/lodash.merge": { "version": "4.6.2", + "dev": true, "license": "MIT" }, "node_modules/lodash.zip": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz", - "integrity": "sha512-C7IOaBBK/0gMORRBd8OETNx3kmOkgIWIPvyDpZSCTwUrpYmgZwJkjZeOD8ww4xbOUOs4/attY+pciKvadNfFbg==" + "integrity": "sha512-C7IOaBBK/0gMORRBd8OETNx3kmOkgIWIPvyDpZSCTwUrpYmgZwJkjZeOD8ww4xbOUOs4/attY+pciKvadNfFbg==", + "dev": true }, "node_modules/log-symbols": { "version": "4.1.0", @@ -7673,6 +7427,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, @@ -7684,12 +7439,14 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/lru-cache": { "version": "6.0.0", + "dev": true, "license": "ISC", "dependencies": { "yallist": "^4.0.0" @@ -7739,6 +7496,11 @@ "markdown-it": "bin/markdown-it.js" } }, + "node_modules/markdown-it/node_modules/argparse": { + "version": "2.0.1", + "dev": true, + "license": "Python-2.0" + }, "node_modules/markdown-it/node_modules/entities": { "version": "2.1.0", "dev": true, @@ -7752,6 +7514,11 @@ "dev": true, "license": "MIT" }, + "node_modules/merge": { + "version": "1.2.1", + "dev": true, + "license": "MIT" + }, "node_modules/merge-source-map": { "version": "1.0.4", "dev": true, @@ -7768,6 +7535,15 @@ "node": ">=0.10.0" } }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, "node_modules/meros": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/meros/-/meros-1.3.0.tgz", @@ -7788,7 +7564,21 @@ "node_modules/micro-spelling-correcter": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/micro-spelling-correcter/-/micro-spelling-correcter-1.1.1.tgz", - "integrity": "sha512-lkJ3Rj/mtjlRcHk6YyCbvZhyWTOzdBvTHsxMmZSk5jxN1YyVSQ+JETAom55mdzfcyDrY/49Z7UCW760BK30crg==" + "integrity": "sha512-lkJ3Rj/mtjlRcHk6YyCbvZhyWTOzdBvTHsxMmZSk5jxN1YyVSQ+JETAom55mdzfcyDrY/49Z7UCW760BK30crg==", + "dev": true + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } }, "node_modules/mime": { "version": "1.6.0", @@ -7801,6 +7591,25 @@ "node": ">=4" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/mimic-response": { "version": "3.1.0", "dev": true, @@ -7817,6 +7626,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, "engines": { "node": ">=4" } @@ -7833,6 +7643,7 @@ }, "node_modules/minimist": { "version": "1.2.7", + "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7886,6 +7697,11 @@ "node": ">= 14.0.0" } }, + "node_modules/mocha/node_modules/argparse": { + "version": "2.0.1", + "dev": true, + "license": "Python-2.0" + }, "node_modules/mocha/node_modules/brace-expansion": { "version": "2.0.1", "dev": true, @@ -8050,6 +7866,7 @@ }, "node_modules/ms": { "version": "2.1.2", + "dev": true, "license": "MIT" }, "node_modules/mute-stream": { @@ -8065,6 +7882,7 @@ }, "node_modules/natural-compare": { "version": "1.4.0", + "dev": true, "license": "MIT" }, "node_modules/natural-compare-lite": { @@ -8127,6 +7945,7 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -8137,12 +7956,14 @@ "node_modules/normalize-package-data/node_modules/hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true }, "node_modules/normalize-package-data/node_modules/semver": { "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, "bin": { "semver": "bin/semver" } @@ -8170,6 +7991,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/obj-props/-/obj-props-1.4.0.tgz", "integrity": "sha512-p7p/7ltzPDiBs6DqxOrIbtRdwxxVRBj5ROukeNb9RgA+fawhrz5n2hpNz8DDmYR//tviJSj7nUnlppGmONkjiQ==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -8178,12 +8000,14 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/object-inspect": { "version": "1.13.1", + "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -8206,6 +8030,7 @@ }, "node_modules/object-keys": { "version": "1.1.1", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -8215,6 +8040,7 @@ "version": "4.1.5", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.5", "define-properties": "^1.2.1", @@ -8232,6 +8058,7 @@ "version": "1.1.8", "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -8245,6 +8072,7 @@ "version": "2.0.8", "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -8262,6 +8090,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -8275,6 +8104,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.4.tgz", "integrity": "sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==", + "dev": true, "dependencies": { "define-properties": "^1.2.1", "es-abstract": "^1.23.2", @@ -8291,6 +8121,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -8305,7 +8136,6 @@ }, "node_modules/once": { "version": "1.4.0", - "dev": true, "license": "ISC", "dependencies": { "wrappy": "1" @@ -8313,6 +8143,7 @@ }, "node_modules/optionator": { "version": "0.9.3", + "dev": true, "license": "MIT", "dependencies": { "@aashutoshrathi/word-wrap": "^1.2.3", @@ -8340,10 +8171,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-locate": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, "engines": { "node": ">=6" } @@ -8352,10 +8198,22 @@ "version": "1.0.6", "license": "(MIT AND Zlib)" }, + "node_modules/parent-module": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -8414,6 +8272,7 @@ }, "node_modules/path-exists": { "version": "4.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -8421,7 +8280,6 @@ }, "node_modules/path-is-absolute": { "version": "1.0.1", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -8429,6 +8287,7 @@ }, "node_modules/path-key": { "version": "3.1.1", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -8436,6 +8295,7 @@ }, "node_modules/path-parse": { "version": "1.0.7", + "dev": true, "license": "MIT" }, "node_modules/path-scurry": { @@ -8463,16 +8323,23 @@ }, "node_modules/path-type": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/pend": { + "version": "1.2.0", + "dev": true, + "license": "MIT" + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true }, "node_modules/picomatch": { "version": "2.3.1", @@ -8489,6 +8356,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "dev": true, "dependencies": { "find-up": "^5.0.0" }, @@ -8505,6 +8373,7 @@ }, "node_modules/possible-typed-array-names": { "version": "1.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -8538,6 +8407,7 @@ }, "node_modules/prelude-ls": { "version": "1.2.1", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.8.0" @@ -8545,8 +8415,8 @@ }, "node_modules/prettier": { "version": "3.2.5", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", - "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", + "dev": true, + "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" }, @@ -8589,6 +8459,7 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -8599,6 +8470,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/proto-props/-/proto-props-2.0.0.tgz", "integrity": "sha512-2yma2tog9VaRZY2mn3Wq51uiSW4NcPYT1cQdBagwyrznrilKSZwIZ0UG3ZPL/mx+axEns0hE35T5ufOYZXEnBQ==", + "dev": true, "engines": { "node": ">=4" } @@ -8615,6 +8487,7 @@ }, "node_modules/punycode": { "version": "2.3.1", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -8660,6 +8533,7 @@ }, "node_modules/queue-microtask": { "version": "1.2.3", + "dev": true, "funding": [ { "type": "github", @@ -8708,7 +8582,8 @@ "node_modules/rambda": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/rambda/-/rambda-7.5.0.tgz", - "integrity": "sha512-y/M9weqWAH4iopRd7EHDEQQvpFPHj1AA3oHozE9tfITHUtTR7Z9PSlIRRG2l1GuW7sefC1cXFfIcF+cgnShdBA==" + "integrity": "sha512-y/M9weqWAH4iopRd7EHDEQQvpFPHj1AA3oHozE9tfITHUtTR7Z9PSlIRRG2l1GuW7sefC1cXFfIcF+cgnShdBA==", + "dev": true }, "node_modules/ramda": { "version": "0.29.1", @@ -8755,7 +8630,8 @@ "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true }, "node_modules/read": { "version": "1.0.7", @@ -8772,6 +8648,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, "dependencies": { "@types/normalize-package-data": "^2.4.0", "normalize-package-data": "^2.5.0", @@ -8786,6 +8663,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, "dependencies": { "find-up": "^4.1.0", "read-pkg": "^5.2.0", @@ -8802,6 +8680,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -8814,6 +8693,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, "dependencies": { "p-locate": "^4.1.0" }, @@ -8825,6 +8705,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, "dependencies": { "p-try": "^2.0.0" }, @@ -8839,6 +8720,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, "dependencies": { "p-limit": "^2.2.0" }, @@ -8850,6 +8732,7 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, "engines": { "node": ">=8" } @@ -8858,6 +8741,7 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, "engines": { "node": ">=8" } @@ -8973,6 +8857,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -8992,7 +8877,8 @@ "node_modules/regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true }, "node_modules/regexp-ast-analysis": { "version": "0.6.0", @@ -9011,12 +8897,14 @@ "version": "0.1.27", "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==", + "dev": true, "bin": { "regexp-tree": "bin/regexp-tree" } }, "node_modules/regexp.prototype.flags": { "version": "1.5.2", + "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.6", @@ -9047,6 +8935,7 @@ "version": "0.10.0", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.10.0.tgz", "integrity": "sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==", + "dev": true, "dependencies": { "jsesc": "~0.5.0" }, @@ -9058,6 +8947,7 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, "bin": { "jsesc": "bin/jsesc" } @@ -9088,6 +8978,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.1.0.tgz", "integrity": "sha512-LBnkqsDE7BZKvqylbmn7lTIVdpx4K/QCduRATpO5R+wtPmky/a8pN1bO2D6wXppn1497AJF9mNjqAXr6bdl9jg==", + "dev": true, "engines": { "node": ">=0.10.5" } @@ -9096,6 +8987,7 @@ "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -9109,11 +9001,11 @@ } }, "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "version": "4.0.0", + "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=4" } }, "node_modules/resolve-pkg-maps": { @@ -9125,6 +9017,29 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, + "node_modules/reusify": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/roarr": { "version": "7.21.1", "resolved": "https://registry.npmjs.org/roarr/-/roarr-7.21.1.tgz", @@ -9141,6 +9056,7 @@ }, "node_modules/run-parallel": { "version": "1.2.0", + "dev": true, "funding": [ { "type": "github", @@ -9164,6 +9080,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "get-intrinsic": "^1.2.4", @@ -9180,7 +9097,8 @@ "node_modules/safe-array-concat/node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true }, "node_modules/safe-buffer": { "version": "5.1.2", @@ -9190,6 +9108,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", @@ -9232,6 +9151,7 @@ }, "node_modules/semver": { "version": "7.6.0", + "dev": true, "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" @@ -9259,6 +9179,7 @@ }, "node_modules/set-function-length": { "version": "1.2.2", + "dev": true, "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", @@ -9274,6 +9195,7 @@ }, "node_modules/set-function-name": { "version": "2.0.2", + "dev": true, "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", @@ -9297,6 +9219,7 @@ }, "node_modules/shebang-command": { "version": "2.0.0", + "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -9307,6 +9230,7 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -9330,6 +9254,7 @@ }, "node_modules/side-channel": { "version": "1.0.6", + "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.7", @@ -9344,6 +9269,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "4.1.0", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/simple-concat": { "version": "1.0.1", "dev": true, @@ -9389,6 +9325,15 @@ "simple-concat": "^1.0.0" } }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/source-map": { "version": "0.6.1", "dev": true, @@ -9401,6 +9346,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -9410,6 +9356,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -9418,7 +9365,8 @@ "node_modules/spdx-exceptions": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==" + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true }, "node_modules/spdx-expression-parse": { "version": "4.0.0", @@ -9433,7 +9381,8 @@ "node_modules/spdx-license-ids": { "version": "3.0.17", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz", - "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==" + "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==", + "dev": true }, "node_modules/static-eval": { "version": "2.1.1", @@ -9626,6 +9575,7 @@ "version": "4.0.11", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -9651,6 +9601,7 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -9668,6 +9619,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -9681,6 +9633,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -9719,6 +9672,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, "engines": { "node": ">=4" } @@ -9727,6 +9681,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, "dependencies": { "min-indent": "^1.0.0" }, @@ -9736,6 +9691,7 @@ }, "node_modules/strip-json-comments": { "version": "3.1.1", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -9746,6 +9702,7 @@ }, "node_modules/supports-color": { "version": "5.5.0", + "dev": true, "license": "MIT", "dependencies": { "has-flag": "^3.0.0" @@ -9758,6 +9715,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -9881,6 +9839,7 @@ }, "node_modules/text-table": { "version": "0.2.0", + "dev": true, "license": "MIT" }, "node_modules/through2": { @@ -9950,6 +9909,7 @@ }, "node_modules/ts-api-utils": { "version": "1.3.0", + "dev": true, "license": "MIT", "engines": { "node": ">=16" @@ -10003,6 +9963,7 @@ "version": "9.0.5", "resolved": "https://registry.npmjs.org/ts-unused-exports/-/ts-unused-exports-9.0.5.tgz", "integrity": "sha512-1XAXaH2i4Al/aZO06pWDn9MUgTN0KQi+fvWudiWfHUTHAav45gzrx7Xq6JAsu6+LoMlVoyGvNvZSPW3KTjDncA==", + "dev": true, "dependencies": { "chalk": "^4.0.0", "tsconfig-paths": "^3.9.0" @@ -10026,6 +9987,7 @@ "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", @@ -10037,6 +9999,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, "dependencies": { "minimist": "^1.2.0" }, @@ -10046,6 +10009,7 @@ }, "node_modules/tslib": { "version": "1.14.1", + "dev": true, "license": "0BSD" }, "node_modules/tunnel": { @@ -10070,6 +10034,7 @@ }, "node_modules/type-check": { "version": "0.4.0", + "dev": true, "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" @@ -10078,10 +10043,22 @@ "node": ">= 0.8.0" } }, + "node_modules/type-fest": { + "version": "0.20.2", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typed-array-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -10095,6 +10072,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", @@ -10113,6 +10091,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", @@ -10132,6 +10111,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", @@ -10189,6 +10169,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "has-bigints": "^1.0.2", @@ -10206,8 +10187,7 @@ }, "node_modules/undici-types": { "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "license": "MIT" }, "node_modules/unicode-properties": { "version": "1.4.1", @@ -10268,9 +10248,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.15.tgz", - "integrity": "sha512-K9HWH62x3/EalU1U6sjSZiylm9C8tgq2mSvshZpqc7QE69RaA2qjhkW2HlNA0tFpEbtyFz7HTqbSdN4MSwUodA==", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", "dev": true, "funding": [ { @@ -10287,7 +10267,7 @@ } ], "dependencies": { - "escalade": "^3.1.2", + "escalade": "^3.1.1", "picocolors": "^1.0.0" }, "bin": { @@ -10299,6 +10279,7 @@ }, "node_modules/uri-js": { "version": "4.4.1", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" @@ -10340,10 +10321,20 @@ "node": ">=10.12.0" } }, + "node_modules/v8-to-istanbul/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" @@ -10353,6 +10344,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -10376,6 +10368,7 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-4.2.1.tgz", "integrity": "sha512-xGmv9QIWs2H8obGbWg+sIPI/3/pFgj/5OWBhNzs00BkYQ9UaB2F6JJaGB/2/YOZJ3BvLXQTC4Q7muqU25QgAhA==", + "dev": true, "dependencies": { "jsonc-parser": "^3.0.0", "vscode-languageserver-textdocument": "^1.0.3", @@ -10387,22 +10380,26 @@ "node_modules/vscode-languageserver-textdocument": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz", - "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==" + "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==", + "dev": true }, "node_modules/vscode-languageserver-types": { "version": "3.17.5", "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", - "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "dev": true }, "node_modules/vscode-nls": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-5.2.0.tgz", - "integrity": "sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==" + "integrity": "sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==", + "dev": true }, "node_modules/vscode-uri": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", - "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==" + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "dev": true }, "node_modules/watch": { "version": "1.0.2", @@ -10465,6 +10462,7 @@ }, "node_modules/which": { "version": "2.0.2", + "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -10478,6 +10476,7 @@ }, "node_modules/which-boxed-primitive": { "version": "1.0.2", + "dev": true, "license": "MIT", "dependencies": { "is-bigint": "^1.0.1", @@ -10494,6 +10493,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "dev": true, "dependencies": { "function.prototype.name": "^1.1.5", "has-tostringtag": "^1.0.0", @@ -10518,10 +10518,12 @@ "node_modules/which-builtin-type/node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true }, "node_modules/which-collection": { "version": "1.0.1", + "dev": true, "license": "MIT", "dependencies": { "is-map": "^2.0.1", @@ -10535,6 +10537,7 @@ }, "node_modules/which-typed-array": { "version": "1.1.15", + "dev": true, "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", @@ -10656,7 +10659,6 @@ }, "node_modules/wrappy": { "version": "1.0.2", - "dev": true, "license": "ISC" }, "node_modules/ws": { @@ -10705,6 +10707,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-5.1.1.tgz", "integrity": "sha512-fKXeVorD+CzWvFs7VBuKTYIW63YD1e1osxwQ8caZ6o1jg6pDAbABDG54LCIq0j5cy7PjRvGIq6sef9DYPXpncg==", + "dev": true, "dependencies": { "@babel/runtime-corejs3": "^7.16.5" } @@ -10726,6 +10729,7 @@ }, "node_modules/yallist": { "version": "4.0.0", + "dev": true, "license": "ISC" }, "node_modules/yaml": { @@ -10859,16 +10863,6 @@ "typescript": "4.9.5" } }, - "packages/quicktype-core/node_modules/browser-or-node": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-3.0.0.tgz", - "integrity": "sha512-iczIdVJzGEYhP5DqQxYM9Hh7Ztpqqi+CXZpSmX8ALFs9ecXkQIeqRyM6TfxEfMVpwhl3dSuDvxdzzo9sUOIVBQ==" - }, - "packages/quicktype-core/node_modules/js-base64": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.7.tgz", - "integrity": "sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==" - }, "packages/quicktype-core/node_modules/pluralize": { "version": "8.0.0", "license": "MIT", @@ -10906,6 +10900,10 @@ "version": "2.1.2", "license": "MIT" }, + "packages/quicktype-typescript-input/node_modules/browser-or-node": { + "version": "1.3.0", + "license": "MIT" + }, "packages/quicktype-typescript-input/node_modules/isomorphic-fetch": { "version": "2.2.1", "license": "MIT", @@ -10914,6 +10912,10 @@ "whatwg-fetch": ">=0.10.0" } }, + "packages/quicktype-typescript-input/node_modules/js-base64": { + "version": "2.6.4", + "license": "BSD-3-Clause" + }, "packages/quicktype-typescript-input/node_modules/node-fetch": { "version": "1.7.3", "license": "MIT", From 811ac4a729e2a01eba463c2f559902c454ab1267 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Fri, 10 May 2024 08:19:41 -0700 Subject: [PATCH 63/94] lint fixed --- packages/quicktype-core/src/Run.ts | 27 +++++++++--------- packages/quicktype-core/src/input/Inputs.ts | 3 +- packages/quicktype-core/src/language/All.ts | 2 +- .../src/language/CJSON/language.ts | 4 +-- .../src/language/CPlusPlus/language.ts | 2 +- .../src/language/CSharp/language.ts | 2 +- .../src/language/Crystal/language.ts | 2 +- .../src/language/Dart/language.ts | 2 +- .../src/language/Elixir/language.ts | 2 +- .../src/language/Elm/language.ts | 2 +- .../src/language/Golang/language.ts | 2 +- .../src/language/Haskell/language.ts | 2 +- .../src/language/JSONSchema/language.ts | 4 +-- .../src/language/Java/language.ts | 2 +- .../src/language/JavaScript/language.ts | 2 +- .../language/JavaScriptPropTypes/language.ts | 2 +- .../src/language/Kotlin/language.ts | 13 +++++---- .../src/language/Objective-C/language.ts | 3 +- .../src/language/Php/language.ts | 2 +- .../src/language/Pike/language.ts | 12 ++++---- .../src/language/Python/language.ts | 2 +- .../src/language/Ruby/language.ts | 2 +- .../src/language/Rust/language.ts | 2 +- .../src/language/Scala3/language.ts | 2 +- .../src/language/Smithy4s/language.ts | 2 +- .../TypeScriptEffectSchema/language.ts | 2 +- .../src/language/TypeScriptFlow/language.ts | 28 +++++++++---------- packages/quicktype-core/src/types.ts | 3 +- packages/quicktype-vscode/src/extension.ts | 2 +- src/index.ts | 3 +- 30 files changed, 72 insertions(+), 68 deletions(-) diff --git a/packages/quicktype-core/src/Run.ts b/packages/quicktype-core/src/Run.ts index bc9244757..f4f8770d4 100644 --- a/packages/quicktype-core/src/Run.ts +++ b/packages/quicktype-core/src/Run.ts @@ -15,13 +15,12 @@ import { replaceObjectType } from "./rewrites/ReplaceObjectType"; import { resolveIntersections } from "./rewrites/ResolveIntersections"; import { type Annotation, type Location, type SerializedRenderResult, type Span } from "./Source"; import { type Comment } from "./support/Comments"; -import type { LanguageName } from "./types"; import { assert } from "./support/Support"; import { type MultiFileRenderResult, type TargetLanguage } from "./TargetLanguage"; import { type TransformedStringTypeKind } from "./Type"; import { type StringTypeMapping, TypeBuilder } from "./TypeBuilder"; import { type TypeGraph, noneToAny, optionalToNullable, removeIndirectionIntersections } from "./TypeGraph"; -import { type FixMeOptionsType } from "./types"; +import { type FixMeOptionsType, type LanguageName } from "./types"; export function getTargetLanguage(nameOrInstance: LanguageName | TargetLanguage): TargetLanguage { if (typeof nameOrInstance === "object") { @@ -123,19 +122,11 @@ export type InferenceFlags = { [F in InferenceFlagName]: boolean }; * The options type for the main quicktype entry points, * `quicktypeMultiFile` and `quicktype`. */ -export type NonInferenceOptions = { - /** - * The target language for which to produce code. This can be either an instance of `TargetLanguage`, - * or a string specifying one of the names for quicktype's built-in target languages. For example, - * both `cs` and `csharp` will generate C#. - */ - lang: LanguageName | TargetLanguage; - /** The input data from which to produce types */ - inputData: InputData; - /** Put class properties in alphabetical order, instead of in the order found in the JSON */ - alphabetizeProperties: boolean; +export interface NonInferenceOptions { /** Make all class property optional */ allPropertiesOptional: boolean; + /** Put class properties in alphabetical order, instead of in the order found in the JSON */ + alphabetizeProperties: boolean; /** Check that we're propagating all type attributes (unless we actually can't) */ checkProvenance: boolean; /** @@ -163,6 +154,14 @@ export type NonInferenceOptions = { fixedTopLevels: boolean; /** String to use for one indentation level. If not given, use the target language's default. */ indentation: string | undefined; + /** The input data from which to produce types */ + inputData: InputData; + /** + * The target language for which to produce code. This can be either an instance of `TargetLanguage`, + * or a string specifying one of the names for quicktype's built-in target languages. For example, + * both `cs` and `csharp` will generate C#. + */ + lang: LanguageName | TargetLanguage; /** If given, output these comments at the beginning of the main output file */ leadingComments?: Comment[]; /** Don't render output. This is mainly useful for benchmarking. */ @@ -173,7 +172,7 @@ export type NonInferenceOptions = { outputFilename: string; /** Options for the target language's renderer */ rendererOptions: RendererOptions; -}; +} export type Options = NonInferenceOptions & InferenceFlags; diff --git a/packages/quicktype-core/src/input/Inputs.ts b/packages/quicktype-core/src/input/Inputs.ts index 9ddd69fb2..17ad239b2 100644 --- a/packages/quicktype-core/src/input/Inputs.ts +++ b/packages/quicktype-core/src/input/Inputs.ts @@ -9,10 +9,11 @@ import { type RunContext } from "../Run"; import { defined, errorMessage, panic } from "../support/Support"; import { type TargetLanguage } from "../TargetLanguage"; import { type TypeBuilder } from "../TypeBuilder"; +import { type LanguageName } from "../types"; import { type CompressedJSON, CompressedJSONFromString, type Value } from "./CompressedJSON"; import { TypeInference } from "./Inference"; -import { LanguageName } from "../types"; + export interface Input { addSource: (source: T) => Promise; diff --git a/packages/quicktype-core/src/language/All.ts b/packages/quicktype-core/src/language/All.ts index 133da4ec2..086740759 100644 --- a/packages/quicktype-core/src/language/All.ts +++ b/packages/quicktype-core/src/language/All.ts @@ -1,4 +1,5 @@ import { type TargetLanguage } from "../TargetLanguage"; +import { type LanguageDisplayName, type LanguageName, type LanguageNameMap } from "../types"; import { CJSONTargetLanguage } from "./CJSON"; import { CPlusPlusTargetLanguage } from "./CPlusPlus"; @@ -28,7 +29,6 @@ import { TypeScriptEffectSchemaTargetLanguage } from "./TypeScriptEffectSchema"; import { FlowTargetLanguage, TypeScriptTargetLanguage } from "./TypeScriptFlow"; import { TypeScriptZodTargetLanguage } from "./TypeScriptZod"; -import type { LanguageDisplayName, LanguageName, LanguageNameMap } from "../types"; export const all = [ new CJSONTargetLanguage(), diff --git a/packages/quicktype-core/src/language/CJSON/language.ts b/packages/quicktype-core/src/language/CJSON/language.ts index 067bc4b8b..6ef2c6607 100644 --- a/packages/quicktype-core/src/language/CJSON/language.ts +++ b/packages/quicktype-core/src/language/CJSON/language.ts @@ -21,11 +21,11 @@ * See test/languages.ts for the test cases which are not implmented/checked. */ -import { type FixMeOptionsType, type FixMeOptionsAnyType } from "../../types"; import { type RenderContext } from "../../Renderer"; import { EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; import { type NamingStyle } from "../../support/Strings"; import { TargetLanguage } from "../../TargetLanguage"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; import { CJSONRenderer } from "./CJSONRenderer"; @@ -121,7 +121,7 @@ export const cJSONLanguageConfig = { } as const; export class CJSONTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super(cJSONLanguageConfig); } diff --git a/packages/quicktype-core/src/language/CPlusPlus/language.ts b/packages/quicktype-core/src/language/CPlusPlus/language.ts index 4532fcc58..248188d3f 100644 --- a/packages/quicktype-core/src/language/CPlusPlus/language.ts +++ b/packages/quicktype-core/src/language/CPlusPlus/language.ts @@ -99,7 +99,7 @@ export const cPlusPlusLanguageConfig = { } as const; export class CPlusPlusTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super(cPlusPlusLanguageConfig); } diff --git a/packages/quicktype-core/src/language/CSharp/language.ts b/packages/quicktype-core/src/language/CSharp/language.ts index 327a9e9af..4e9007b44 100644 --- a/packages/quicktype-core/src/language/CSharp/language.ts +++ b/packages/quicktype-core/src/language/CSharp/language.ts @@ -108,7 +108,7 @@ export const systemTextJsonCSharpOptions = Object.assign({}, cSharpOptions, {}); export const cSharpLanguageConfig = { displayName: "C#", names: ["cs", "csharp"], extension: "cs" } as const; export class CSharpTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super(cSharpLanguageConfig); } diff --git a/packages/quicktype-core/src/language/Crystal/language.ts b/packages/quicktype-core/src/language/Crystal/language.ts index 39e0a748e..98eb00994 100644 --- a/packages/quicktype-core/src/language/Crystal/language.ts +++ b/packages/quicktype-core/src/language/Crystal/language.ts @@ -12,7 +12,7 @@ export const crystalLanguageConfig = { } as const; export class CrystalTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super(crystalLanguageConfig); } diff --git a/packages/quicktype-core/src/language/Dart/language.ts b/packages/quicktype-core/src/language/Dart/language.ts index 2089cbdc9..9c6206020 100644 --- a/packages/quicktype-core/src/language/Dart/language.ts +++ b/packages/quicktype-core/src/language/Dart/language.ts @@ -34,7 +34,7 @@ export const dartOptions = { export const dartLanguageConfig = { displayName: "Dart", names: ["dart"], extension: "dart" } as const; export class DartTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super(dartLanguageConfig); } diff --git a/packages/quicktype-core/src/language/Elixir/language.ts b/packages/quicktype-core/src/language/Elixir/language.ts index 82f1d1c25..dad552a2a 100644 --- a/packages/quicktype-core/src/language/Elixir/language.ts +++ b/packages/quicktype-core/src/language/Elixir/language.ts @@ -17,7 +17,7 @@ export const elixirLanguageConfig = { } as const; export class ElixirTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super(elixirLanguageConfig); } diff --git a/packages/quicktype-core/src/language/Elm/language.ts b/packages/quicktype-core/src/language/Elm/language.ts index f26d29ed5..79e63f863 100644 --- a/packages/quicktype-core/src/language/Elm/language.ts +++ b/packages/quicktype-core/src/language/Elm/language.ts @@ -22,7 +22,7 @@ export const elmLanguageConfig = { } as const; export class ElmTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super(elmLanguageConfig); } diff --git a/packages/quicktype-core/src/language/Golang/language.ts b/packages/quicktype-core/src/language/Golang/language.ts index 6af82ac1b..6715d4e2e 100644 --- a/packages/quicktype-core/src/language/Golang/language.ts +++ b/packages/quicktype-core/src/language/Golang/language.ts @@ -27,7 +27,7 @@ const golangLanguageConfig = { } as const; export class GoTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super(golangLanguageConfig); } diff --git a/packages/quicktype-core/src/language/Haskell/language.ts b/packages/quicktype-core/src/language/Haskell/language.ts index 2a35fa025..2884bcb8d 100644 --- a/packages/quicktype-core/src/language/Haskell/language.ts +++ b/packages/quicktype-core/src/language/Haskell/language.ts @@ -21,7 +21,7 @@ export const haskellLanguageConfig = { } as const; export class HaskellTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super(haskellLanguageConfig); } diff --git a/packages/quicktype-core/src/language/JSONSchema/language.ts b/packages/quicktype-core/src/language/JSONSchema/language.ts index c0dc7ffce..e872eb758 100644 --- a/packages/quicktype-core/src/language/JSONSchema/language.ts +++ b/packages/quicktype-core/src/language/JSONSchema/language.ts @@ -2,7 +2,7 @@ import { type RenderContext } from "../../Renderer"; import { type Option } from "../../RendererOptions"; import { TargetLanguage } from "../../TargetLanguage"; import { type StringTypeMapping, getNoStringTypeMapping } from "../../TypeBuilder"; -import { type FixMeOptionsType, type FixMeOptionsAnyType } from "../../types"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; import { JSONSchemaRenderer } from "./JSONSchemaRenderer"; @@ -13,7 +13,7 @@ export const JSONSchemaLanguageConfig = { } as const; export class JSONSchemaTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super(JSONSchemaLanguageConfig); } diff --git a/packages/quicktype-core/src/language/Java/language.ts b/packages/quicktype-core/src/language/Java/language.ts index 060de2c70..6dc1e9ee0 100644 --- a/packages/quicktype-core/src/language/Java/language.ts +++ b/packages/quicktype-core/src/language/Java/language.ts @@ -43,7 +43,7 @@ export const javaLanguageConfig = { } as const; export class JavaTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super(javaLanguageConfig); } diff --git a/packages/quicktype-core/src/language/JavaScript/language.ts b/packages/quicktype-core/src/language/JavaScript/language.ts index 0fea584f8..8eb0862e7 100644 --- a/packages/quicktype-core/src/language/JavaScript/language.ts +++ b/packages/quicktype-core/src/language/JavaScript/language.ts @@ -38,7 +38,7 @@ export const javaScriptLanguageConfig = { } as const; export class JavaScriptTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super(javaScriptLanguageConfig); } diff --git a/packages/quicktype-core/src/language/JavaScriptPropTypes/language.ts b/packages/quicktype-core/src/language/JavaScriptPropTypes/language.ts index 6df5625c1..39a388de7 100644 --- a/packages/quicktype-core/src/language/JavaScriptPropTypes/language.ts +++ b/packages/quicktype-core/src/language/JavaScriptPropTypes/language.ts @@ -28,7 +28,7 @@ export const javaScriptPropTypesLanguageConfig = { } as const; export class JavaScriptPropTypesTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super(javaScriptPropTypesLanguageConfig); } diff --git a/packages/quicktype-core/src/language/Kotlin/language.ts b/packages/quicktype-core/src/language/Kotlin/language.ts index 4071c3eef..55254f807 100644 --- a/packages/quicktype-core/src/language/Kotlin/language.ts +++ b/packages/quicktype-core/src/language/Kotlin/language.ts @@ -35,15 +35,16 @@ export const kotlinOptions = { }; export const kotlinLanguageConfig = { - displayName: "Kotlin", - names: ["kotlin"], - extension: "kt" + displayName: "Kotlin", + names: ["kotlin"], + extension: "kt" } as const; export class KotlinTargetLanguage extends TargetLanguage { - constructor() { - super(kotlinLanguageConfig); - } + public constructor() { + super(kotlinLanguageConfig); + } + protected getOptions(): Array> { return [kotlinOptions.framework, kotlinOptions.acronymStyle, kotlinOptions.packageName]; } diff --git a/packages/quicktype-core/src/language/Objective-C/language.ts b/packages/quicktype-core/src/language/Objective-C/language.ts index 28c3dbfe4..0aa44ab24 100644 --- a/packages/quicktype-core/src/language/Objective-C/language.ts +++ b/packages/quicktype-core/src/language/Objective-C/language.ts @@ -31,9 +31,10 @@ export const objectiveCLanguageConfig = { } as const; export class ObjectiveCTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super(objectiveCLanguageConfig); } + protected getOptions(): Array> { return [ objectiveCOptions.justTypes, diff --git a/packages/quicktype-core/src/language/Php/language.ts b/packages/quicktype-core/src/language/Php/language.ts index 6d6f13283..a3212dea0 100644 --- a/packages/quicktype-core/src/language/Php/language.ts +++ b/packages/quicktype-core/src/language/Php/language.ts @@ -25,7 +25,7 @@ export const phpLanguageConfig = { } as const; export class PhpTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super(phpLanguageConfig); } diff --git a/packages/quicktype-core/src/language/Pike/language.ts b/packages/quicktype-core/src/language/Pike/language.ts index 8822ce894..43a6db737 100644 --- a/packages/quicktype-core/src/language/Pike/language.ts +++ b/packages/quicktype-core/src/language/Pike/language.ts @@ -8,15 +8,15 @@ import { PikeRenderer } from "./PikeRenderer"; export const pikeOptions = {}; export const pikeLanguageConfig = { - displayName: "Pike", - names: ["pike", "pikelang"], - extension: "pmod" + displayName: "Pike", + names: ["pike", "pikelang"], + extension: "pmod" } as const; export class PikeTargetLanguage extends TargetLanguage { - constructor() { - super(pikeLanguageConfig); - } + public constructor() { + super(pikeLanguageConfig); + } protected getOptions(): Array> { return []; diff --git a/packages/quicktype-core/src/language/Python/language.ts b/packages/quicktype-core/src/language/Python/language.ts index 61464febf..0cf7e0f07 100644 --- a/packages/quicktype-core/src/language/Python/language.ts +++ b/packages/quicktype-core/src/language/Python/language.ts @@ -33,7 +33,7 @@ export const pythonOptions = { export const pythonLanguageConfig = { displayName: "Python", names: ["python", "py"], extension: "py" } as const; export class PythonTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super(pythonLanguageConfig); } diff --git a/packages/quicktype-core/src/language/Ruby/language.ts b/packages/quicktype-core/src/language/Ruby/language.ts index 953366cd2..34f9b4747 100644 --- a/packages/quicktype-core/src/language/Ruby/language.ts +++ b/packages/quicktype-core/src/language/Ruby/language.ts @@ -23,7 +23,7 @@ export const rubyLanguageConfig = { } as const; export class RubyTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super(rubyLanguageConfig); } diff --git a/packages/quicktype-core/src/language/Rust/language.ts b/packages/quicktype-core/src/language/Rust/language.ts index 8be961865..855a28f6b 100644 --- a/packages/quicktype-core/src/language/Rust/language.ts +++ b/packages/quicktype-core/src/language/Rust/language.ts @@ -31,7 +31,7 @@ export const rustLanguageConfig = { } as const; export class RustTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super(rustLanguageConfig); } diff --git a/packages/quicktype-core/src/language/Scala3/language.ts b/packages/quicktype-core/src/language/Scala3/language.ts index a040799af..ad8b2f87f 100644 --- a/packages/quicktype-core/src/language/Scala3/language.ts +++ b/packages/quicktype-core/src/language/Scala3/language.ts @@ -36,7 +36,7 @@ export const scala3LanguageConfig = { } as const; export class Scala3TargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super(scala3LanguageConfig); } diff --git a/packages/quicktype-core/src/language/Smithy4s/language.ts b/packages/quicktype-core/src/language/Smithy4s/language.ts index 9f2fbe8ab..c85a80bca 100644 --- a/packages/quicktype-core/src/language/Smithy4s/language.ts +++ b/packages/quicktype-core/src/language/Smithy4s/language.ts @@ -23,7 +23,7 @@ export const smithyLanguageConfig = { } as const; export class SmithyTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super(smithyLanguageConfig); } diff --git a/packages/quicktype-core/src/language/TypeScriptEffectSchema/language.ts b/packages/quicktype-core/src/language/TypeScriptEffectSchema/language.ts index 7507264ad..050b6a005 100644 --- a/packages/quicktype-core/src/language/TypeScriptEffectSchema/language.ts +++ b/packages/quicktype-core/src/language/TypeScriptEffectSchema/language.ts @@ -16,7 +16,7 @@ export const typeScriptEffectSchemaLanguageConfig = { } as const; export class TypeScriptEffectSchemaTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super(typeScriptEffectSchemaLanguageConfig); } diff --git a/packages/quicktype-core/src/language/TypeScriptFlow/language.ts b/packages/quicktype-core/src/language/TypeScriptFlow/language.ts index 84b2a0f41..b97bc4b9f 100644 --- a/packages/quicktype-core/src/language/TypeScriptFlow/language.ts +++ b/packages/quicktype-core/src/language/TypeScriptFlow/language.ts @@ -1,13 +1,13 @@ -import { TargetLanguage } from "../../TargetLanguage"; import { type RenderContext } from "../../Renderer"; import { BooleanOption, type Option, getOptionValues } from "../../RendererOptions"; -import { type FixMeOptionsType } from "../../types"; +import { TargetLanguage } from "../../TargetLanguage"; +import { type PrimitiveStringTypeKind, type TransformedStringTypeKind } from "../../Type"; +import { type StringTypeMapping } from "../../TypeBuilder"; +import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; import { javaScriptOptions } from "../JavaScript"; import { FlowRenderer } from "./FlowRenderer"; import { TypeScriptRenderer } from "./TypeScriptRenderer"; -import { type TransformedStringTypeKind, type PrimitiveStringTypeKind } from "../../Type"; -import { type StringTypeMapping } from "../../TypeBuilder"; export const tsFlowOptions = Object.assign({}, javaScriptOptions, { justTypes: new BooleanOption("just-types", "Interfaces only", false), @@ -30,11 +30,11 @@ export const typeScriptLanguageConfig = { } as const; export class TypeScriptTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super(typeScriptLanguageConfig); } - protected getOptions(): Option[] { + protected getOptions(): Array> { return [ tsFlowOptions.justTypes, tsFlowOptions.nicePropertyNames, @@ -51,7 +51,7 @@ export class TypeScriptTargetLanguage extends TargetLanguage = new Map(); const dateTimeType = "date-time"; mapping.set("date", dateTimeType); @@ -59,11 +59,11 @@ export class TypeScriptTargetLanguage extends TargetLanguage { - constructor() { + public constructor() { super(flowLanguageConfig); } - protected getOptions(): Option[] { + protected getOptions(): Array> { return [ tsFlowOptions.justTypes, tsFlowOptions.nicePropertyNames, @@ -100,7 +100,7 @@ export class FlowTargetLanguage extends TargetLanguage = new Map(); const dateTimeType = "date-time"; mapping.set("date", dateTimeType); @@ -108,11 +108,11 @@ export class FlowTargetLanguage extends TargetLanguage, targetLanguage: TargetLangua if (targetLanguage !== undefined) { language = targetLanguage; } else { - const languageName = opts.lang !== undefined ? opts.lang : inferLang(opts, defaultDefaultTargetLanguageName); + const languageName = opts.lang ?? inferLang(opts, defaultDefaultTargetLanguageName); if (isLanguageName(languageName)) { language = languageNamed(languageName); @@ -906,6 +906,7 @@ export async function makeQuicktypeOptions( if (!isLanguageName(options.lang)) { return messageError("DriverUnknownOutputLanguage", { lang: options.lang }); } + const lang = languageNamed(options.lang, targetLanguages); const quicktypeOptions: Partial = { From 9b8908aa4dbf337b85476e2a10fef976a8048d8f Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sun, 19 May 2024 09:56:46 -0700 Subject: [PATCH 64/94] use LanguageName in cli index --- .../quicktype-core/src/language/Smithy4s/language.ts | 2 +- src/index.ts | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/quicktype-core/src/language/Smithy4s/language.ts b/packages/quicktype-core/src/language/Smithy4s/language.ts index c85a80bca..21c28d796 100644 --- a/packages/quicktype-core/src/language/Smithy4s/language.ts +++ b/packages/quicktype-core/src/language/Smithy4s/language.ts @@ -18,7 +18,7 @@ export const smithyOptions = { export const smithyLanguageConfig = { displayName: "Smithy", - names: ["Smithy"], + names: ["smithy"], extension: "smithy" } as const; diff --git a/src/index.ts b/src/index.ts index 61747d723..eb9f8f0d4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -20,6 +20,7 @@ import { JSONInput, JSONSchemaInput, type JSONSourceData, + type LanguageName, type OptionDefinition, type Options, type RendererOptions, @@ -50,13 +51,14 @@ import { import { GraphQLInput } from "quicktype-graphql-input"; import { schemaForTypeScriptSources } from "quicktype-typescript-input"; -import packageJSON from "../package.json"; - import { CompressedJSONFromStream } from "./CompressedJSONFromStream"; import { introspectServer } from "./GraphQLIntrospection"; import { type GraphQLTypeSource, type JSONTypeSource, type SchemaTypeSource, type TypeSource } from "./TypeSource"; import { urlsFromURLGrammar } from "./URLGrammar"; +// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires +const packageJSON = require("../package.json"); + const wordWrap: (s: string) => string = _wordwrap(90); export interface CLIOptions { @@ -73,7 +75,7 @@ export interface CLIOptions { help: boolean; httpHeader?: string[]; httpMethod?: string; - lang: string; + lang: LanguageName; noRender: boolean; out?: string; @@ -222,7 +224,7 @@ async function samplesFromDirectory(dataDir: string, httpHeaders?: string[]): Pr return sources; } -function inferLang(options: Partial, defaultLanguage: string): string { +function inferLang(options: Partial, defaultLanguage: LanguageName): string | LanguageName { // Output file extension determines the language if language is undefined if (options.out !== undefined) { let extension = path.extname(options.out); @@ -284,7 +286,7 @@ function inferCLIOptions(opts: Partial, targetLanguage: TargetLangua src: opts.src ?? [], srcUrls: opts.srcUrls, srcLang: srcLang, - lang: language.displayName, + lang: language.name as LanguageName, topLevel: opts.topLevel ?? inferTopLevel(opts), noRender: !!opts.noRender, alphabetizeProperties: !!opts.alphabetizeProperties, From 8555b845d7232d42852737cf0cc2a2dcfd5d8f68 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sun, 19 May 2024 14:46:10 -0700 Subject: [PATCH 65/94] fix type errors in test --- packages/quicktype-core/src/language/Smithy4s/language.ts | 2 +- test/fixtures.ts | 4 ++-- test/languages.ts | 4 +++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/quicktype-core/src/language/Smithy4s/language.ts b/packages/quicktype-core/src/language/Smithy4s/language.ts index 21c28d796..888a77e18 100644 --- a/packages/quicktype-core/src/language/Smithy4s/language.ts +++ b/packages/quicktype-core/src/language/Smithy4s/language.ts @@ -18,7 +18,7 @@ export const smithyOptions = { export const smithyLanguageConfig = { displayName: "Smithy", - names: ["smithy"], + names: ["smithy4a"], extension: "smithy" } as const; diff --git a/test/fixtures.ts b/test/fixtures.ts index 1aa5e5c0c..0e948a983 100644 --- a/test/fixtures.ts +++ b/test/fixtures.ts @@ -23,7 +23,7 @@ import { callAndExpectFailure } from "./utils"; import * as languages from "./languages"; -import { RendererOptions } from "quicktype-core"; +import { type LanguageName, RendererOptions } from "quicktype-core"; import { mustNotHappen, defined } from "../packages/quicktype-core/dist/support/Support"; import { DefaultDateTimeRecognizer } from "../packages/quicktype-core/dist/DateTime"; @@ -377,7 +377,7 @@ class JSONToXToYFixture extends JSONFixture { constructor( private readonly _fixturePrefix: string, - languageXName: string, + languageXName: LanguageName, languageXOutputFilename: string, rendererOptions: RendererOptions, skipJSON: string[], diff --git a/test/languages.ts b/test/languages.ts index f1890a7d5..82f3520ec 100644 --- a/test/languages.ts +++ b/test/languages.ts @@ -1,3 +1,5 @@ +import { type LanguageName } from "quicktype-core"; + import * as process from "process"; // @ts-ignore import { RendererOptions } from "../dist/quicktype-core/Run"; @@ -18,7 +20,7 @@ export type LanguageFeature = | "pattern"; export interface Language { - name: string; + name: LanguageName; base: string; setupCommand?: string; compileCommand?: string; From 23c2c5fa3436dcd0e70cd85a4a757825f69bc2e9 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Fri, 31 May 2024 09:56:05 -0700 Subject: [PATCH 66/94] add docs for creating custom languages and renderers --- doc/CustomRenderer.md | 147 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 doc/CustomRenderer.md diff --git a/doc/CustomRenderer.md b/doc/CustomRenderer.md new file mode 100644 index 000000000..0d866508a --- /dev/null +++ b/doc/CustomRenderer.md @@ -0,0 +1,147 @@ +# Extending quicktype functionality with a Custom Renderer + +## quicktype Interface + +To customise your rendering output, you can extend existing quicktype classes and override existing methods to achieve the behaviour you want. + +This process requires 3 main steps: + +1. [Extending a `Renderer` Class](#creating-a-custom-renderer) +2. [Wrapping your `Renderer` in a `TargetLanguage` Class](#creating-a-targetlanguage) +3. [Using your new classes in the `quicktype` function](#using-your-custom-language) +4. [Advanced Usage: Creating an entirely new Language](#creating-a-new-language) + +## Creating a custom `Renderer` + +Adding custom render logic for an existing language often involves extending a Renderer class and simply overriding or amending one of the `emit` methods: + +```ts +// MyCustomRenderer.ts +import { CSharpRenderer } from "quicktype-core"; + +export class MyCustomRenderer extends CSharpRenderer { + // Add your custom logic here, feel free to reference the source code for how existing methods work + // + // ex. + protected superclassForType(t: Type): Sourcelike | undefined { + // if the type is a class, it should extend `GameObject` when rendered in C# + if (t instanceof ClassType) { + return "GameObject"; + } + return undefined; + } + // See: http://blog.quicktype.io/customizing-quicktype/ for more context +} +``` + +## Creating a `TargetLanguage` + +If you just want to change the rendering logic for an existing language, you can just extend an exported Language class (`CSharpTargetLanguage` in this example) and override the `makeRenderer` method: + +```ts +// MyCustomLanguage.ts +import { CSharpTargetLanguage } from "quicktype-core"; + +import { MyCustomRenderer } from "./MyCustomRenderer"; + +export class MyCustomLanguage extends CSharpTargetLanguage { + // `makeRenderer` instantiates the Renderer class for the TargetLanguage + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: Record + ): MyCustomRenderer { + // use your new custom renderer class here + return new MyCustomRenderer(this, renderContext, getOptionValues(cSharpOptions, untypedOptionValues)); + } +} +``` + +## Using your custom Language + +```ts +import { quicktype } from "quicktype-core"; + +import { MyCustomLanguage } from './MyCustomLanguage'; + +const lang = new MyCustomLanguage(); + +const lines = await quicktype({ + lang: lang, // use your new TargetLanguage in the `lang` field here + ... +}); + +console.log(lines); +``` + +## Creating a new Language + +If none of the existing `quicktype` Language classes suit your needs, you can creating your own `TargetLanguge` and `Renderer` classes from scratch. If this satisfies your use cases for a language we don't currently support, please consider opening a PR with your new language and we'd love to take a look. + +If you run into any issues, you can open a GitHub issue and we'll help you take a look. + +### Creating a `TargetLanguage` from scratch + +Instead of just extending an existing language, a new Language requires two additional steps: + +- Defining the language config +- Adding any language-specific options + +```ts +import { TargetLanguage, BooleanOption } from "quicktype-core"; + +// language config +const brandNewLanguageConfig = { + displayName: "Scratch", // these can be the same + names: ["scratch"], // these can be the same + extension: "sb" // the file extension that this language commonly has +} as const; + +// language options +const brandNewLanguageOptions = { + allowFoo: new BooleanOption( + "allow-foo", // option name + "Allows Foo", // description + true // default value + ) + // The default available Option classes are: StringOption, BooleanOption, EnumOption + // Please visit the source code for more examples and usage +}; + +class BrandNewLanguage extends TargetLanguage { + public constructor() { + super(brandNewLanguageConfig); + } + + protected getOptions(): Array> { + return [ + brandNewLanguageOptions.allowFoo // list all options from the options config + ]; + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: Record + ): BrandNewRenderer { + return new BrandNewRenderer(this, renderContext, getOptionValues(brandNewLanguageOptions, untypedOptionValues)); + } +} +``` + +### Creating a `Renderer` from scratch + +Creating a brand new `Renderer` class is very similar to extending an existing class: + +```ts +export class BrandNewRenderer extends ConvenienceRenderer { + public constructor(targetLanguage: TargetLanguage, renderContext: RenderContext) { + super(targetLanguage, renderContext); + } + + // Additional render methods go here + // Please reference existing Renderer classes and open a GitHub issue if you need help +} +``` + +## Links + +Blog post with an older example: http://blog.quicktype.io/customizing-quicktype/ From aef27c291d2de8437a873ad05bcba60213fb871f Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Fri, 31 May 2024 09:59:00 -0700 Subject: [PATCH 67/94] update README --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index b8a93cb39..9d9fcbbf9 100644 --- a/README.md +++ b/README.md @@ -186,6 +186,11 @@ main(); 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. +### Adding Custom logic or Rendering: + +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`.
+Check out [this guide](./doc/CustomRenderer.md) for more info. + ## Contributing `quicktype` is [Open Source](LICENSE) and we love contributors! In fact, we have a [list of issues](https://github.com/quicktype/quicktype/issues?utf8=✓&q=is%3Aissue+is%3Aopen+label%3Ahelp-wanted) that are low-priority for us, but for which we'd happily accept contributions. Support for new target languages is also strongly desired. If you'd like to contribute, need help with anything at all, or would just like to talk things over, come [join us on Slack](http://slack.quicktype.io/). From 898d5f2b5e6005bae029858eb4d77fdac332d661 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 1 Jun 2024 16:54:30 -0700 Subject: [PATCH 68/94] working tuple type generics --- .../quicktype-core/src/RendererOptions.ts | 34 +++++++++---------- packages/quicktype-core/src/TargetLanguage.ts | 2 +- src/index.ts | 7 ++-- 3 files changed, 20 insertions(+), 23 deletions(-) diff --git a/packages/quicktype-core/src/RendererOptions.ts b/packages/quicktype-core/src/RendererOptions.ts index 6c3a3d348..c8909a8e4 100644 --- a/packages/quicktype-core/src/RendererOptions.ts +++ b/packages/quicktype-core/src/RendererOptions.ts @@ -1,9 +1,6 @@ -// eslint-disable-next-line @typescript-eslint/no-redeclare -import { hasOwnProperty } from "collection-utils"; - import { messageError } from "./Messages"; import { assert } from "./support/Support"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "./types"; +import { type FixMeOptionsType } from "./types"; /** * Primary options show up in the web UI in the "Language" settings tab, @@ -12,16 +9,16 @@ import { type FixMeOptionsAnyType, type FixMeOptionsType } from "./types"; export type OptionKind = "primary" | "secondary"; export interface OptionDefinition { - name: Name; - description: string; - type: StringConstructor | BooleanConstructor; - kind?: OptionKind; - renderer?: boolean; alias?: string; defaultOption?: boolean; defaultValue?: T; + description: string; + kind?: OptionKind; legalValues?: string[]; multiple?: boolean; + name: Name; + renderer?: boolean; + type: StringConstructor | BooleanConstructor; typeLabel?: string; } @@ -30,7 +27,7 @@ export interface OptionDefinition { * subclasses, `BooleanOption`, `EnumOption`, or `StringOption`. */ export abstract class Option { - protected readonly definition: OptionDefinition; + public readonly definition: OptionDefinition; public constructor(definition: OptionDefinition) { definition.renderer = true; @@ -54,7 +51,7 @@ export abstract class Option { } } -export type OptionValueType = O extends Option ? T : never; +export type OptionValueType = O extends Option ? T : never; export type OptionValues = { [P in keyof T]: OptionValueType }; export function getOptionValues>>( @@ -62,11 +59,11 @@ export function getOptionValues { const optionValues: FixMeOptionsType = {}; - for (const name of Object.getOwnPropertyNames(options)) { + for (const name of Object.keys(options)) { const option = options[name]; const value = option.getValue(untypedOptionValues); if (option instanceof EnumOption) { - optionValues[name] = option.getEnumValue(value); + optionValues[name] = option.getEnumValue(value as string); } else { optionValues[name] = value; } @@ -158,6 +155,7 @@ export class StringOption extends Option { } } +// eslint-disable-next-line @typescript-eslint/no-explicit-any type NoInfer = [T][T extends any ? 0 : never]; // FIXME: remove tuples and use map @@ -165,9 +163,9 @@ export class EnumOption< Name extends string, // EnumMap extends Record, // EnumKey = keyof EnumMap - EnumTuples extends Array<[string, unknown]>, - EnumKey = EnumTuples[number][0], - EnumMap = { [Key in EnumTuples[number][0]]: Extract[1] } + EnumTuples extends Readonly> = readonly [], + EnumKey = Readonly, + EnumMap extends object = Readonly<{ [Tuple in EnumTuples[number] as Tuple[0]]: Tuple[1] }> > extends Option { private readonly _values: EnumMap; @@ -176,7 +174,7 @@ export class EnumOption< description: string, // values: EnumMap, values: EnumTuples, - defaultValue: NoInfer, + defaultValue?: NoInfer, kind: OptionKind = "primary" ) { const definition = { @@ -196,7 +194,7 @@ export class EnumOption< // getEnumValue(name: Key): EnumMap[Key] { public getEnumValue(name: Key): EnumMap[Key] { - if (!hasOwnProperty(this._values, name)) { + if (!(name in this._values)) { return messageError("RendererUnknownOptionValue", { value: name, name: this.name }); } diff --git a/packages/quicktype-core/src/TargetLanguage.ts b/packages/quicktype-core/src/TargetLanguage.ts index 127a14d80..89da85a25 100644 --- a/packages/quicktype-core/src/TargetLanguage.ts +++ b/packages/quicktype-core/src/TargetLanguage.ts @@ -33,7 +33,7 @@ export abstract class TargetLanguage>; + protected abstract getOptions(): ReadonlyArray>; public get optionDefinitions(): OptionDefinition[] { return this.getOptions().map(o => o.definition); diff --git a/src/index.ts b/src/index.ts index eb9f8f0d4..ea0b74b68 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,10 +9,6 @@ import { definedMap, hasOwnProperty, mapFromObject, mapMap, withDefault } from " import commandLineArgs from "command-line-args"; import getUsage from "command-line-usage"; import * as _ from "lodash"; -import { type Readable } from "readable-stream"; -import stringToStream from "string-to-stream"; -import _wordwrap from "wordwrap"; - import { FetchingJSONSchemaStore, InputData, @@ -50,6 +46,9 @@ import { } from "quicktype-core"; import { GraphQLInput } from "quicktype-graphql-input"; import { schemaForTypeScriptSources } from "quicktype-typescript-input"; +import { type Readable } from "readable-stream"; +import stringToStream from "string-to-stream"; +import _wordwrap from "wordwrap"; import { CompressedJSONFromStream } from "./CompressedJSONFromStream"; import { introspectServer } from "./GraphQLIntrospection"; From da86cafee86d5e93f1d1eec96b8d43f6d7a8a1dd Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 1 Jun 2024 17:04:39 -0700 Subject: [PATCH 69/94] re-export All through index --- packages/quicktype-core/src/index.ts | 2 +- packages/quicktype-core/src/language/index.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/quicktype-core/src/index.ts b/packages/quicktype-core/src/index.ts index 596d05f21..4e8cb944b 100644 --- a/packages/quicktype-core/src/index.ts +++ b/packages/quicktype-core/src/index.ts @@ -21,7 +21,7 @@ export { Ref, type JSONSchemaType, type JSONSchemaAttributes } from "./input/JSO export type { RenderContext } from "./Renderer"; export { Option, type OptionDefinition, getOptionValues, type OptionValues } from "./RendererOptions"; export { TargetLanguage, type MultiFileRenderResult } from "./TargetLanguage"; -export { all as defaultTargetLanguages, languageNamed, isLanguageName } from "./language/All"; + export { type MultiWord, type Sourcelike, diff --git a/packages/quicktype-core/src/language/index.ts b/packages/quicktype-core/src/language/index.ts index 024a52494..9053882f9 100644 --- a/packages/quicktype-core/src/language/index.ts +++ b/packages/quicktype-core/src/language/index.ts @@ -24,3 +24,5 @@ export * from "./Swift"; export * from "./TypeScriptFlow"; export * from "./TypeScriptEffectSchema"; export * from "./TypeScriptZod"; + +export { all as defaultTargetLanguages, languageNamed, isLanguageName } from "./All"; From 31b343dfd929633526ce2800fec07773b8831004 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 1 Jun 2024 17:07:02 -0700 Subject: [PATCH 70/94] move language specific types into own file --- packages/quicktype-core/src/index.ts | 1 - packages/quicktype-core/src/language/index.ts | 1 + packages/quicktype-core/src/language/types.ts | 15 +++++++++++++++ packages/quicktype-core/src/types.ts | 15 --------------- 4 files changed, 16 insertions(+), 16 deletions(-) create mode 100644 packages/quicktype-core/src/language/types.ts diff --git a/packages/quicktype-core/src/index.ts b/packages/quicktype-core/src/index.ts index 4e8cb944b..6d41d2d22 100644 --- a/packages/quicktype-core/src/index.ts +++ b/packages/quicktype-core/src/index.ts @@ -83,6 +83,5 @@ export { StringTypes } from "./attributes/StringTypes"; export { removeNullFromUnion, matchType, nullableFromUnion } from "./TypeUtils"; export { ConvenienceRenderer } from "./ConvenienceRenderer"; export { uriTypeAttributeKind } from "./attributes/URIAttributes"; -export { type LanguageName, type LanguageDisplayName } from "./types"; export * from "./language"; diff --git a/packages/quicktype-core/src/language/index.ts b/packages/quicktype-core/src/language/index.ts index 9053882f9..c9fc2e4e8 100644 --- a/packages/quicktype-core/src/language/index.ts +++ b/packages/quicktype-core/src/language/index.ts @@ -26,3 +26,4 @@ export * from "./TypeScriptEffectSchema"; export * from "./TypeScriptZod"; export { all as defaultTargetLanguages, languageNamed, isLanguageName } from "./All"; +export { type LanguageName, type LanguageDisplayName } from "./types"; diff --git a/packages/quicktype-core/src/language/types.ts b/packages/quicktype-core/src/language/types.ts new file mode 100644 index 000000000..1a685e627 --- /dev/null +++ b/packages/quicktype-core/src/language/types.ts @@ -0,0 +1,15 @@ +import { type TargetLanguage } from "../TargetLanguage"; + +import { type all } from "./All"; + +type AllLanguages = (typeof all)[number]; + +export type LanguageDisplayName = Language["displayName"]; +export type LanguageName = Language["names"][number]; + +export type LanguageDisplayNameMap = { + [Language in AllLanguages as LanguageDisplayName]: Language; +}; +export type LanguageNameMap = { + [Language in AllLanguages as LanguageName]: Language; +}; diff --git a/packages/quicktype-core/src/types.ts b/packages/quicktype-core/src/types.ts index b276ed93f..de3800ca9 100644 --- a/packages/quicktype-core/src/types.ts +++ b/packages/quicktype-core/src/types.ts @@ -1,18 +1,3 @@ -import { type all } from "./language/All"; -import { type TargetLanguage } from "./TargetLanguage"; - -type AllLanguages = (typeof all)[number]; - -export type LanguageDisplayName = Language["displayName"]; -export type LanguageName = Language["names"][number]; - -export type LanguageDisplayNameMap = { - [Language in AllLanguages as LanguageDisplayName]: Language; -}; -export type LanguageNameMap = { - [Language in AllLanguages as LanguageName]: Language; -}; - // FIXME: remove these when options are strongly typed /* eslint-disable @typescript-eslint/no-explicit-any */ From 6d488d33f49f39a5d2b46504ed261bcccbb51e1d Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 1 Jun 2024 17:12:54 -0700 Subject: [PATCH 71/94] use map arg for EnumOption instead of tuple --- .../quicktype-core/src/RendererOptions.ts | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/packages/quicktype-core/src/RendererOptions.ts b/packages/quicktype-core/src/RendererOptions.ts index c8909a8e4..dbc36781a 100644 --- a/packages/quicktype-core/src/RendererOptions.ts +++ b/packages/quicktype-core/src/RendererOptions.ts @@ -158,22 +158,17 @@ export class StringOption extends Option { // eslint-disable-next-line @typescript-eslint/no-explicit-any type NoInfer = [T][T extends any ? 0 : never]; -// FIXME: remove tuples and use map export class EnumOption< Name extends string, - // EnumMap extends Record, - // EnumKey = keyof EnumMap - EnumTuples extends Readonly> = readonly [], - EnumKey = Readonly, - EnumMap extends object = Readonly<{ [Tuple in EnumTuples[number] as Tuple[0]]: Tuple[1] }> + EnumMap extends Record, + EnumKey extends Extract = Extract > extends Option { private readonly _values: EnumMap; public constructor( name: Name, description: string, - // values: EnumMap, - values: EnumTuples, + values: EnumMap, defaultValue?: NoInfer, kind: OptionKind = "primary" ) { @@ -182,18 +177,15 @@ export class EnumOption< kind, type: String, description, - // typeLabel: Object.keys(values).join("|"), - typeLabel: values.map(([key, _]) => key).join("|"), + typeLabel: Object.keys(values).join("|"), defaultValue }; super(definition); - // this._values = values; - this._values = values.reduce((acc, [key, val]) => ({ ...acc, [key]: val }), {} as Partial) as EnumMap; + this._values = values; } - // getEnumValue(name: Key): EnumMap[Key] { - public getEnumValue(name: Key): EnumMap[Key] { + public getEnumValue(name: Key): EnumMap[Key] { if (!(name in this._values)) { return messageError("RendererUnknownOptionValue", { value: name, name: this.name }); } From 258bd001378f188af5bde1d95f71a50e2b1a8efb Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 1 Jun 2024 17:17:12 -0700 Subject: [PATCH 72/94] remove custom NoInfer --- packages/quicktype-core/src/RendererOptions.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/quicktype-core/src/RendererOptions.ts b/packages/quicktype-core/src/RendererOptions.ts index dbc36781a..d9f61b238 100644 --- a/packages/quicktype-core/src/RendererOptions.ts +++ b/packages/quicktype-core/src/RendererOptions.ts @@ -155,9 +155,6 @@ export class StringOption extends Option { } } -// eslint-disable-next-line @typescript-eslint/no-explicit-any -type NoInfer = [T][T extends any ? 0 : never]; - export class EnumOption< Name extends string, EnumMap extends Record, From a68107ace477160c292828c8dc98024a6ebbfb25 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Tue, 4 Jun 2024 07:03:14 -0700 Subject: [PATCH 73/94] split OptionMap and OptionValues types --- packages/quicktype-core/src/RendererOptions.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/quicktype-core/src/RendererOptions.ts b/packages/quicktype-core/src/RendererOptions.ts index d9f61b238..759d82c56 100644 --- a/packages/quicktype-core/src/RendererOptions.ts +++ b/packages/quicktype-core/src/RendererOptions.ts @@ -51,8 +51,17 @@ export abstract class Option { } } -export type OptionValueType = O extends Option ? T : never; -export type OptionValues = { [P in keyof T]: OptionValueType }; +export type OptionKey = O extends Option ? Name : never; +export type OptionValue = + O extends EnumOption + ? EnumMap[EnumKey] + : O extends Option + ? Value + : never; + +// FIXME: Merge these and use camelCase user-facing keys (v24) +export type OptionMap = { [K in keyof T as OptionKey]: OptionValue }; // user-facing, keys are `name` property of Option +export type OptionValues = { [K in keyof T]: OptionValue }; // internal, keys are keys of `_Options` object in each language file export function getOptionValues>>( options: Options, @@ -155,6 +164,7 @@ export class StringOption extends Option { } } +// FIXME: use const generics here export class EnumOption< Name extends string, EnumMap extends Record, From 7ca8ffcb42e3babd04386b3ff285e86082b5f151 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Tue, 4 Jun 2024 07:59:40 -0700 Subject: [PATCH 74/94] update EnumOptions to use map --- .prettierrc | 2 +- .../src/language/CJSON/language.ts | 70 ++++++++-------- .../src/language/CPlusPlus/language.ts | 66 +++++++-------- .../src/language/CSharp/language.ts | 84 +++++++++---------- .../src/language/Elm/language.ts | 8 +- .../src/language/Haskell/language.ts | 8 +- .../src/language/Java/language.ts | 15 +--- .../src/language/JavaScript/language.ts | 10 +-- .../language/JavaScriptPropTypes/language.ts | 8 +- .../src/language/Kotlin/language.ts | 27 +++--- .../Objective-C/ObjectiveCRenderer.ts | 4 +- .../src/language/Objective-C/language.ts | 16 ++-- .../src/language/Python/language.ts | 12 +-- .../src/language/Ruby/language.ts | 10 +-- .../src/language/Rust/language.ts | 26 +++--- .../src/language/Scala3/language.ts | 22 ++--- .../src/language/Smithy4s/language.ts | 8 +- .../src/language/Swift/language.ts | 34 ++++---- .../quicktype-core/src/support/Acronyms.ts | 14 ++-- .../quicktype-core/src/support/Converters.ts | 10 +-- 20 files changed, 213 insertions(+), 241 deletions(-) diff --git a/.prettierrc b/.prettierrc index 1e80e79ea..994784875 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1 +1 @@ -{ "tabWidth": 4, "printWidth": 120, "trailingComma": "none", "arrowParens": "avoid" } +{ "tabWidth": 4, "printWidth": 120, "trailingComma": "none", "arrowParens": "avoid", "quoteProps": "consistent" } diff --git a/packages/quicktype-core/src/language/CJSON/language.ts b/packages/quicktype-core/src/language/CJSON/language.ts index 6ef2c6607..c4c52581a 100644 --- a/packages/quicktype-core/src/language/CJSON/language.ts +++ b/packages/quicktype-core/src/language/CJSON/language.ts @@ -22,42 +22,42 @@ */ import { type RenderContext } from "../../Renderer"; -import { EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; -import { type NamingStyle } from "../../support/Strings"; +import { EnumOption, StringOption, getOptionValues } from "../../RendererOptions"; import { TargetLanguage } from "../../TargetLanguage"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; +import { type FixMeOptionsType } from "../../types"; import { CJSONRenderer } from "./CJSONRenderer"; +// FIXME: share with C++ /* Naming styles */ -const pascalValue: [string, NamingStyle] = ["pascal-case", "pascal"]; -const underscoreValue: [string, NamingStyle] = ["underscore-case", "underscore"]; -const camelValue: [string, NamingStyle] = ["camel-case", "camel"]; -const upperUnderscoreValue: [string, NamingStyle] = ["upper-underscore-case", "upper-underscore"]; -const pascalUpperAcronymsValue: [string, NamingStyle] = ["pascal-case-upper-acronyms", "pascal-upper-acronyms"]; -const camelUpperAcronymsValue: [string, NamingStyle] = ["camel-case-upper-acronyms", "camel-upper-acronyms"]; +const pascalValue = ["pascal-case", "pascal"] as const; +const underscoreValue = ["underscore-case", "underscore"] as const; +const camelValue = ["camel-case", "camel"] as const; +const upperUnderscoreValue = ["upper-underscore-case", "upper-underscore"] as const; +const pascalUpperAcronymsValue = ["pascal-case-upper-acronyms", "pascal-upper-acronyms"] as const; +const camelUpperAcronymsValue = ["camel-case-upper-acronyms", "camel-upper-acronyms"] as const; /* cJSON generator options */ export const cJSONOptions = { typeSourceStyle: new EnumOption( "source-style", "Source code generation type, whether to generate single or multiple source files", - [ - ["single-source", true], - ["multi-source", false] - ], + { + "single-source": true, + "multi-source": false + } as const, "single-source", "secondary" ), typeIntegerSize: new EnumOption( "integer-size", "Integer code generation type (int64_t by default)", - [ - ["int8_t", "int8_t"], - ["int16_t", "int16_t"], - ["int32_t", "int32_t"], - ["int64_t", "int64_t"] - ], + { + int8_t: "int8_t", + int16_t: "int16_t", + int32_t: "int32_t", + int64_t: "int64_t" + } as const, "int64_t", "secondary" ), @@ -70,47 +70,47 @@ export const cJSONOptions = { addTypedefAlias: new EnumOption( "typedef-alias", "Add typedef alias to unions, structs, and enums (no typedef by default)", - [ - ["no-typedef", false], - ["add-typedef", true] - ], + { + "no-typedef": false, + "add-typedef": true + } as const, "no-typedef", "secondary" ), printStyle: new EnumOption( "print-style", "Which cJSON print should be used (formatted by default)", - [ - ["print-formatted", false], - ["print-unformatted", true] - ], + { + "print-formatted": false, + "print-unformatted": true + } as const, "print-formatted", "secondary" ), - typeNamingStyle: new EnumOption("type-style", "Naming style for types", [ + typeNamingStyle: new EnumOption("type-style", "Naming style for types", { pascalValue, underscoreValue, camelValue, upperUnderscoreValue, pascalUpperAcronymsValue, camelUpperAcronymsValue - ]), - memberNamingStyle: new EnumOption("member-style", "Naming style for members", [ + }), + memberNamingStyle: new EnumOption("member-style", "Naming style for members", { underscoreValue, pascalValue, camelValue, upperUnderscoreValue, pascalUpperAcronymsValue, camelUpperAcronymsValue - ]), - enumeratorNamingStyle: new EnumOption("enumerator-style", "Naming style for enumerators", [ + }), + enumeratorNamingStyle: new EnumOption("enumerator-style", "Naming style for enumerators", { upperUnderscoreValue, underscoreValue, pascalValue, camelValue, pascalUpperAcronymsValue, camelUpperAcronymsValue - ]) + }) }; /* cJSON generator target language */ @@ -129,7 +129,7 @@ export class CJSONTargetLanguage extends TargetLanguage> { + protected getOptions() { return [ cJSONOptions.typeSourceStyle, cJSONOptions.typeIntegerSize, @@ -139,7 +139,7 @@ export class CJSONTargetLanguage extends TargetLanguage("type-style", "Naming style for types", [ + typeNamingStyle: new EnumOption("type-style", "Naming style for types", { pascalValue, underscoreValue, camelValue, upperUnderscoreValue, pascalUpperAcronymsValue, camelUpperAcronymsValue - ]), - memberNamingStyle: new EnumOption("member-style", "Naming style for members", [ + }), + memberNamingStyle: new EnumOption("member-style", "Naming style for members", { underscoreValue, pascalValue, camelValue, upperUnderscoreValue, pascalUpperAcronymsValue, camelUpperAcronymsValue - ]), - enumeratorNamingStyle: new EnumOption("enumerator-style", "Naming style for enumerators", [ + }), + enumeratorNamingStyle: new EnumOption("enumerator-style", "Naming style for enumerators", { upperUnderscoreValue, underscoreValue, pascalValue, camelValue, pascalUpperAcronymsValue, camelUpperAcronymsValue - ]), + }), boost: new BooleanOption("boost", "Require a dependency on boost. Without boost, C++17 is required", true), hideNullOptional: new BooleanOption("hide-null-optional", "Hide null value for optional field", false) }; diff --git a/packages/quicktype-core/src/language/CSharp/language.ts b/packages/quicktype-core/src/language/CSharp/language.ts index 4e9007b44..3ec1ecaab 100644 --- a/packages/quicktype-core/src/language/CSharp/language.ts +++ b/packages/quicktype-core/src/language/CSharp/language.ts @@ -11,12 +11,6 @@ import { NewtonsoftCSharpRenderer } from "./NewtonSoftCSharpRenderer"; import { SystemTextJsonCSharpRenderer } from "./SystemTextJsonCSharpRenderer"; import { needTransformerForType } from "./utils"; -export enum Framework { - Newtonsoft = "Newtonsoft", - SystemTextJson = "SystemTextJson" -} - -export type Version = 5 | 6; export interface OutputFeatures { attributes: boolean; helpers: boolean; @@ -28,78 +22,78 @@ export const cSharpOptions = { framework: new EnumOption( "framework", "Serialization framework", - [ - ["NewtonSoft", Framework.Newtonsoft], - ["SystemTextJson", Framework.SystemTextJson] - ], + { + NewtonSoft: "NewtonSoft", + SystemTextJson: "SystemTextJson" + } as const, "NewtonSoft" ), - useList: new EnumOption("array-type", "Use T[] or List", [ - ["array", false], - ["list", true] - ]), + useList: new EnumOption("array-type", "Use T[] or List", { + array: false, + list: true + }), dense: new EnumOption( "density", "Property density", - [ - ["normal", false], - ["dense", true] - ], + { + normal: false, + dense: true + } as const, "normal", "secondary" ), // FIXME: Do this via a configurable named eventually. namespace: new StringOption("namespace", "Generated namespace", "NAME", "QuickType"), - version: new EnumOption( + version: new EnumOption( "csharp-version", "C# version", - [ - ["5", 5], - ["6", 6] - ], + { + "5": 5, + "6": 6 + } as const, "6", "secondary" ), virtual: new BooleanOption("virtual", "Generate virtual properties", false), - typeForAny: new EnumOption( + typeForAny: new EnumOption( "any-type", 'Type to use for "any"', - [ - ["object", "object"], - ["dynamic", "dynamic"] - ], + { + object: "object", + dynamic: "dynamic" + } as const, "object", "secondary" ), useDecimal: new EnumOption( "number-type", "Type to use for numbers", - [ - ["double", false], - ["decimal", true] - ], + { + double: false, + decimal: true + } as const, "double", "secondary" ), - features: new EnumOption("features", "Output features", [ - ["complete", { namespaces: true, helpers: true, attributes: true }], - ["attributes-only", { namespaces: true, helpers: false, attributes: true }], - ["just-types-and-namespace", { namespaces: true, helpers: false, attributes: false }], - ["just-types", { namespaces: true, helpers: false, attributes: false }] - ]), + features: new EnumOption("features", "Output features", { + "complete": { namespaces: true, helpers: true, attributes: true }, + "attributes-only": { namespaces: true, helpers: false, attributes: true }, + "just-types-and-namespace": { namespaces: true, helpers: false, attributes: false }, + "just-types": { namespaces: true, helpers: false, attributes: false } + } as const), baseclass: new EnumOption( "base-class", "Base class", - [ - ["EntityData", "EntityData"], - ["Object", undefined] - ], + { + EntityData: "EntityData", + Object: undefined + } as const, "Object", "secondary" ), checkRequired: new BooleanOption("check-required", "Fail if required properties are missing", false), keepPropertyName: new BooleanOption("keep-property-name", "Keep original field name generate", false) -}; +} as const; export const newtonsoftCSharpOptions = Object.assign({}, cSharpOptions, {}); @@ -158,13 +152,13 @@ export class CSharpTargetLanguage extends TargetLanguage", - [ - ["array", false], - ["list", true] - ], - "array" - ), + useList: new EnumOption("array-type", "Use T[] or List", { array: false, list: true } as const, "array"), justTypes: new BooleanOption("just-types", "Plain types only", false), dateTimeProvider: new EnumOption( "datetime-provider", "Date time provider type", - [ - ["java8", "java8"], - ["legacy", "legacy"] - ], + { java8: "java8", legacy: "legacy" } as const, "java8" ), acronymStyle: acronymOption(AcronymStyleOptions.Pascal), diff --git a/packages/quicktype-core/src/language/JavaScript/language.ts b/packages/quicktype-core/src/language/JavaScript/language.ts index 8eb0862e7..8be2f3eca 100644 --- a/packages/quicktype-core/src/language/JavaScript/language.ts +++ b/packages/quicktype-core/src/language/JavaScript/language.ts @@ -19,13 +19,13 @@ export const javaScriptOptions = { "secondary" ), converters: convertersOption(), - rawType: new EnumOption<"json" | "any">( + rawType: new EnumOption( "raw-type", "Type of raw input (json by default)", - [ - ["json", "json"], - ["any", "any"] - ], + { + json: "json", + any: "any" + } as const, "json", "secondary" ) diff --git a/packages/quicktype-core/src/language/JavaScriptPropTypes/language.ts b/packages/quicktype-core/src/language/JavaScriptPropTypes/language.ts index 39a388de7..9374a960c 100644 --- a/packages/quicktype-core/src/language/JavaScriptPropTypes/language.ts +++ b/packages/quicktype-core/src/language/JavaScriptPropTypes/language.ts @@ -13,10 +13,10 @@ export const javaScriptPropTypesOptions = { moduleSystem: new EnumOption( "module-system", "Which module system to use", - [ - ["common-js", false], - ["es6", true] - ], + { + "common-js": false, + "es6": true + } as const, "es6" ) }; diff --git a/packages/quicktype-core/src/language/Kotlin/language.ts b/packages/quicktype-core/src/language/Kotlin/language.ts index 55254f807..a7991d1df 100644 --- a/packages/quicktype-core/src/language/Kotlin/language.ts +++ b/packages/quicktype-core/src/language/Kotlin/language.ts @@ -11,23 +11,16 @@ import { KotlinKlaxonRenderer } from "./KotlinKlaxonRenderer"; import { KotlinRenderer } from "./KotlinRenderer"; import { KotlinXRenderer } from "./KotlinXRenderer"; -export enum Framework { - None = "None", - Jackson = "Jackson", - Klaxon = "Klaxon", - KotlinX = "KotlinX" -} - export const kotlinOptions = { framework: new EnumOption( "framework", "Serialization framework", - [ - ["just-types", Framework.None], - ["jackson", Framework.Jackson], - ["klaxon", Framework.Klaxon], - ["kotlinx", Framework.KotlinX] - ], + { + "just-types": "None", + "jackson": "Jackson", + "klaxon": "Klaxon", + "kotlinx": "KotlinX" + } as const, "klaxon" ), acronymStyle: acronymOption(AcronymStyleOptions.Pascal), @@ -61,13 +54,13 @@ export class KotlinTargetLanguage extends TargetLanguage( + features: new EnumOption( "python-version", "Python version", - [ - ["3.5", { typeHints: false, dataClasses: false }], - ["3.6", { typeHints: true, dataClasses: false }], - ["3.7", { typeHints: true, dataClasses: true }] - ], + { + "3.5": { typeHints: false, dataClasses: false }, + "3.6": { typeHints: true, dataClasses: false }, + "3.7": { typeHints: true, dataClasses: true } + }, "3.6" ), justTypes: new BooleanOption("just-types", "Classes only", false), diff --git a/packages/quicktype-core/src/language/Ruby/language.ts b/packages/quicktype-core/src/language/Ruby/language.ts index 34f9b4747..10fe38502 100644 --- a/packages/quicktype-core/src/language/Ruby/language.ts +++ b/packages/quicktype-core/src/language/Ruby/language.ts @@ -8,11 +8,11 @@ import { Strictness } from "./utils"; export const rubyOptions = { justTypes: new BooleanOption("just-types", "Plain types only", false), - strictness: new EnumOption("strictness", "Type strictness", [ - ["strict", Strictness.Strict], - ["coercible", Strictness.Coercible], - ["none", Strictness.None] - ]), + strictness: new EnumOption("strictness", "Type strictness", { + strict: Strictness.Strict, + coercible: Strictness.Coercible, + none: Strictness.None + } as const), namespace: new StringOption("namespace", "Specify a wrapping Namespace", "NAME", "", "secondary") }; diff --git a/packages/quicktype-core/src/language/Rust/language.ts b/packages/quicktype-core/src/language/Rust/language.ts index 855a28f6b..a33fa32b0 100644 --- a/packages/quicktype-core/src/language/Rust/language.ts +++ b/packages/quicktype-core/src/language/Rust/language.ts @@ -1,28 +1,28 @@ import { type RenderContext } from "../../Renderer"; -import { BooleanOption, EnumOption, type Option, getOptionValues } from "../../RendererOptions"; +import { BooleanOption, EnumOption, getOptionValues } from "../../RendererOptions"; import { TargetLanguage } from "../../TargetLanguage"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; +import { type FixMeOptionsType } from "../../types"; import { RustRenderer } from "./RustRenderer"; import { Density, Visibility } from "./utils"; export const rustOptions = { - density: new EnumOption("density", "Density", [ - ["normal", Density.Normal], - ["dense", Density.Dense] - ]), - visibility: new EnumOption("visibility", "Field visibility", [ - ["private", Visibility.Private], - ["crate", Visibility.Crate], - ["public", Visibility.Public] - ]), + density: new EnumOption("density", "Density", { + normal: Density.Normal, + dense: Density.Dense + } as const), + visibility: new EnumOption("visibility", "Field visibility", { + private: Visibility.Private, + crate: Visibility.Crate, + public: Visibility.Public + } as const), deriveDebug: new BooleanOption("derive-debug", "Derive Debug impl", false), deriveClone: new BooleanOption("derive-clone", "Derive Clone impl", false), derivePartialEq: new BooleanOption("derive-partial-eq", "Derive PartialEq impl", false), skipSerializingNone: new BooleanOption("skip-serializing-none", "Skip serializing empty Option fields", false), edition2018: new BooleanOption("edition-2018", "Edition 2018", true), leadingComments: new BooleanOption("leading-comments", "Leading Comments", true) -}; +} as const; export const rustLanguageConfig = { displayName: "Rust", @@ -39,7 +39,7 @@ export class RustTargetLanguage extends TargetLanguage> { + protected getOptions() { return [ rustOptions.density, rustOptions.visibility, diff --git a/packages/quicktype-core/src/language/Scala3/language.ts b/packages/quicktype-core/src/language/Scala3/language.ts index ad8b2f87f..e890a6780 100644 --- a/packages/quicktype-core/src/language/Scala3/language.ts +++ b/packages/quicktype-core/src/language/Scala3/language.ts @@ -9,21 +9,15 @@ import { CirceRenderer } from "./CirceRenderer"; import { Scala3Renderer } from "./Scala3Renderer"; import { UpickleRenderer } from "./UpickleRenderer"; -export enum Framework { - None = "None", - Upickle = "Upickle", - Circe = "Circe" -} - export const scala3Options = { framework: new EnumOption( "framework", "Serialization framework", - [ - ["just-types", Framework.None], - ["circe", Framework.Circe], - ["upickle", Framework.Upickle] - ], + { + "just-types": "None", + "circe": "Circe", + "upickle": "Upickle" + } as const, undefined ), packageName: new StringOption("package", "Package", "PACKAGE", "quicktype") @@ -56,11 +50,11 @@ export class Scala3TargetLanguage extends TargetLanguage { +export const acronymOption = function (defaultOption: AcronymStyleOptions) { return new EnumOption( "acronym-style", "Acronym naming style", - [ - [AcronymStyleOptions.Original, AcronymStyleOptions.Original], - [AcronymStyleOptions.Pascal, AcronymStyleOptions.Pascal], - [AcronymStyleOptions.Camel, AcronymStyleOptions.Camel], - [AcronymStyleOptions.Lower, AcronymStyleOptions.Lower] - ], + { + [AcronymStyleOptions.Original]: AcronymStyleOptions.Original, + [AcronymStyleOptions.Pascal]: AcronymStyleOptions.Pascal, + [AcronymStyleOptions.Camel]: AcronymStyleOptions.Camel, + [AcronymStyleOptions.Lower]: AcronymStyleOptions.Lower + } as const, defaultOption, "secondary" ); diff --git a/packages/quicktype-core/src/support/Converters.ts b/packages/quicktype-core/src/support/Converters.ts index caec348bf..0bc2f58fb 100644 --- a/packages/quicktype-core/src/support/Converters.ts +++ b/packages/quicktype-core/src/support/Converters.ts @@ -5,14 +5,14 @@ export enum ConvertersOptions { TopLevel = "top-level" } -export function convertersOption(): EnumOption { +export function convertersOption() { return new EnumOption( "converters", "Which converters to generate (top-level by default)", - [ - [ConvertersOptions.TopLevel, ConvertersOptions.TopLevel], - [ConvertersOptions.AllObjects, ConvertersOptions.AllObjects] - ], + { + [ConvertersOptions.TopLevel]: ConvertersOptions.TopLevel, + [ConvertersOptions.AllObjects]: ConvertersOptions.AllObjects + } as const, ConvertersOptions.TopLevel, "secondary" ); From 0f203f716b511e750590bf6c2f9e0b04c696fc46 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Tue, 4 Jun 2024 08:35:06 -0700 Subject: [PATCH 75/94] update getOptions to return options object instead of array --- doc/CustomRenderer.md | 6 +-- .../src/language/CJSON/language.ts | 13 +------ .../src/language/CPlusPlus/language.ts | 22 ++--------- .../src/language/CSharp/language.ts | 21 ++-------- .../src/language/Crystal/language.ts | 6 +-- .../src/language/Dart/language.ts | 20 ++-------- .../src/language/Elixir/language.ts | 8 ++-- .../src/language/Elm/language.ts | 8 ++-- .../src/language/Golang/language.ts | 15 ++------ .../src/language/Haskell/language.ts | 8 ++-- .../src/language/JSONSchema/language.ts | 7 ++-- .../src/language/Java/language.ts | 16 ++------ .../src/language/JavaScript/language.ts | 14 ++----- .../language/JavaScriptPropTypes/language.ts | 8 ++-- .../src/language/Kotlin/language.ts | 8 ++-- .../src/language/Objective-C/language.ts | 14 ++----- .../src/language/Php/language.ts | 10 ++--- .../src/language/Pike/language.ts | 6 +-- .../src/language/Python/language.ts | 8 ++-- .../src/language/Ruby/language.ts | 8 ++-- .../src/language/Rust/language.ts | 13 +------ .../src/language/Scala3/language.ts | 8 ++-- .../src/language/Smithy4s/language.ts | 8 ++-- .../src/language/Swift/language.ts | 27 ++----------- .../TypeScriptEffectSchema/language.ts | 8 ++-- .../src/language/TypeScriptFlow/language.ts | 38 +++---------------- .../src/language/TypeScriptZod/language.ts | 8 ++-- 27 files changed, 99 insertions(+), 237 deletions(-) diff --git a/doc/CustomRenderer.md b/doc/CustomRenderer.md index 0d866508a..42040e393 100644 --- a/doc/CustomRenderer.md +++ b/doc/CustomRenderer.md @@ -112,10 +112,8 @@ class BrandNewLanguage extends TargetLanguage { super(brandNewLanguageConfig); } - protected getOptions(): Array> { - return [ - brandNewLanguageOptions.allowFoo // list all options from the options config - ]; + public getOptions(): typeof brandNewLanguageOptions { + return brandNewLanguageOptions; } protected makeRenderer( diff --git a/packages/quicktype-core/src/language/CJSON/language.ts b/packages/quicktype-core/src/language/CJSON/language.ts index c4c52581a..3c3687442 100644 --- a/packages/quicktype-core/src/language/CJSON/language.ts +++ b/packages/quicktype-core/src/language/CJSON/language.ts @@ -129,17 +129,8 @@ export class CJSONTargetLanguage extends TargetLanguage> { - return [ - cPlusPlusOptions.justTypes, - cPlusPlusOptions.namespace, - cPlusPlusOptions.codeFormat, - cPlusPlusOptions.wstring, - cPlusPlusOptions.westConst, - cPlusPlusOptions.typeSourceStyle, - cPlusPlusOptions.includeLocation, - cPlusPlusOptions.typeNamingStyle, - cPlusPlusOptions.memberNamingStyle, - cPlusPlusOptions.enumeratorNamingStyle, - cPlusPlusOptions.enumType, - cPlusPlusOptions.boost, - cPlusPlusOptions.hideNullOptional - ]; + public getOptions(): typeof cPlusPlusOptions { + return cPlusPlusOptions; } public get supportsUnionsWithBothNumberTypes(): boolean { diff --git a/packages/quicktype-core/src/language/CSharp/language.ts b/packages/quicktype-core/src/language/CSharp/language.ts index 3ec1ecaab..d102211ce 100644 --- a/packages/quicktype-core/src/language/CSharp/language.ts +++ b/packages/quicktype-core/src/language/CSharp/language.ts @@ -1,11 +1,11 @@ import { type ConvenienceRenderer } from "../../ConvenienceRenderer"; import { type RenderContext } from "../../Renderer"; -import { BooleanOption, EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { BooleanOption, EnumOption, StringOption, getOptionValues } from "../../RendererOptions"; import { assertNever } from "../../support/Support"; import { TargetLanguage } from "../../TargetLanguage"; import { type PrimitiveStringTypeKind, type TransformedStringTypeKind, type Type } from "../../Type"; import { type StringTypeMapping } from "../../TypeBuilder"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; +import { type FixMeOptionsType } from "../../types"; import { NewtonsoftCSharpRenderer } from "./NewtonSoftCSharpRenderer"; import { SystemTextJsonCSharpRenderer } from "./SystemTextJsonCSharpRenderer"; @@ -106,21 +106,8 @@ export class CSharpTargetLanguage extends TargetLanguage> { - return [ - cSharpOptions.framework, - cSharpOptions.namespace, - cSharpOptions.version, - cSharpOptions.dense, - cSharpOptions.useList, - cSharpOptions.useDecimal, - cSharpOptions.typeForAny, - cSharpOptions.virtual, - cSharpOptions.features, - cSharpOptions.baseclass, - cSharpOptions.checkRequired, - cSharpOptions.keepPropertyName - ]; + public getOptions(): typeof cSharpOptions { + return cSharpOptions; } public get stringTypeMapping(): StringTypeMapping { diff --git a/packages/quicktype-core/src/language/Crystal/language.ts b/packages/quicktype-core/src/language/Crystal/language.ts index 98eb00994..db61e48be 100644 --- a/packages/quicktype-core/src/language/Crystal/language.ts +++ b/packages/quicktype-core/src/language/Crystal/language.ts @@ -1,7 +1,5 @@ import { type RenderContext } from "../../Renderer"; -import { type Option } from "../../RendererOptions"; import { TargetLanguage } from "../../TargetLanguage"; -import { type FixMeOptionsAnyType } from "../../types"; import { CrystalRenderer } from "./CrystalRenderer"; @@ -24,7 +22,7 @@ export class CrystalTargetLanguage extends TargetLanguage> { - return []; + public getOptions(): {} { + return {}; } } diff --git a/packages/quicktype-core/src/language/Dart/language.ts b/packages/quicktype-core/src/language/Dart/language.ts index 9c6206020..ffbe59f02 100644 --- a/packages/quicktype-core/src/language/Dart/language.ts +++ b/packages/quicktype-core/src/language/Dart/language.ts @@ -1,9 +1,9 @@ import { type RenderContext } from "../../Renderer"; -import { BooleanOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { BooleanOption, StringOption, getOptionValues } from "../../RendererOptions"; import { TargetLanguage } from "../../TargetLanguage"; import { type PrimitiveStringTypeKind, type TransformedStringTypeKind } from "../../Type"; import { type StringTypeMapping } from "../../TypeBuilder"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; +import { type FixMeOptionsType } from "../../types"; import { DartRenderer } from "./DartRenderer"; @@ -38,20 +38,8 @@ export class DartTargetLanguage extends TargetLanguage> { - return [ - dartOptions.nullSafety, - dartOptions.justTypes, - dartOptions.codersInClass, - dartOptions.methodNamesWithMap, - dartOptions.requiredProperties, - dartOptions.finalProperties, - dartOptions.generateCopyWith, - dartOptions.useFreezed, - dartOptions.useHive, - dartOptions.useJsonAnnotation, - dartOptions.partName - ]; + public getOptions(): typeof dartOptions { + return dartOptions; } public get supportsUnionsWithBothNumberTypes(): boolean { diff --git a/packages/quicktype-core/src/language/Elixir/language.ts b/packages/quicktype-core/src/language/Elixir/language.ts index dad552a2a..37b15d4cc 100644 --- a/packages/quicktype-core/src/language/Elixir/language.ts +++ b/packages/quicktype-core/src/language/Elixir/language.ts @@ -1,7 +1,7 @@ import { type RenderContext } from "../../Renderer"; -import { BooleanOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { BooleanOption, StringOption, getOptionValues } from "../../RendererOptions"; import { TargetLanguage } from "../../TargetLanguage"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; +import { type FixMeOptionsType } from "../../types"; import { ElixirRenderer } from "./ElixirRenderer"; @@ -21,8 +21,8 @@ export class ElixirTargetLanguage extends TargetLanguage> { - return [elixirOptions.justTypes, elixirOptions.namespace]; + public getOptions(): typeof elixirOptions { + return elixirOptions; } public get supportsOptionalClassProperties(): boolean { diff --git a/packages/quicktype-core/src/language/Elm/language.ts b/packages/quicktype-core/src/language/Elm/language.ts index e623cc58b..2725c798b 100644 --- a/packages/quicktype-core/src/language/Elm/language.ts +++ b/packages/quicktype-core/src/language/Elm/language.ts @@ -1,7 +1,7 @@ import { type RenderContext } from "../../Renderer"; -import { BooleanOption, EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { BooleanOption, EnumOption, StringOption, getOptionValues } from "../../RendererOptions"; import { TargetLanguage } from "../../TargetLanguage"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; +import { type FixMeOptionsType } from "../../types"; import { ElmRenderer } from "./ElmRenderer"; @@ -26,8 +26,8 @@ export class ElmTargetLanguage extends TargetLanguage super(elmLanguageConfig); } - protected getOptions(): Array> { - return [elmOptions.justTypes, elmOptions.moduleName, elmOptions.useList]; + public getOptions(): typeof elmOptions { + return elmOptions; } public get supportsOptionalClassProperties(): boolean { diff --git a/packages/quicktype-core/src/language/Golang/language.ts b/packages/quicktype-core/src/language/Golang/language.ts index 6715d4e2e..bf20cae3f 100644 --- a/packages/quicktype-core/src/language/Golang/language.ts +++ b/packages/quicktype-core/src/language/Golang/language.ts @@ -1,9 +1,9 @@ import { type RenderContext } from "../../Renderer"; -import { BooleanOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { BooleanOption, StringOption, getOptionValues } from "../../RendererOptions"; import { TargetLanguage } from "../../TargetLanguage"; import { type PrimitiveStringTypeKind, type TransformedStringTypeKind } from "../../Type"; import { type StringTypeMapping } from "../../TypeBuilder"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; +import { type FixMeOptionsType } from "../../types"; import { GoRenderer } from "./GolangRenderer"; @@ -31,15 +31,8 @@ export class GoTargetLanguage extends TargetLanguage> { - return [ - goOptions.justTypes, - goOptions.justTypesAndPackage, - goOptions.packageName, - goOptions.multiFileOutput, - goOptions.fieldTags, - goOptions.omitEmpty - ]; + public getOptions(): typeof goOptions { + return goOptions; } public get supportsUnionsWithBothNumberTypes(): boolean { diff --git a/packages/quicktype-core/src/language/Haskell/language.ts b/packages/quicktype-core/src/language/Haskell/language.ts index d49a667c3..a7b937fd0 100644 --- a/packages/quicktype-core/src/language/Haskell/language.ts +++ b/packages/quicktype-core/src/language/Haskell/language.ts @@ -1,7 +1,7 @@ import { type RenderContext } from "../../Renderer"; -import { BooleanOption, EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { BooleanOption, EnumOption, StringOption, getOptionValues } from "../../RendererOptions"; import { TargetLanguage } from "../../TargetLanguage"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; +import { type FixMeOptionsType } from "../../types"; import { HaskellRenderer } from "./HaskellRenderer"; @@ -25,8 +25,8 @@ export class HaskellTargetLanguage extends TargetLanguage> { - return [haskellOptions.justTypes, haskellOptions.moduleName, haskellOptions.useList]; + public getOptions(): typeof haskellOptions { + return haskellOptions; } public get supportsOptionalClassProperties(): boolean { diff --git a/packages/quicktype-core/src/language/JSONSchema/language.ts b/packages/quicktype-core/src/language/JSONSchema/language.ts index e872eb758..f3caf14c0 100644 --- a/packages/quicktype-core/src/language/JSONSchema/language.ts +++ b/packages/quicktype-core/src/language/JSONSchema/language.ts @@ -1,8 +1,7 @@ import { type RenderContext } from "../../Renderer"; -import { type Option } from "../../RendererOptions"; import { TargetLanguage } from "../../TargetLanguage"; import { type StringTypeMapping, getNoStringTypeMapping } from "../../TypeBuilder"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; +import { type FixMeOptionsType } from "../../types"; import { JSONSchemaRenderer } from "./JSONSchemaRenderer"; @@ -17,8 +16,8 @@ export class JSONSchemaTargetLanguage extends TargetLanguage> { - return []; + public getOptions(): {} { + return {}; } public get stringTypeMapping(): StringTypeMapping { diff --git a/packages/quicktype-core/src/language/Java/language.ts b/packages/quicktype-core/src/language/Java/language.ts index 34ad8fa31..368757a02 100644 --- a/packages/quicktype-core/src/language/Java/language.ts +++ b/packages/quicktype-core/src/language/Java/language.ts @@ -1,10 +1,10 @@ import { type RenderContext } from "../../Renderer"; -import { BooleanOption, EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { BooleanOption, EnumOption, StringOption, getOptionValues } from "../../RendererOptions"; import { AcronymStyleOptions, acronymOption } from "../../support/Acronyms"; import { TargetLanguage } from "../../TargetLanguage"; import { type PrimitiveStringTypeKind, type TransformedStringTypeKind } from "../../Type"; import { type StringTypeMapping } from "../../TypeBuilder"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; +import { type FixMeOptionsType } from "../../types"; import { JacksonRenderer } from "./JavaJacksonRenderer"; import { JavaRenderer } from "./JavaRenderer"; @@ -36,16 +36,8 @@ export class JavaTargetLanguage extends TargetLanguage> { - return [ - javaOptions.useList, - javaOptions.justTypes, - javaOptions.dateTimeProvider, - javaOptions.acronymStyle, - javaOptions.packageName, - javaOptions.lombok, - javaOptions.lombokCopyAnnotations - ]; + public getOptions(): typeof javaOptions { + return javaOptions; } public get supportsUnionsWithBothNumberTypes(): boolean { diff --git a/packages/quicktype-core/src/language/JavaScript/language.ts b/packages/quicktype-core/src/language/JavaScript/language.ts index 8be2f3eca..b781a2044 100644 --- a/packages/quicktype-core/src/language/JavaScript/language.ts +++ b/packages/quicktype-core/src/language/JavaScript/language.ts @@ -1,11 +1,11 @@ import { type RenderContext } from "../../Renderer"; -import { BooleanOption, EnumOption, type Option, getOptionValues } from "../../RendererOptions"; +import { BooleanOption, EnumOption, getOptionValues } from "../../RendererOptions"; import { AcronymStyleOptions, acronymOption } from "../../support/Acronyms"; import { convertersOption } from "../../support/Converters"; import { TargetLanguage } from "../../TargetLanguage"; import { type PrimitiveStringTypeKind, type TransformedStringTypeKind } from "../../Type"; import { type StringTypeMapping } from "../../TypeBuilder"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; +import { type FixMeOptionsType } from "../../types"; import { JavaScriptRenderer } from "./JavaScriptRenderer"; @@ -42,14 +42,8 @@ export class JavaScriptTargetLanguage extends TargetLanguage> { - return [ - javaScriptOptions.runtimeTypecheck, - javaScriptOptions.runtimeTypecheckIgnoreUnknownProperties, - javaScriptOptions.acronymStyle, - javaScriptOptions.converters, - javaScriptOptions.rawType - ]; + public getOptions(): typeof javaScriptOptions { + return javaScriptOptions; } public get stringTypeMapping(): StringTypeMapping { diff --git a/packages/quicktype-core/src/language/JavaScriptPropTypes/language.ts b/packages/quicktype-core/src/language/JavaScriptPropTypes/language.ts index 9374a960c..317ac8596 100644 --- a/packages/quicktype-core/src/language/JavaScriptPropTypes/language.ts +++ b/packages/quicktype-core/src/language/JavaScriptPropTypes/language.ts @@ -1,9 +1,9 @@ import { type RenderContext } from "../../Renderer"; -import { EnumOption, type Option, getOptionValues } from "../../RendererOptions"; +import { EnumOption, getOptionValues } from "../../RendererOptions"; import { AcronymStyleOptions, acronymOption } from "../../support/Acronyms"; import { convertersOption } from "../../support/Converters"; import { TargetLanguage } from "../../TargetLanguage"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; +import { type FixMeOptionsType } from "../../types"; import { JavaScriptPropTypesRenderer } from "./JavaScriptPropTypesRenderer"; @@ -32,8 +32,8 @@ export class JavaScriptPropTypesTargetLanguage extends TargetLanguage> { - return [javaScriptPropTypesOptions.acronymStyle, javaScriptPropTypesOptions.converters]; + public getOptions(): typeof javaScriptPropTypesOptions { + return javaScriptPropTypesOptions; } protected makeRenderer( diff --git a/packages/quicktype-core/src/language/Kotlin/language.ts b/packages/quicktype-core/src/language/Kotlin/language.ts index a7991d1df..27d149a3b 100644 --- a/packages/quicktype-core/src/language/Kotlin/language.ts +++ b/packages/quicktype-core/src/language/Kotlin/language.ts @@ -1,10 +1,10 @@ import { type ConvenienceRenderer } from "../../ConvenienceRenderer"; import { type RenderContext } from "../../Renderer"; -import { EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { EnumOption, StringOption, getOptionValues } from "../../RendererOptions"; import { AcronymStyleOptions, acronymOption } from "../../support/Acronyms"; import { assertNever } from "../../support/Support"; import { TargetLanguage } from "../../TargetLanguage"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; +import { type FixMeOptionsType } from "../../types"; import { KotlinJacksonRenderer } from "./KotlinJacksonRenderer"; import { KotlinKlaxonRenderer } from "./KotlinKlaxonRenderer"; @@ -38,8 +38,8 @@ export class KotlinTargetLanguage extends TargetLanguage> { - return [kotlinOptions.framework, kotlinOptions.acronymStyle, kotlinOptions.packageName]; + public getOptions(): typeof kotlinOptions { + return kotlinOptions; } public get supportsOptionalClassProperties(): boolean { diff --git a/packages/quicktype-core/src/language/Objective-C/language.ts b/packages/quicktype-core/src/language/Objective-C/language.ts index 1cc5fa3ef..13e639a04 100644 --- a/packages/quicktype-core/src/language/Objective-C/language.ts +++ b/packages/quicktype-core/src/language/Objective-C/language.ts @@ -1,7 +1,7 @@ import { type RenderContext } from "../../Renderer"; -import { BooleanOption, EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { BooleanOption, EnumOption, StringOption, getOptionValues } from "../../RendererOptions"; import { TargetLanguage } from "../../TargetLanguage"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; +import { type FixMeOptionsType } from "../../types"; import { ObjectiveCRenderer } from "./ObjectiveCRenderer"; import { DEFAULT_CLASS_PREFIX } from "./utils"; @@ -29,14 +29,8 @@ export class ObjectiveCTargetLanguage extends TargetLanguage> { - return [ - objectiveCOptions.justTypes, - objectiveCOptions.classPrefix, - objectiveCOptions.features, - objectiveCOptions.extraComments, - objectiveCOptions.marshallingFunctions - ]; + public getOptions(): typeof objectiveCOptions { + return objectiveCOptions; } protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): ObjectiveCRenderer { diff --git a/packages/quicktype-core/src/language/Php/language.ts b/packages/quicktype-core/src/language/Php/language.ts index a3212dea0..2177ffa5f 100644 --- a/packages/quicktype-core/src/language/Php/language.ts +++ b/packages/quicktype-core/src/language/Php/language.ts @@ -1,12 +1,10 @@ -import * as _ from "lodash"; - import { type RenderContext } from "../../Renderer"; -import { BooleanOption, type Option, getOptionValues } from "../../RendererOptions"; +import { BooleanOption, getOptionValues } from "../../RendererOptions"; import { AcronymStyleOptions, acronymOption } from "../../support/Acronyms"; import { TargetLanguage } from "../../TargetLanguage"; import { type PrimitiveStringTypeKind, type TransformedStringTypeKind } from "../../Type"; import { type StringTypeMapping } from "../../TypeBuilder"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; +import { type FixMeOptionsType } from "../../types"; import { PhpRenderer } from "./PhpRenderer"; @@ -29,8 +27,8 @@ export class PhpTargetLanguage extends TargetLanguage super(phpLanguageConfig); } - protected getOptions(): Array> { - return _.values(phpOptions); + public getOptions(): typeof phpOptions { + return phpOptions; } public get supportsUnionsWithBothNumberTypes(): boolean { diff --git a/packages/quicktype-core/src/language/Pike/language.ts b/packages/quicktype-core/src/language/Pike/language.ts index 43a6db737..35be5b5a0 100644 --- a/packages/quicktype-core/src/language/Pike/language.ts +++ b/packages/quicktype-core/src/language/Pike/language.ts @@ -1,7 +1,5 @@ import { type RenderContext } from "../../Renderer"; -import { type Option } from "../../RendererOptions"; import { TargetLanguage } from "../../TargetLanguage"; -import { type FixMeOptionsAnyType } from "../../types"; import { PikeRenderer } from "./PikeRenderer"; @@ -18,8 +16,8 @@ export class PikeTargetLanguage extends TargetLanguage> { - return []; + public getOptions(): {} { + return {}; } protected makeRenderer(renderContext: RenderContext): PikeRenderer { diff --git a/packages/quicktype-core/src/language/Python/language.ts b/packages/quicktype-core/src/language/Python/language.ts index 2d41f089e..53b148aef 100644 --- a/packages/quicktype-core/src/language/Python/language.ts +++ b/packages/quicktype-core/src/language/Python/language.ts @@ -1,11 +1,11 @@ import { iterableSome } from "collection-utils"; import { type RenderContext } from "../../Renderer"; -import { BooleanOption, EnumOption, type Option, getOptionValues } from "../../RendererOptions"; +import { BooleanOption, EnumOption, getOptionValues } from "../../RendererOptions"; import { TargetLanguage } from "../../TargetLanguage"; import { type PrimitiveStringTypeKind, type TransformedStringTypeKind, type Type, UnionType } from "../../Type"; import { type StringTypeMapping } from "../../TypeBuilder"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; +import { type FixMeOptionsType } from "../../types"; import { JSONPythonRenderer } from "./JSONPythonRenderer"; import { PythonRenderer } from "./PythonRenderer"; @@ -37,8 +37,8 @@ export class PythonTargetLanguage extends TargetLanguage> { - return [pythonOptions.features, pythonOptions.justTypes, pythonOptions.nicePropertyNames]; + public getOptions(): typeof pythonOptions { + return pythonOptions; } public get stringTypeMapping(): StringTypeMapping { diff --git a/packages/quicktype-core/src/language/Ruby/language.ts b/packages/quicktype-core/src/language/Ruby/language.ts index 10fe38502..b2e63ccb3 100644 --- a/packages/quicktype-core/src/language/Ruby/language.ts +++ b/packages/quicktype-core/src/language/Ruby/language.ts @@ -1,7 +1,7 @@ import { type RenderContext } from "../../Renderer"; -import { BooleanOption, EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { BooleanOption, EnumOption, StringOption, getOptionValues } from "../../RendererOptions"; import { TargetLanguage } from "../../TargetLanguage"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; +import { type FixMeOptionsType } from "../../types"; import { RubyRenderer } from "./RubyRenderer"; import { Strictness } from "./utils"; @@ -27,8 +27,8 @@ export class RubyTargetLanguage extends TargetLanguage> { - return [rubyOptions.justTypes, rubyOptions.strictness, rubyOptions.namespace]; + public getOptions(): typeof rubyOptions { + return rubyOptions; } public get supportsOptionalClassProperties(): boolean { diff --git a/packages/quicktype-core/src/language/Rust/language.ts b/packages/quicktype-core/src/language/Rust/language.ts index a33fa32b0..29f7a92d3 100644 --- a/packages/quicktype-core/src/language/Rust/language.ts +++ b/packages/quicktype-core/src/language/Rust/language.ts @@ -39,16 +39,7 @@ export class RustTargetLanguage extends TargetLanguage> { - return [scala3Options.framework, scala3Options.packageName]; + public getOptions(): typeof scala3Options { + return scala3Options; } public get supportsOptionalClassProperties(): boolean { diff --git a/packages/quicktype-core/src/language/Smithy4s/language.ts b/packages/quicktype-core/src/language/Smithy4s/language.ts index ca2f78e70..a00247469 100644 --- a/packages/quicktype-core/src/language/Smithy4s/language.ts +++ b/packages/quicktype-core/src/language/Smithy4s/language.ts @@ -1,9 +1,9 @@ import { type ConvenienceRenderer } from "../../ConvenienceRenderer"; import { type RenderContext } from "../../Renderer"; -import { EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { EnumOption, StringOption, getOptionValues } from "../../RendererOptions"; import { assertNever } from "../../support/Support"; import { TargetLanguage } from "../../TargetLanguage"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; +import { type FixMeOptionsType } from "../../types"; import { Smithy4sRenderer } from "./Smithy4sRenderer"; @@ -33,8 +33,8 @@ export class SmithyTargetLanguage extends TargetLanguage> { - return [smithyOptions.framework, smithyOptions.packageName]; + public getOptions(): typeof smithyOptions { + return smithyOptions; } public get supportsOptionalClassProperties(): boolean { diff --git a/packages/quicktype-core/src/language/Swift/language.ts b/packages/quicktype-core/src/language/Swift/language.ts index bec5801d9..54c2301f4 100644 --- a/packages/quicktype-core/src/language/Swift/language.ts +++ b/packages/quicktype-core/src/language/Swift/language.ts @@ -1,11 +1,11 @@ import { type DateTimeRecognizer } from "../../DateTime"; import { type RenderContext } from "../../Renderer"; -import { BooleanOption, EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; +import { BooleanOption, EnumOption, StringOption, getOptionValues } from "../../RendererOptions"; import { AcronymStyleOptions, acronymOption } from "../../support/Acronyms"; import { TargetLanguage } from "../../TargetLanguage"; import { type PrimitiveStringTypeKind, type TransformedStringTypeKind } from "../../Type"; import { type StringTypeMapping } from "../../TypeBuilder"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; +import { type FixMeOptionsType } from "../../types"; import { SwiftRenderer } from "./SwiftRenderer"; import { SwiftDateTimeRecognizer } from "./utils"; @@ -87,27 +87,8 @@ export class SwiftTargetLanguage extends TargetLanguage> { - return [ - swiftOptions.justTypes, - swiftOptions.useClasses, - swiftOptions.dense, - swiftOptions.convenienceInitializers, - swiftOptions.explicitCodingKeys, - swiftOptions.codingKeysProtocol, - swiftOptions.accessLevel, - swiftOptions.alamofire, - swiftOptions.linux, - swiftOptions.namedTypePrefix, - swiftOptions.protocol, - swiftOptions.acronymStyle, - swiftOptions.objcSupport, - swiftOptions.optionalEnums, - swiftOptions.sendable, - swiftOptions.swift5Support, - swiftOptions.multiFileOutput, - swiftOptions.mutableProperties - ]; + public getOptions(): typeof swiftOptions { + return swiftOptions; } public get stringTypeMapping(): StringTypeMapping { diff --git a/packages/quicktype-core/src/language/TypeScriptEffectSchema/language.ts b/packages/quicktype-core/src/language/TypeScriptEffectSchema/language.ts index 050b6a005..9d14bf29d 100644 --- a/packages/quicktype-core/src/language/TypeScriptEffectSchema/language.ts +++ b/packages/quicktype-core/src/language/TypeScriptEffectSchema/language.ts @@ -1,7 +1,7 @@ import { type RenderContext } from "../../Renderer"; -import { BooleanOption, type Option, getOptionValues } from "../../RendererOptions"; +import { BooleanOption, getOptionValues } from "../../RendererOptions"; import { TargetLanguage } from "../../TargetLanguage"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; +import { type FixMeOptionsType } from "../../types"; import { TypeScriptEffectSchemaRenderer } from "./TypeScriptEffectSchemaRenderer"; @@ -20,8 +20,8 @@ export class TypeScriptEffectSchemaTargetLanguage extends TargetLanguage> { - return []; + public getOptions(): {} { + return {}; } protected makeRenderer( diff --git a/packages/quicktype-core/src/language/TypeScriptFlow/language.ts b/packages/quicktype-core/src/language/TypeScriptFlow/language.ts index b97bc4b9f..c2285d9fc 100644 --- a/packages/quicktype-core/src/language/TypeScriptFlow/language.ts +++ b/packages/quicktype-core/src/language/TypeScriptFlow/language.ts @@ -1,9 +1,9 @@ import { type RenderContext } from "../../Renderer"; -import { BooleanOption, type Option, getOptionValues } from "../../RendererOptions"; +import { BooleanOption, getOptionValues } from "../../RendererOptions"; import { TargetLanguage } from "../../TargetLanguage"; import { type PrimitiveStringTypeKind, type TransformedStringTypeKind } from "../../Type"; import { type StringTypeMapping } from "../../TypeBuilder"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; +import { type FixMeOptionsType } from "../../types"; import { javaScriptOptions } from "../JavaScript"; import { FlowRenderer } from "./FlowRenderer"; @@ -34,21 +34,8 @@ export class TypeScriptTargetLanguage extends TargetLanguage> { - return [ - tsFlowOptions.justTypes, - tsFlowOptions.nicePropertyNames, - tsFlowOptions.declareUnions, - tsFlowOptions.runtimeTypecheck, - tsFlowOptions.runtimeTypecheckIgnoreUnknownProperties, - tsFlowOptions.acronymStyle, - tsFlowOptions.converters, - tsFlowOptions.rawType, - tsFlowOptions.preferUnions, - tsFlowOptions.preferTypes, - tsFlowOptions.preferConstValues, - tsFlowOptions.readonly - ]; + public getOptions(): typeof tsFlowOptions { + return tsFlowOptions; } public get stringTypeMapping(): StringTypeMapping { @@ -83,21 +70,8 @@ export class FlowTargetLanguage extends TargetLanguage> { - return [ - tsFlowOptions.justTypes, - tsFlowOptions.nicePropertyNames, - tsFlowOptions.declareUnions, - tsFlowOptions.runtimeTypecheck, - tsFlowOptions.runtimeTypecheckIgnoreUnknownProperties, - tsFlowOptions.acronymStyle, - tsFlowOptions.converters, - tsFlowOptions.rawType, - tsFlowOptions.preferUnions, - tsFlowOptions.preferTypes, - tsFlowOptions.preferConstValues, - tsFlowOptions.readonly - ]; + public getOptions(): typeof tsFlowOptions { + return tsFlowOptions; } public get stringTypeMapping(): StringTypeMapping { diff --git a/packages/quicktype-core/src/language/TypeScriptZod/language.ts b/packages/quicktype-core/src/language/TypeScriptZod/language.ts index aeda1f641..9f119aec5 100644 --- a/packages/quicktype-core/src/language/TypeScriptZod/language.ts +++ b/packages/quicktype-core/src/language/TypeScriptZod/language.ts @@ -1,9 +1,9 @@ import { type RenderContext } from "../../Renderer"; -import { BooleanOption, type Option, getOptionValues } from "../../RendererOptions"; +import { BooleanOption, getOptionValues } from "../../RendererOptions"; import { TargetLanguage } from "../../TargetLanguage"; import { type PrimitiveStringTypeKind, type TransformedStringTypeKind } from "../../Type"; import { type StringTypeMapping } from "../../TypeBuilder"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; +import { type FixMeOptionsType } from "../../types"; import { TypeScriptZodRenderer } from "./TypeScriptZodRenderer"; @@ -22,8 +22,8 @@ export class TypeScriptZodTargetLanguage extends TargetLanguage> { - return []; + public getOptions(): {} { + return {}; } public get stringTypeMapping(): StringTypeMapping { From 9e0f8aa96cab874bf600c8bdc79db00ad5962202 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Tue, 4 Jun 2024 08:35:33 -0700 Subject: [PATCH 76/94] aggregate language options types --- packages/quicktype-core/src/language/All.ts | 2 +- packages/quicktype-core/src/language/options.types.ts | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 packages/quicktype-core/src/language/options.types.ts diff --git a/packages/quicktype-core/src/language/All.ts b/packages/quicktype-core/src/language/All.ts index fec959dc9..6dfa991fc 100644 --- a/packages/quicktype-core/src/language/All.ts +++ b/packages/quicktype-core/src/language/All.ts @@ -1,5 +1,4 @@ import { type TargetLanguage } from "../TargetLanguage"; -import { type LanguageDisplayName, type LanguageName, type LanguageNameMap } from "../types"; import { CJSONTargetLanguage } from "./CJSON"; import { CPlusPlusTargetLanguage } from "./CPlusPlus"; @@ -25,6 +24,7 @@ import { RustTargetLanguage } from "./Rust"; import { Scala3TargetLanguage } from "./Scala3"; import { SmithyTargetLanguage } from "./Smithy4s"; import { SwiftTargetLanguage } from "./Swift"; +import { type LanguageDisplayName, type LanguageName, type LanguageNameMap } from "./types"; import { TypeScriptEffectSchemaTargetLanguage } from "./TypeScriptEffectSchema"; import { FlowTargetLanguage, TypeScriptTargetLanguage } from "./TypeScriptFlow"; import { TypeScriptZodTargetLanguage } from "./TypeScriptZod"; diff --git a/packages/quicktype-core/src/language/options.types.ts b/packages/quicktype-core/src/language/options.types.ts new file mode 100644 index 000000000..1fb9a8699 --- /dev/null +++ b/packages/quicktype-core/src/language/options.types.ts @@ -0,0 +1,11 @@ +import { type OptionMap } from "../RendererOptions"; + +import { type LanguageDisplayNameMap } from "./types"; + +export type LanguageRawOptionMap = Readonly<{ + [Lang in keyof LanguageDisplayNameMap]: ReturnType; +}>; + +export type LanguageOptionMap = Readonly<{ + [Lang in keyof LanguageRawOptionMap]: OptionMap; +}>; From 2608f68f931ac86e151b73a265f66694f3c4cb8f Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Tue, 4 Jun 2024 08:46:13 -0700 Subject: [PATCH 77/94] fix naming style options for C langs --- .../src/language/CJSON/language.ts | 42 +++++-------------- .../src/language/CPlusPlus/language.ts | 41 +++++------------- 2 files changed, 22 insertions(+), 61 deletions(-) diff --git a/packages/quicktype-core/src/language/CJSON/language.ts b/packages/quicktype-core/src/language/CJSON/language.ts index 3c3687442..14add3530 100644 --- a/packages/quicktype-core/src/language/CJSON/language.ts +++ b/packages/quicktype-core/src/language/CJSON/language.ts @@ -28,14 +28,15 @@ import { type FixMeOptionsType } from "../../types"; import { CJSONRenderer } from "./CJSONRenderer"; -// FIXME: share with C++ /* Naming styles */ -const pascalValue = ["pascal-case", "pascal"] as const; -const underscoreValue = ["underscore-case", "underscore"] as const; -const camelValue = ["camel-case", "camel"] as const; -const upperUnderscoreValue = ["upper-underscore-case", "upper-underscore"] as const; -const pascalUpperAcronymsValue = ["pascal-case-upper-acronyms", "pascal-upper-acronyms"] as const; -const camelUpperAcronymsValue = ["camel-case-upper-acronyms", "camel-upper-acronyms"] as const; +const namingStyles = { + "pascal-case": "pascal", + "underscore-case": "underscore", + "camel-case": "camel", + "upper-underscore-case": "upper-underscore", + "pascal-case-upper-acronyms": "pascal-upper-acronyms", + "camel-case-upper-acronyms": "camel-upper-acronyms" +} as const; /* cJSON generator options */ export const cJSONOptions = { @@ -87,30 +88,9 @@ export const cJSONOptions = { "print-formatted", "secondary" ), - typeNamingStyle: new EnumOption("type-style", "Naming style for types", { - pascalValue, - underscoreValue, - camelValue, - upperUnderscoreValue, - pascalUpperAcronymsValue, - camelUpperAcronymsValue - }), - memberNamingStyle: new EnumOption("member-style", "Naming style for members", { - underscoreValue, - pascalValue, - camelValue, - upperUnderscoreValue, - pascalUpperAcronymsValue, - camelUpperAcronymsValue - }), - enumeratorNamingStyle: new EnumOption("enumerator-style", "Naming style for enumerators", { - upperUnderscoreValue, - underscoreValue, - pascalValue, - camelValue, - pascalUpperAcronymsValue, - camelUpperAcronymsValue - }) + typeNamingStyle: new EnumOption("type-style", "Naming style for types", namingStyles), + memberNamingStyle: new EnumOption("member-style", "Naming style for members", namingStyles), + enumeratorNamingStyle: new EnumOption("enumerator-style", "Naming style for enumerators", namingStyles) }; /* cJSON generator target language */ diff --git a/packages/quicktype-core/src/language/CPlusPlus/language.ts b/packages/quicktype-core/src/language/CPlusPlus/language.ts index 9788420ed..1def52fc0 100644 --- a/packages/quicktype-core/src/language/CPlusPlus/language.ts +++ b/packages/quicktype-core/src/language/CPlusPlus/language.ts @@ -6,12 +6,14 @@ import { type FixMeOptionsType } from "../../types"; import { CPlusPlusRenderer } from "./CPlusPlusRenderer"; // FIXME: share with CJSON -const pascalValue = ["pascal-case", "pascal"] as const; -const underscoreValue = ["underscore-case", "underscore"] as const; -const camelValue = ["camel-case", "camel"] as const; -const upperUnderscoreValue = ["upper-underscore-case", "upper-underscore"] as const; -const pascalUpperAcronymsValue = ["pascal-case-upper-acronyms", "pascal-upper-acronyms"] as const; -const camelUpperAcronymsValue = ["camel-case-upper-acronyms", "camel-upper-acronyms"] as const; +const namingStyles = { + "pascal-case": "pascal", + "underscore-case": "underscore", + "camel-case": "camel", + "upper-underscore-case": "upper-underscore", + "pascal-case-upper-acronyms": "pascal-upper-acronyms", + "camel-case-upper-acronyms": "camel-upper-acronyms" +} as const; export const cPlusPlusOptions = { typeSourceStyle: new EnumOption( @@ -64,30 +66,9 @@ export const cPlusPlusOptions = { justTypes: new BooleanOption("just-types", "Plain types only", false), namespace: new StringOption("namespace", "Name of the generated namespace(s)", "NAME", "quicktype"), enumType: new StringOption("enum-type", "Type of enum class", "NAME", "int", "secondary"), - typeNamingStyle: new EnumOption("type-style", "Naming style for types", { - pascalValue, - underscoreValue, - camelValue, - upperUnderscoreValue, - pascalUpperAcronymsValue, - camelUpperAcronymsValue - }), - memberNamingStyle: new EnumOption("member-style", "Naming style for members", { - underscoreValue, - pascalValue, - camelValue, - upperUnderscoreValue, - pascalUpperAcronymsValue, - camelUpperAcronymsValue - }), - enumeratorNamingStyle: new EnumOption("enumerator-style", "Naming style for enumerators", { - upperUnderscoreValue, - underscoreValue, - pascalValue, - camelValue, - pascalUpperAcronymsValue, - camelUpperAcronymsValue - }), + typeNamingStyle: new EnumOption("type-style", "Naming style for types", namingStyles), + memberNamingStyle: new EnumOption("member-style", "Naming style for members", namingStyles), + enumeratorNamingStyle: new EnumOption("enumerator-style", "Naming style for enumerators", namingStyles), boost: new BooleanOption("boost", "Require a dependency on boost. Without boost, C++17 is required", true), hideNullOptional: new BooleanOption("hide-null-optional", "Hide null value for optional field", false) }; From 288feb4b9dcca7b41ce39e7bbb0a4dc8893b8d6c Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Tue, 4 Jun 2024 08:46:37 -0700 Subject: [PATCH 78/94] use LanguageOptions in Run --- packages/quicktype-core/src/Run.ts | 14 ++++++-------- packages/quicktype-core/src/TargetLanguage.ts | 19 +++++++++++-------- packages/quicktype-core/src/index.ts | 1 - .../src/language/options.types.ts | 4 ++-- packages/quicktype-core/src/types.ts | 5 +++-- packages/quicktype-vscode/src/extension.ts | 1 - 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/packages/quicktype-core/src/Run.ts b/packages/quicktype-core/src/Run.ts index f4f8770d4..b8f88d67b 100644 --- a/packages/quicktype-core/src/Run.ts +++ b/packages/quicktype-core/src/Run.ts @@ -4,6 +4,8 @@ import { initTypeNames } from "./attributes/TypeNames"; import { gatherNames } from "./GatherNames"; import { InputData } from "./input/Inputs"; import * as targetLanguages from "./language/All"; +import { type LanguageOptionMap } from "./language/options.types"; +import { type LanguageName } from "./language/types"; import { makeTransformations } from "./MakeTransformations"; import { messageError } from "./Messages"; import { combineClasses } from "./rewrites/CombineClasses"; @@ -20,7 +22,7 @@ import { type MultiFileRenderResult, type TargetLanguage } from "./TargetLanguag import { type TransformedStringTypeKind } from "./Type"; import { type StringTypeMapping, TypeBuilder } from "./TypeBuilder"; import { type TypeGraph, noneToAny, optionalToNullable, removeIndirectionIntersections } from "./TypeGraph"; -import { type FixMeOptionsType, type LanguageName } from "./types"; +import { type FixMeOptionsType } from "./types"; export function getTargetLanguage(nameOrInstance: LanguageName | TargetLanguage): TargetLanguage { if (typeof nameOrInstance === "object") { @@ -35,10 +37,6 @@ export function getTargetLanguage(nameOrInstance: LanguageName | TargetLanguage) return messageError("DriverUnknownOutputLanguage", { lang: nameOrInstance }); } -export interface RendererOptions { - [name: string]: string | boolean; -} - export interface InferenceFlag { description: string; explanation: string; @@ -122,7 +120,7 @@ export type InferenceFlags = { [F in InferenceFlagName]: boolean }; * The options type for the main quicktype entry points, * `quicktypeMultiFile` and `quicktype`. */ -export interface NonInferenceOptions { +export interface NonInferenceOptions { /** Make all class property optional */ allPropertiesOptional: boolean; /** Put class properties in alphabetical order, instead of in the order found in the JSON */ @@ -161,7 +159,7 @@ export interface NonInferenceOptions { * or a string specifying one of the names for quicktype's built-in target languages. For example, * both `cs` and `csharp` will generate C#. */ - lang: LanguageName | TargetLanguage; + lang: Lang | TargetLanguage; /** If given, output these comments at the beginning of the main output file */ leadingComments?: Comment[]; /** Don't render output. This is mainly useful for benchmarking. */ @@ -171,7 +169,7 @@ export interface NonInferenceOptions { */ outputFilename: string; /** Options for the target language's renderer */ - rendererOptions: RendererOptions; + rendererOptions: LanguageOptionMap[Lang]; } export type Options = NonInferenceOptions & InferenceFlags; diff --git a/packages/quicktype-core/src/TargetLanguage.ts b/packages/quicktype-core/src/TargetLanguage.ts index 89da85a25..13301bccd 100644 --- a/packages/quicktype-core/src/TargetLanguage.ts +++ b/packages/quicktype-core/src/TargetLanguage.ts @@ -10,7 +10,7 @@ import { defined } from "./support/Support"; import { type Type } from "./Type"; import { type StringTypeMapping } from "./TypeBuilder"; import { type TypeGraph } from "./TypeGraph"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "./types"; +import { type FixMeOptionsType } from "./types"; export type MultiFileRenderResult = ReadonlyMap; @@ -33,16 +33,19 @@ export abstract class TargetLanguage>; + protected abstract getOptions(): Record>; - public get optionDefinitions(): OptionDefinition[] { - return this.getOptions().map(o => o.definition); + public get optionDefinitions(): Array> { + return Object.values(this.getOptions()).map(o => o.definition); } - public get cliOptionDefinitions(): { actual: OptionDefinition[]; display: OptionDefinition[] } { - let actual: OptionDefinition[] = []; - let display: OptionDefinition[] = []; - for (const { cliDefinitions } of this.getOptions()) { + public get cliOptionDefinitions(): { + actual: Array>; + display: Array>; + } { + let actual: Array> = []; + let display: Array> = []; + for (const { cliDefinitions } of Object.values(this.getOptions())) { actual = actual.concat(cliDefinitions.actual); display = display.concat(cliDefinitions.display); } diff --git a/packages/quicktype-core/src/index.ts b/packages/quicktype-core/src/index.ts index 6d41d2d22..df8dff0fa 100644 --- a/packages/quicktype-core/src/index.ts +++ b/packages/quicktype-core/src/index.ts @@ -1,6 +1,5 @@ export { type Options, - type RendererOptions, getTargetLanguage, quicktypeMultiFile, quicktypeMultiFileSync, diff --git a/packages/quicktype-core/src/language/options.types.ts b/packages/quicktype-core/src/language/options.types.ts index 1fb9a8699..ee2013a55 100644 --- a/packages/quicktype-core/src/language/options.types.ts +++ b/packages/quicktype-core/src/language/options.types.ts @@ -1,9 +1,9 @@ import { type OptionMap } from "../RendererOptions"; -import { type LanguageDisplayNameMap } from "./types"; +import { type LanguageNameMap } from "./types"; export type LanguageRawOptionMap = Readonly<{ - [Lang in keyof LanguageDisplayNameMap]: ReturnType; + [Lang in keyof LanguageNameMap]: ReturnType; }>; export type LanguageOptionMap = Readonly<{ diff --git a/packages/quicktype-core/src/types.ts b/packages/quicktype-core/src/types.ts index de3800ca9..5e8269d8c 100644 --- a/packages/quicktype-core/src/types.ts +++ b/packages/quicktype-core/src/types.ts @@ -1,6 +1,7 @@ +export * from "./language/types"; +export * from "./language/options.types"; + // FIXME: remove these when options are strongly typed /* eslint-disable @typescript-eslint/no-explicit-any */ export type FixMeOptionsType = Record; - -export type FixMeOptionsAnyType = any; diff --git a/packages/quicktype-vscode/src/extension.ts b/packages/quicktype-vscode/src/extension.ts index b82f2bcfb..8790128b2 100644 --- a/packages/quicktype-vscode/src/extension.ts +++ b/packages/quicktype-vscode/src/extension.ts @@ -203,7 +203,6 @@ async function pasteAsTypes(editor: vscode.TextEditor, kind: InputKind, justType } } - // @ts-expect-error FIXME: resolve this after above ^ const text = result.lines.join("\n"); const selection = editor.selection; return await editor.edit(builder => { From 96c411fb3582ca589320c908240bd5a5afe58394 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Tue, 4 Jun 2024 08:49:47 -0700 Subject: [PATCH 79/94] readd NoInfer util type --- packages/quicktype-core/src/RendererOptions.ts | 2 +- packages/quicktype-core/src/types.ts | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/quicktype-core/src/RendererOptions.ts b/packages/quicktype-core/src/RendererOptions.ts index 759d82c56..e557d11aa 100644 --- a/packages/quicktype-core/src/RendererOptions.ts +++ b/packages/quicktype-core/src/RendererOptions.ts @@ -1,6 +1,6 @@ import { messageError } from "./Messages"; import { assert } from "./support/Support"; -import { type FixMeOptionsType } from "./types"; +import { type FixMeOptionsType, type NoInfer } from "./types"; /** * Primary options show up in the web UI in the "Language" settings tab, diff --git a/packages/quicktype-core/src/types.ts b/packages/quicktype-core/src/types.ts index 5e8269d8c..22a702b5a 100644 --- a/packages/quicktype-core/src/types.ts +++ b/packages/quicktype-core/src/types.ts @@ -2,6 +2,8 @@ export * from "./language/types"; export * from "./language/options.types"; // FIXME: remove these when options are strongly typed - /* eslint-disable @typescript-eslint/no-explicit-any */ export type FixMeOptionsType = Record; + +// FIXME: Remove this post TS5.4 +export type NoInfer = [T][T extends any ? 0 : never]; From e96ff17cfdeae0568a08d5ef7e4eb8550649652c Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sun, 20 Apr 2025 15:38:46 -0700 Subject: [PATCH 80/94] add LanguageOptions type --- packages/quicktype-core/src/Run.ts | 6 +++--- packages/quicktype-core/src/language/index.ts | 3 ++- packages/quicktype-core/src/language/options.types.ts | 4 +++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/quicktype-core/src/Run.ts b/packages/quicktype-core/src/Run.ts index b8f88d67b..7082186e0 100644 --- a/packages/quicktype-core/src/Run.ts +++ b/packages/quicktype-core/src/Run.ts @@ -4,8 +4,8 @@ import { initTypeNames } from "./attributes/TypeNames"; import { gatherNames } from "./GatherNames"; import { InputData } from "./input/Inputs"; import * as targetLanguages from "./language/All"; -import { type LanguageOptionMap } from "./language/options.types"; -import { type LanguageName } from "./language/types"; +import type { LanguageOptions } from "./language/options.types"; +import type { LanguageName } from "./language/types"; import { makeTransformations } from "./MakeTransformations"; import { messageError } from "./Messages"; import { combineClasses } from "./rewrites/CombineClasses"; @@ -169,7 +169,7 @@ export interface NonInferenceOptions { */ outputFilename: string; /** Options for the target language's renderer */ - rendererOptions: LanguageOptionMap[Lang]; + rendererOptions: LanguageOptions; } export type Options = NonInferenceOptions & InferenceFlags; diff --git a/packages/quicktype-core/src/language/index.ts b/packages/quicktype-core/src/language/index.ts index c9fc2e4e8..cfb4577ef 100644 --- a/packages/quicktype-core/src/language/index.ts +++ b/packages/quicktype-core/src/language/index.ts @@ -26,4 +26,5 @@ export * from "./TypeScriptEffectSchema"; export * from "./TypeScriptZod"; export { all as defaultTargetLanguages, languageNamed, isLanguageName } from "./All"; -export { type LanguageName, type LanguageDisplayName } from "./types"; +export type { LanguageName, LanguageDisplayName } from "./types"; +export type { LanguageOptions } from "./options.types"; diff --git a/packages/quicktype-core/src/language/options.types.ts b/packages/quicktype-core/src/language/options.types.ts index ee2013a55..13a9c21b6 100644 --- a/packages/quicktype-core/src/language/options.types.ts +++ b/packages/quicktype-core/src/language/options.types.ts @@ -1,6 +1,6 @@ import { type OptionMap } from "../RendererOptions"; -import { type LanguageNameMap } from "./types"; +import type { LanguageName, LanguageNameMap } from "./types"; export type LanguageRawOptionMap = Readonly<{ [Lang in keyof LanguageNameMap]: ReturnType; @@ -9,3 +9,5 @@ export type LanguageRawOptionMap = Readonly<{ export type LanguageOptionMap = Readonly<{ [Lang in keyof LanguageRawOptionMap]: OptionMap; }>; + +export type LanguageOptions = LanguageOptionMap[Lang]; From 89946ac1eacaa9ef03ccd5d109ff0a1097afabf9 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sun, 20 Apr 2025 16:13:38 -0700 Subject: [PATCH 81/94] move RendererOptions to own dir --- .../src/{RendererOptions.ts => RendererOptions/index.ts} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename packages/quicktype-core/src/{RendererOptions.ts => RendererOptions/index.ts} (97%) diff --git a/packages/quicktype-core/src/RendererOptions.ts b/packages/quicktype-core/src/RendererOptions/index.ts similarity index 97% rename from packages/quicktype-core/src/RendererOptions.ts rename to packages/quicktype-core/src/RendererOptions/index.ts index e557d11aa..b51302f44 100644 --- a/packages/quicktype-core/src/RendererOptions.ts +++ b/packages/quicktype-core/src/RendererOptions/index.ts @@ -1,6 +1,6 @@ -import { messageError } from "./Messages"; -import { assert } from "./support/Support"; -import { type FixMeOptionsType, type NoInfer } from "./types"; +import { messageError } from "../Messages"; +import { assert } from "../support/Support"; +import { type FixMeOptionsType, type NoInfer } from "../types"; /** * Primary options show up in the web UI in the "Language" settings tab, From 6ab469e8139c80c50e2abcaa514d60a7192237a9 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sun, 20 Apr 2025 16:15:46 -0700 Subject: [PATCH 82/94] move options types to own file --- .../src/RendererOptions/index.ts | 34 ++----------------- .../src/RendererOptions/types.ts | 33 ++++++++++++++++++ 2 files changed, 36 insertions(+), 31 deletions(-) create mode 100644 packages/quicktype-core/src/RendererOptions/types.ts diff --git a/packages/quicktype-core/src/RendererOptions/index.ts b/packages/quicktype-core/src/RendererOptions/index.ts index b51302f44..395683ab8 100644 --- a/packages/quicktype-core/src/RendererOptions/index.ts +++ b/packages/quicktype-core/src/RendererOptions/index.ts @@ -2,25 +2,9 @@ import { messageError } from "../Messages"; import { assert } from "../support/Support"; import { type FixMeOptionsType, type NoInfer } from "../types"; -/** - * Primary options show up in the web UI in the "Language" settings tab, - * secondary options in "Other". - */ -export type OptionKind = "primary" | "secondary"; - -export interface OptionDefinition { - alias?: string; - defaultOption?: boolean; - defaultValue?: T; - description: string; - kind?: OptionKind; - legalValues?: string[]; - multiple?: boolean; - name: Name; - renderer?: boolean; - type: StringConstructor | BooleanConstructor; - typeLabel?: string; -} +import type { OptionDefinition, OptionKind, OptionValues } from "./types"; + +export type * from "./types"; /** * The superclass for target language options. You probably want to use one of its @@ -51,18 +35,6 @@ export abstract class Option { } } -export type OptionKey = O extends Option ? Name : never; -export type OptionValue = - O extends EnumOption - ? EnumMap[EnumKey] - : O extends Option - ? Value - : never; - -// FIXME: Merge these and use camelCase user-facing keys (v24) -export type OptionMap = { [K in keyof T as OptionKey]: OptionValue }; // user-facing, keys are `name` property of Option -export type OptionValues = { [K in keyof T]: OptionValue }; // internal, keys are keys of `_Options` object in each language file - export function getOptionValues>>( options: Options, untypedOptionValues: FixMeOptionsType diff --git a/packages/quicktype-core/src/RendererOptions/types.ts b/packages/quicktype-core/src/RendererOptions/types.ts new file mode 100644 index 000000000..724839880 --- /dev/null +++ b/packages/quicktype-core/src/RendererOptions/types.ts @@ -0,0 +1,33 @@ +import type { EnumOption, Option } from "./index"; + +/** + * Primary options show up in the web UI in the "Language" settings tab, + * secondary options in "Other". + */ +export type OptionKind = "primary" | "secondary"; + +export interface OptionDefinition { + alias?: string; + defaultOption?: boolean; + defaultValue?: T; + description: string; + kind?: OptionKind; + legalValues?: string[]; + multiple?: boolean; + name: Name; + renderer?: boolean; + type: StringConstructor | BooleanConstructor; + typeLabel?: string; +} + +export type OptionKey = O extends Option ? Name : never; +export type OptionValue = + O extends EnumOption + ? EnumMap[EnumKey] + : O extends Option + ? Value + : never; + +// FIXME: Merge these and use camelCase user-facing keys (v24) +export type OptionMap = { [K in keyof T as OptionKey]: OptionValue }; // user-facing, keys are `name` property of Option +export type OptionValues = { [K in keyof T]: OptionValue }; // internal, keys are keys of `_Options` object in each language file From 19ba522db1b2e1bf4f21f4683d981034ef11685d Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sun, 20 Apr 2025 16:20:31 -0700 Subject: [PATCH 83/94] update type of LanguageOptions to reflect input --- packages/quicktype-core/src/RendererOptions/index.ts | 2 +- packages/quicktype-core/src/RendererOptions/types.ts | 4 +++- packages/quicktype-core/src/language/options.types.ts | 6 ++++-- packages/quicktype-vscode/src/extension.ts | 11 ++++++----- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/packages/quicktype-core/src/RendererOptions/index.ts b/packages/quicktype-core/src/RendererOptions/index.ts index 395683ab8..20baa934e 100644 --- a/packages/quicktype-core/src/RendererOptions/index.ts +++ b/packages/quicktype-core/src/RendererOptions/index.ts @@ -4,7 +4,7 @@ import { type FixMeOptionsType, type NoInfer } from "../types"; import type { OptionDefinition, OptionKind, OptionValues } from "./types"; -export type * from "./types"; +export * from "./types"; /** * The superclass for target language options. You probably want to use one of its diff --git a/packages/quicktype-core/src/RendererOptions/types.ts b/packages/quicktype-core/src/RendererOptions/types.ts index 724839880..51eb58b99 100644 --- a/packages/quicktype-core/src/RendererOptions/types.ts +++ b/packages/quicktype-core/src/RendererOptions/types.ts @@ -28,6 +28,8 @@ export type OptionValue = ? Value : never; +export type OptionInput = O extends EnumOption ? EnumKey : O; + // FIXME: Merge these and use camelCase user-facing keys (v24) -export type OptionMap = { [K in keyof T as OptionKey]: OptionValue }; // user-facing, keys are `name` property of Option +export type OptionMap = { [K in keyof T as OptionKey]: OptionInput }; // user-facing, keys are `name` property of Option, values are the available input type export type OptionValues = { [K in keyof T]: OptionValue }; // internal, keys are keys of `_Options` object in each language file diff --git a/packages/quicktype-core/src/language/options.types.ts b/packages/quicktype-core/src/language/options.types.ts index 13a9c21b6..e20e50752 100644 --- a/packages/quicktype-core/src/language/options.types.ts +++ b/packages/quicktype-core/src/language/options.types.ts @@ -1,4 +1,4 @@ -import { type OptionMap } from "../RendererOptions"; +import type { OptionMap } from "../RendererOptions"; import type { LanguageName, LanguageNameMap } from "./types"; @@ -10,4 +10,6 @@ export type LanguageOptionMap = Readonly<{ [Lang in keyof LanguageRawOptionMap]: OptionMap; }>; -export type LanguageOptions = LanguageOptionMap[Lang]; +export type LanguageOptions = { + -readonly [K in keyof Options]: Options[K]; +}; diff --git a/packages/quicktype-vscode/src/extension.ts b/packages/quicktype-vscode/src/extension.ts index 8790128b2..84a268c22 100644 --- a/packages/quicktype-vscode/src/extension.ts +++ b/packages/quicktype-vscode/src/extension.ts @@ -6,7 +6,7 @@ import { InputData, JSONSchemaInput, type Options, - type RendererOptions, + type LanguageOptions, type SerializedRenderResult, type TargetLanguage, defaultTargetLanguages, @@ -99,14 +99,14 @@ async function runQuicktype( const configuration = vscode.workspace.getConfiguration(configurationSection); const justTypes = forceJustTypes || configuration.justTypes; - const rendererOptions: RendererOptions = {}; + const rendererOptions: LanguageOptions = {}; if (justTypes) { // FIXME: The target language should have a property to return these options. if (lang.name === "csharp") { - rendererOptions.features = "just-types"; + (rendererOptions as LanguageOptions<"csharp">).features = "just-types"; } else if (lang.name === "kotlin") { - rendererOptions.framework = "just-types"; - } else { + (rendererOptions as LanguageOptions<"kotlin">).framework = "just-types"; + } else if ("just-types" in rendererOptions) { rendererOptions["just-types"] = "true"; } } @@ -203,6 +203,7 @@ async function pasteAsTypes(editor: vscode.TextEditor, kind: InputKind, justType } } + // @ts-expect-error const text = result.lines.join("\n"); const selection = editor.selection; return await editor.edit(builder => { From 94cfe7de0aff59385f1f45dc8dc578c2f29cf1bc Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sun, 20 Apr 2025 16:31:11 -0700 Subject: [PATCH 84/94] fix types errors in cli script --- .../src/RendererOptions/types.ts | 2 +- src/index.ts | 26 ++++++++++--------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/packages/quicktype-core/src/RendererOptions/types.ts b/packages/quicktype-core/src/RendererOptions/types.ts index 51eb58b99..0a1d3a88c 100644 --- a/packages/quicktype-core/src/RendererOptions/types.ts +++ b/packages/quicktype-core/src/RendererOptions/types.ts @@ -6,7 +6,7 @@ import type { EnumOption, Option } from "./index"; */ export type OptionKind = "primary" | "secondary"; -export interface OptionDefinition { +export interface OptionDefinition { alias?: string; defaultOption?: boolean; defaultValue?: T; diff --git a/src/index.ts b/src/index.ts index ea0b74b68..23a0d9809 100644 --- a/src/index.ts +++ b/src/index.ts @@ -19,7 +19,7 @@ import { type LanguageName, type OptionDefinition, type Options, - type RendererOptions, + type LanguageOptions, type SerializedRenderResult, type TargetLanguage, assert, @@ -60,7 +60,7 @@ const packageJSON = require("../package.json"); const wordWrap: (s: string) => string = _wordwrap(90); -export interface CLIOptions { +export interface CLIOptions { // We use this to access the inference flags // eslint-disable-next-line @typescript-eslint/no-explicit-any [option: string]: any; @@ -74,13 +74,13 @@ export interface CLIOptions { help: boolean; httpHeader?: string[]; httpMethod?: string; - lang: LanguageName; + lang: Lang; noRender: boolean; out?: string; quiet: boolean; - rendererOptions: RendererOptions; + rendererOptions: LanguageOptions; src: string[]; srcLang: string; @@ -617,14 +617,16 @@ function parseOptions(definitions: OptionDefinition[], argv: string[], partial: } } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const options: { [key: string]: any; rendererOptions: RendererOptions } = { rendererOptions: {} }; - for (const o of definitions) { - if (!hasOwnProperty(opts, o.name)) continue; - const v = opts[o.name] as string; - if (o.renderer !== undefined) options.rendererOptions[o.name] = v; - else { - const k = _.lowerFirst(o.name.split("-").map(_.upperFirst).join("")); + const options: { [key: string]: unknown; rendererOptions: LanguageOptions } = { rendererOptions: {} }; + for (const optionDefinition of definitions) { + if (!hasOwnProperty(opts, optionDefinition.name)) { + continue; + } + const v = opts[optionDefinition.name] as string; + if (optionDefinition.renderer !== undefined && optionDefinition.name in options.rendererOptions) { + (options.rendererOptions as Record)[optionDefinition.name] = v; + } else { + const k = _.lowerFirst(optionDefinition.name.split("-").map(_.upperFirst).join("")); options[k] = v; } } From d7098e78d7316b948cc21ed5f709955e40ab2ded Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sun, 20 Apr 2025 16:37:19 -0700 Subject: [PATCH 85/94] rename back to RendererOptions --- packages/quicktype-core/src/Run.ts | 4 ++-- packages/quicktype-core/src/language/index.ts | 2 +- .../quicktype-core/src/language/options.types.ts | 2 +- packages/quicktype-vscode/src/extension.ts | 8 ++++---- src/index.ts | 13 +++++++------ test/languages.ts | 4 ++-- 6 files changed, 17 insertions(+), 16 deletions(-) diff --git a/packages/quicktype-core/src/Run.ts b/packages/quicktype-core/src/Run.ts index 7082186e0..e05efe5c6 100644 --- a/packages/quicktype-core/src/Run.ts +++ b/packages/quicktype-core/src/Run.ts @@ -4,7 +4,7 @@ import { initTypeNames } from "./attributes/TypeNames"; import { gatherNames } from "./GatherNames"; import { InputData } from "./input/Inputs"; import * as targetLanguages from "./language/All"; -import type { LanguageOptions } from "./language/options.types"; +import type { RendererOptions } from "./language/options.types"; import type { LanguageName } from "./language/types"; import { makeTransformations } from "./MakeTransformations"; import { messageError } from "./Messages"; @@ -169,7 +169,7 @@ export interface NonInferenceOptions { */ outputFilename: string; /** Options for the target language's renderer */ - rendererOptions: LanguageOptions; + rendererOptions: RendererOptions; } export type Options = NonInferenceOptions & InferenceFlags; diff --git a/packages/quicktype-core/src/language/index.ts b/packages/quicktype-core/src/language/index.ts index cfb4577ef..ee9515c3b 100644 --- a/packages/quicktype-core/src/language/index.ts +++ b/packages/quicktype-core/src/language/index.ts @@ -27,4 +27,4 @@ export * from "./TypeScriptZod"; export { all as defaultTargetLanguages, languageNamed, isLanguageName } from "./All"; export type { LanguageName, LanguageDisplayName } from "./types"; -export type { LanguageOptions } from "./options.types"; +export type { RendererOptions } from "./options.types"; diff --git a/packages/quicktype-core/src/language/options.types.ts b/packages/quicktype-core/src/language/options.types.ts index e20e50752..c0addc16a 100644 --- a/packages/quicktype-core/src/language/options.types.ts +++ b/packages/quicktype-core/src/language/options.types.ts @@ -10,6 +10,6 @@ export type LanguageOptionMap = Readonly<{ [Lang in keyof LanguageRawOptionMap]: OptionMap; }>; -export type LanguageOptions = { +export type RendererOptions = { -readonly [K in keyof Options]: Options[K]; }; diff --git a/packages/quicktype-vscode/src/extension.ts b/packages/quicktype-vscode/src/extension.ts index 84a268c22..fecc619aa 100644 --- a/packages/quicktype-vscode/src/extension.ts +++ b/packages/quicktype-vscode/src/extension.ts @@ -6,7 +6,7 @@ import { InputData, JSONSchemaInput, type Options, - type LanguageOptions, + type RendererOptions, type SerializedRenderResult, type TargetLanguage, defaultTargetLanguages, @@ -99,13 +99,13 @@ async function runQuicktype( const configuration = vscode.workspace.getConfiguration(configurationSection); const justTypes = forceJustTypes || configuration.justTypes; - const rendererOptions: LanguageOptions = {}; + const rendererOptions: RendererOptions = {}; if (justTypes) { // FIXME: The target language should have a property to return these options. if (lang.name === "csharp") { - (rendererOptions as LanguageOptions<"csharp">).features = "just-types"; + (rendererOptions as RendererOptions<"csharp">).features = "just-types"; } else if (lang.name === "kotlin") { - (rendererOptions as LanguageOptions<"kotlin">).framework = "just-types"; + (rendererOptions as RendererOptions<"kotlin">).framework = "just-types"; } else if ("just-types" in rendererOptions) { rendererOptions["just-types"] = "true"; } diff --git a/src/index.ts b/src/index.ts index 23a0d9809..38a68677c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,6 +9,10 @@ import { definedMap, hasOwnProperty, mapFromObject, mapMap, withDefault } from " import commandLineArgs from "command-line-args"; import getUsage from "command-line-usage"; import * as _ from "lodash"; +import { type Readable } from "readable-stream"; +import stringToStream from "string-to-stream"; +import _wordwrap from "wordwrap"; + import { FetchingJSONSchemaStore, InputData, @@ -19,7 +23,7 @@ import { type LanguageName, type OptionDefinition, type Options, - type LanguageOptions, + type RendererOptions, type SerializedRenderResult, type TargetLanguage, assert, @@ -46,9 +50,6 @@ import { } from "quicktype-core"; import { GraphQLInput } from "quicktype-graphql-input"; import { schemaForTypeScriptSources } from "quicktype-typescript-input"; -import { type Readable } from "readable-stream"; -import stringToStream from "string-to-stream"; -import _wordwrap from "wordwrap"; import { CompressedJSONFromStream } from "./CompressedJSONFromStream"; import { introspectServer } from "./GraphQLIntrospection"; @@ -80,7 +81,7 @@ export interface CLIOptions { out?: string; quiet: boolean; - rendererOptions: LanguageOptions; + rendererOptions: RendererOptions; src: string[]; srcLang: string; @@ -617,7 +618,7 @@ function parseOptions(definitions: OptionDefinition[], argv: string[], partial: } } - const options: { [key: string]: unknown; rendererOptions: LanguageOptions } = { rendererOptions: {} }; + const options: { [key: string]: unknown; rendererOptions: RendererOptions } = { rendererOptions: {} }; for (const optionDefinition of definitions) { if (!hasOwnProperty(opts, optionDefinition.name)) { continue; diff --git a/test/languages.ts b/test/languages.ts index 82f3520ec..95d3e3ea7 100644 --- a/test/languages.ts +++ b/test/languages.ts @@ -96,7 +96,7 @@ export const CSharpLanguageSystemTextJson: Language = { skipSchema: [ "top-level-enum.schema" // The code we generate for top-level enums is incompatible with the driver ], - rendererOptions: { "check-required": "true", framework: "SystemTextJson" }, + rendererOptions: { "check-required": "true", "framework": "SystemTextJson" }, quickTestRendererOptions: [ { "array-type": "list" }, { "csharp-version": "6" }, @@ -149,7 +149,7 @@ export const JavaLanguageWithLegacyDateTime: Language = { export const JavaLanguageWithLombok: Language = { ...JavaLanguage, base: "test/fixtures/java-lombok", - quickTestRendererOptions: [{ "array-type": "list", lombok: "true" }] + quickTestRendererOptions: [{ "array-type": "list", "lombok": "true" }] }; export const PythonLanguage: Language = { From a84cba7e94821e4211917fa236b5f6495877ea59 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Thu, 24 Apr 2025 08:17:14 -0700 Subject: [PATCH 86/94] fix type error for fixtures.ts --- test/fixtures.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/fixtures.ts b/test/fixtures.ts index 57dc97ade..d8279f864 100644 --- a/test/fixtures.ts +++ b/test/fixtures.ts @@ -23,7 +23,7 @@ import { callAndExpectFailure } from "./utils"; import * as languages from "./languages"; -import { type LanguageName, RendererOptions } from "quicktype-core"; +import type { LanguageName, Option, RendererOptions } from "quicktype-core"; import { mustNotHappen, defined } from "../packages/quicktype-core/dist/support/Support"; import { DefaultDateTimeRecognizer } from "../packages/quicktype-core/dist/DateTime"; @@ -80,8 +80,11 @@ function additionalTestFiles(base: string, extension: string, features: string[] function runEnvForLanguage(additionalRendererOptions: RendererOptions): NodeJS.ProcessEnv { const newEnv = Object.assign({}, process.env); - for (const o of Object.getOwnPropertyNames(additionalRendererOptions)) { - newEnv["QUICKTYPE_" + o.toUpperCase().replace("-", "_")] = additionalRendererOptions[o].toString(); + + for (const option of Object.keys(additionalRendererOptions)) { + newEnv["QUICKTYPE_" + option.toUpperCase().replace("-", "_")] = ( + additionalRendererOptions[option as keyof typeof additionalRendererOptions] as Option + ).name; } return newEnv; } From 169c9827d247b090d727cfdbbaab5aff3b6848fa Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Thu, 24 Apr 2025 23:33:22 -0700 Subject: [PATCH 87/94] update messageError --- packages/quicktype-core/src/Messages.ts | 33 ++++++++++++------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/packages/quicktype-core/src/Messages.ts b/packages/quicktype-core/src/Messages.ts index 0c945480a..28407960a 100644 --- a/packages/quicktype-core/src/Messages.ts +++ b/packages/quicktype-core/src/Messages.ts @@ -80,7 +80,7 @@ export type ErrorProperties = // TypeScript input | { kind: "TypeScriptCompilerError"; properties: { message: string } }; -export type ErrorKinds = ErrorProperties extends { kind: infer K } ? K : never; +export type ErrorKinds = ErrorProperties["kind"]; type ErrorMessages = { readonly [K in ErrorKinds]: string }; @@ -165,7 +165,7 @@ const errorMessages: ErrorMessages = { TypeScriptCompilerError: "TypeScript error: ${message}" }; -export type ErrorPropertiesForName = +export type ErrorPropertiesForKind = Extract extends { properties: infer P } ? P : never; export class QuickTypeError extends Error { @@ -179,31 +179,30 @@ export class QuickTypeError extends Error { } } -export function messageError(kind: N, properties: ErrorPropertiesForName): never { +export function messageError(kind: Kind, properties: ErrorPropertiesForKind): never { const message = errorMessages[kind]; let userMessage: string = message; - const propertiesMap = properties as StringMap; - - for (const name of Object.getOwnPropertyNames(propertiesMap)) { - let value = propertiesMap[name]; - if (typeof value === "object" && typeof value.toString === "function") { - value = value.toString(); - } else if (typeof value.message === "string") { - value = value.message; + + for (const [name, value] of Object.entries(properties as StringMap)) { + let valueString = ""; + if (typeof value === "object" && typeof value?.toString === "function") { + valueString = value.toString(); + } else if (typeof value?.message === "string") { + valueString = value.message; } else if (typeof value !== "string") { - value = JSON.stringify(value); + valueString = JSON.stringify(value); } - userMessage = userMessage.replace("${" + name + "}", value); + userMessage = userMessage.replace("${" + name + "}", valueString); } - throw new QuickTypeError(message, kind, userMessage, propertiesMap); + throw new QuickTypeError(message, kind, userMessage, properties as StringMap); } -export function messageAssert( +export function messageAssert( assertion: boolean, - kind: N, - properties: ErrorPropertiesForName + kind: Kind, + properties: ErrorPropertiesForKind ): void { if (assertion) return; return messageError(kind, properties); From 3687e7c98a3de0303d3554bc51a3d263f97661df Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Fri, 25 Apr 2025 10:36:25 -0700 Subject: [PATCH 88/94] update getOptionValues to use name instead of key --- packages/quicktype-core/src/RendererOptions/index.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/quicktype-core/src/RendererOptions/index.ts b/packages/quicktype-core/src/RendererOptions/index.ts index 20baa934e..3d88c5587 100644 --- a/packages/quicktype-core/src/RendererOptions/index.ts +++ b/packages/quicktype-core/src/RendererOptions/index.ts @@ -40,13 +40,13 @@ export function getOptionValues { const optionValues: FixMeOptionsType = {}; - for (const name of Object.keys(options)) { - const option = options[name]; + + for (const [key, option] of Object.entries(options)) { const value = option.getValue(untypedOptionValues); if (option instanceof EnumOption) { - optionValues[name] = option.getEnumValue(value as string); + optionValues[key] = option.getEnumValue(value as string); } else { - optionValues[name] = value; + optionValues[key] = value; } } From 855326a7be716ebdac440df24eee5f4bea6785a8 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 26 Apr 2025 22:41:53 -0700 Subject: [PATCH 89/94] require defaults for EnumOptions --- .../src/RendererOptions/index.ts | 7 +++- .../src/language/CJSON/language.ts | 11 ++++-- .../src/language/CPlusPlus/language.ts | 11 ++++-- .../src/language/CSharp/language.ts | 30 ++++++++++------ .../src/language/Elm/language.ts | 13 ++++--- .../src/language/Haskell/language.ts | 13 ++++--- .../src/language/Objective-C/language.ts | 15 +++++--- .../src/language/Ruby/language.ts | 15 +++++--- .../src/language/Rust/language.ts | 36 ++++++++++++------- .../src/language/Scala3/language.ts | 2 +- .../src/language/Smithy4s/language.ts | 2 +- .../src/language/Swift/language.ts | 13 ++++--- 12 files changed, 114 insertions(+), 54 deletions(-) diff --git a/packages/quicktype-core/src/RendererOptions/index.ts b/packages/quicktype-core/src/RendererOptions/index.ts index 3d88c5587..dc84cfc7d 100644 --- a/packages/quicktype-core/src/RendererOptions/index.ts +++ b/packages/quicktype-core/src/RendererOptions/index.ts @@ -148,7 +148,7 @@ export class EnumOption< name: Name, description: string, values: EnumMap, - defaultValue?: NoInfer, + defaultValue: NoInfer, kind: OptionKind = "primary" ) { const definition = { @@ -165,6 +165,11 @@ export class EnumOption< } public getEnumValue(name: Key): EnumMap[Key] { + if (!name) { + const defaultKey = this.definition.defaultValue as NonNullable; + return this._values[defaultKey]; + } + if (!(name in this._values)) { return messageError("RendererUnknownOptionValue", { value: name, name: this.name }); } diff --git a/packages/quicktype-core/src/language/CJSON/language.ts b/packages/quicktype-core/src/language/CJSON/language.ts index 14add3530..29602d0ac 100644 --- a/packages/quicktype-core/src/language/CJSON/language.ts +++ b/packages/quicktype-core/src/language/CJSON/language.ts @@ -88,9 +88,14 @@ export const cJSONOptions = { "print-formatted", "secondary" ), - typeNamingStyle: new EnumOption("type-style", "Naming style for types", namingStyles), - memberNamingStyle: new EnumOption("member-style", "Naming style for members", namingStyles), - enumeratorNamingStyle: new EnumOption("enumerator-style", "Naming style for enumerators", namingStyles) + typeNamingStyle: new EnumOption("type-style", "Naming style for types", namingStyles, "pascal-case"), + memberNamingStyle: new EnumOption("member-style", "Naming style for members", namingStyles, "pascal-case"), + enumeratorNamingStyle: new EnumOption( + "enumerator-style", + "Naming style for enumerators", + namingStyles, + "pascal-case" + ) }; /* cJSON generator target language */ diff --git a/packages/quicktype-core/src/language/CPlusPlus/language.ts b/packages/quicktype-core/src/language/CPlusPlus/language.ts index 1def52fc0..21dfba94b 100644 --- a/packages/quicktype-core/src/language/CPlusPlus/language.ts +++ b/packages/quicktype-core/src/language/CPlusPlus/language.ts @@ -66,9 +66,14 @@ export const cPlusPlusOptions = { justTypes: new BooleanOption("just-types", "Plain types only", false), namespace: new StringOption("namespace", "Name of the generated namespace(s)", "NAME", "quicktype"), enumType: new StringOption("enum-type", "Type of enum class", "NAME", "int", "secondary"), - typeNamingStyle: new EnumOption("type-style", "Naming style for types", namingStyles), - memberNamingStyle: new EnumOption("member-style", "Naming style for members", namingStyles), - enumeratorNamingStyle: new EnumOption("enumerator-style", "Naming style for enumerators", namingStyles), + typeNamingStyle: new EnumOption("type-style", "Naming style for types", namingStyles, "pascal-case"), + memberNamingStyle: new EnumOption("member-style", "Naming style for members", namingStyles, "pascal-case"), + enumeratorNamingStyle: new EnumOption( + "enumerator-style", + "Naming style for enumerators", + namingStyles, + "pascal-case" + ), boost: new BooleanOption("boost", "Require a dependency on boost. Without boost, C++17 is required", true), hideNullOptional: new BooleanOption("hide-null-optional", "Hide null value for optional field", false) }; diff --git a/packages/quicktype-core/src/language/CSharp/language.ts b/packages/quicktype-core/src/language/CSharp/language.ts index d102211ce..293dc101d 100644 --- a/packages/quicktype-core/src/language/CSharp/language.ts +++ b/packages/quicktype-core/src/language/CSharp/language.ts @@ -28,10 +28,15 @@ export const cSharpOptions = { } as const, "NewtonSoft" ), - useList: new EnumOption("array-type", "Use T[] or List", { - array: false, - list: true - }), + useList: new EnumOption( + "array-type", + "Use T[] or List", + { + array: false, + list: true + }, + "array" + ), dense: new EnumOption( "density", "Property density", @@ -75,12 +80,17 @@ export const cSharpOptions = { "double", "secondary" ), - features: new EnumOption("features", "Output features", { - "complete": { namespaces: true, helpers: true, attributes: true }, - "attributes-only": { namespaces: true, helpers: false, attributes: true }, - "just-types-and-namespace": { namespaces: true, helpers: false, attributes: false }, - "just-types": { namespaces: true, helpers: false, attributes: false } - } as const), + features: new EnumOption( + "features", + "Output features", + { + "complete": { namespaces: true, helpers: true, attributes: true }, + "attributes-only": { namespaces: true, helpers: false, attributes: true }, + "just-types-and-namespace": { namespaces: true, helpers: false, attributes: false }, + "just-types": { namespaces: true, helpers: false, attributes: false } + } as const, + "complete" + ), baseclass: new EnumOption( "base-class", "Base class", diff --git a/packages/quicktype-core/src/language/Elm/language.ts b/packages/quicktype-core/src/language/Elm/language.ts index 2725c798b..d77d3b332 100644 --- a/packages/quicktype-core/src/language/Elm/language.ts +++ b/packages/quicktype-core/src/language/Elm/language.ts @@ -7,10 +7,15 @@ import { ElmRenderer } from "./ElmRenderer"; export const elmOptions = { justTypes: new BooleanOption("just-types", "Plain types only", false), - useList: new EnumOption("array-type", "Use Array or List", { - array: false, - list: true - } as const), + useList: new EnumOption( + "array-type", + "Use Array or List", + { + array: false, + list: true + } as const, + "array" + ), // FIXME: Do this via a configurable named eventually. moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType") }; diff --git a/packages/quicktype-core/src/language/Haskell/language.ts b/packages/quicktype-core/src/language/Haskell/language.ts index a7b937fd0..e7c35f9cf 100644 --- a/packages/quicktype-core/src/language/Haskell/language.ts +++ b/packages/quicktype-core/src/language/Haskell/language.ts @@ -7,10 +7,15 @@ import { HaskellRenderer } from "./HaskellRenderer"; export const haskellOptions = { justTypes: new BooleanOption("just-types", "Plain types only", false), - useList: new EnumOption("array-type", "Use Array or List", { - array: false, - list: true - } as const), + useList: new EnumOption( + "array-type", + "Use Array or List", + { + array: false, + list: true + } as const, + "array" + ), moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType") }; diff --git a/packages/quicktype-core/src/language/Objective-C/language.ts b/packages/quicktype-core/src/language/Objective-C/language.ts index 13e639a04..a8b8b88ad 100644 --- a/packages/quicktype-core/src/language/Objective-C/language.ts +++ b/packages/quicktype-core/src/language/Objective-C/language.ts @@ -7,11 +7,16 @@ import { ObjectiveCRenderer } from "./ObjectiveCRenderer"; import { DEFAULT_CLASS_PREFIX } from "./utils"; export const objectiveCOptions = { - features: new EnumOption("features", "Interface and implementation", { - all: { interface: true, implementation: true }, - interface: { interface: true, implementation: false }, - implementation: { interface: false, implementation: true } - } as const), + features: new EnumOption( + "features", + "Interface and implementation", + { + all: { interface: true, implementation: true }, + interface: { interface: true, implementation: false }, + implementation: { interface: false, implementation: true } + } as const, + "all" + ), justTypes: new BooleanOption("just-types", "Plain types only", false), marshallingFunctions: new BooleanOption("functions", "C-style functions", false), classPrefix: new StringOption("class-prefix", "Class prefix", "PREFIX", DEFAULT_CLASS_PREFIX), diff --git a/packages/quicktype-core/src/language/Ruby/language.ts b/packages/quicktype-core/src/language/Ruby/language.ts index b2e63ccb3..e96c0109c 100644 --- a/packages/quicktype-core/src/language/Ruby/language.ts +++ b/packages/quicktype-core/src/language/Ruby/language.ts @@ -8,11 +8,16 @@ import { Strictness } from "./utils"; export const rubyOptions = { justTypes: new BooleanOption("just-types", "Plain types only", false), - strictness: new EnumOption("strictness", "Type strictness", { - strict: Strictness.Strict, - coercible: Strictness.Coercible, - none: Strictness.None - } as const), + strictness: new EnumOption( + "strictness", + "Type strictness", + { + strict: Strictness.Strict, + coercible: Strictness.Coercible, + none: Strictness.None + } as const, + "strict" + ), namespace: new StringOption("namespace", "Specify a wrapping Namespace", "NAME", "", "secondary") }; diff --git a/packages/quicktype-core/src/language/Rust/language.ts b/packages/quicktype-core/src/language/Rust/language.ts index 29f7a92d3..ac61b6fca 100644 --- a/packages/quicktype-core/src/language/Rust/language.ts +++ b/packages/quicktype-core/src/language/Rust/language.ts @@ -7,15 +7,25 @@ import { RustRenderer } from "./RustRenderer"; import { Density, Visibility } from "./utils"; export const rustOptions = { - density: new EnumOption("density", "Density", { - normal: Density.Normal, - dense: Density.Dense - } as const), - visibility: new EnumOption("visibility", "Field visibility", { - private: Visibility.Private, - crate: Visibility.Crate, - public: Visibility.Public - } as const), + density: new EnumOption( + "density", + "Density", + { + normal: Density.Normal, + dense: Density.Dense + } as const, + "normal" + ), + visibility: new EnumOption( + "visibility", + "Field visibility", + { + private: Visibility.Private, + crate: Visibility.Crate, + public: Visibility.Public + } as const, + "private" + ), deriveDebug: new BooleanOption("derive-debug", "Derive Debug impl", false), deriveClone: new BooleanOption("derive-clone", "Derive Clone impl", false), derivePartialEq: new BooleanOption("derive-partial-eq", "Derive PartialEq impl", false), @@ -35,11 +45,11 @@ export class RustTargetLanguage extends TargetLanguage Date: Sat, 26 Apr 2025 23:11:19 -0700 Subject: [PATCH 90/94] rename options types --- packages/quicktype-core/src/RendererOptions/types.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/quicktype-core/src/RendererOptions/types.ts b/packages/quicktype-core/src/RendererOptions/types.ts index 0a1d3a88c..273a754d2 100644 --- a/packages/quicktype-core/src/RendererOptions/types.ts +++ b/packages/quicktype-core/src/RendererOptions/types.ts @@ -20,7 +20,7 @@ export interface OptionDefinition { typeLabel?: string; } -export type OptionKey = O extends Option ? Name : never; +export type OptionName = O extends Option ? Name : never; export type OptionValue = O extends EnumOption ? EnumMap[EnumKey] @@ -28,8 +28,8 @@ export type OptionValue = ? Value : never; -export type OptionInput = O extends EnumOption ? EnumKey : O; +export type OptionKey = O extends EnumOption, infer EnumKey> ? EnumKey : O; // FIXME: Merge these and use camelCase user-facing keys (v24) -export type OptionMap = { [K in keyof T as OptionKey]: OptionInput }; // user-facing, keys are `name` property of Option, values are the available input type +export type OptionMap = { [K in keyof T as OptionName]: OptionKey }; // user-facing, keys are `name` property of Option, values are the available input type export type OptionValues = { [K in keyof T]: OptionValue }; // internal, keys are keys of `_Options` object in each language file From b5540bbf2ff6925bea7944faf1fc028d7b4f4e7c Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 26 Apr 2025 23:19:20 -0700 Subject: [PATCH 91/94] remove unused members of OptionDefinition --- packages/quicktype-core/src/RendererOptions/index.ts | 1 - packages/quicktype-core/src/RendererOptions/types.ts | 2 -- src/index.ts | 2 +- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/quicktype-core/src/RendererOptions/index.ts b/packages/quicktype-core/src/RendererOptions/index.ts index dc84cfc7d..c8a9f66e9 100644 --- a/packages/quicktype-core/src/RendererOptions/index.ts +++ b/packages/quicktype-core/src/RendererOptions/index.ts @@ -14,7 +14,6 @@ export abstract class Option { public readonly definition: OptionDefinition; public constructor(definition: OptionDefinition) { - definition.renderer = true; this.definition = definition; assert(definition.kind !== undefined, "Renderer option kind must be defined"); } diff --git a/packages/quicktype-core/src/RendererOptions/types.ts b/packages/quicktype-core/src/RendererOptions/types.ts index 273a754d2..cdca12570 100644 --- a/packages/quicktype-core/src/RendererOptions/types.ts +++ b/packages/quicktype-core/src/RendererOptions/types.ts @@ -12,10 +12,8 @@ export interface OptionDefinition { defaultValue?: T; description: string; kind?: OptionKind; - legalValues?: string[]; multiple?: boolean; name: Name; - renderer?: boolean; type: StringConstructor | BooleanConstructor; typeLabel?: string; } diff --git a/src/index.ts b/src/index.ts index 38a68677c..ad9f3d82b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -624,7 +624,7 @@ function parseOptions(definitions: OptionDefinition[], argv: string[], partial: continue; } const v = opts[optionDefinition.name] as string; - if (optionDefinition.renderer !== undefined && optionDefinition.name in options.rendererOptions) { + if (optionDefinition.name in options.rendererOptions) { (options.rendererOptions as Record)[optionDefinition.name] = v; } else { const k = _.lowerFirst(optionDefinition.name.split("-").map(_.upperFirst).join("")); From bb1ee9b705c71f7b51d8e78bd2af6a236d680365 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sat, 26 Apr 2025 23:22:51 -0700 Subject: [PATCH 92/94] temp skip swift --- .github/workflows/test-pr.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-pr.yaml b/.github/workflows/test-pr.yaml index b18612a7c..1532ae4a5 100644 --- a/.github/workflows/test-pr.yaml +++ b/.github/workflows/test-pr.yaml @@ -3,7 +3,7 @@ on: pull_request: branches: - master - - 'release/**' + - "release/**" jobs: build: runs-on: ubuntu-22.04 @@ -32,7 +32,7 @@ jobs: - csharp,schema-csharp,schema-json-csharp,graphql-csharp,csharp-SystemTextJson - json-ts-csharp - dart,schema-dart - - swift,schema-swift + # - swift,schema-swift - javascript-prop-types - ruby - php From e4acc527e8905d29fea0213dac7c403b27cc6d64 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sun, 27 Apr 2025 08:45:27 -0700 Subject: [PATCH 93/94] fix defaults for c-based --- packages/quicktype-core/src/language/CJSON/language.ts | 4 ++-- packages/quicktype-core/src/language/CPlusPlus/language.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/quicktype-core/src/language/CJSON/language.ts b/packages/quicktype-core/src/language/CJSON/language.ts index 29602d0ac..7c3854c9c 100644 --- a/packages/quicktype-core/src/language/CJSON/language.ts +++ b/packages/quicktype-core/src/language/CJSON/language.ts @@ -89,12 +89,12 @@ export const cJSONOptions = { "secondary" ), typeNamingStyle: new EnumOption("type-style", "Naming style for types", namingStyles, "pascal-case"), - memberNamingStyle: new EnumOption("member-style", "Naming style for members", namingStyles, "pascal-case"), + memberNamingStyle: new EnumOption("member-style", "Naming style for members", namingStyles, "underscore-case"), enumeratorNamingStyle: new EnumOption( "enumerator-style", "Naming style for enumerators", namingStyles, - "pascal-case" + "upper-underscore-case" ) }; diff --git a/packages/quicktype-core/src/language/CPlusPlus/language.ts b/packages/quicktype-core/src/language/CPlusPlus/language.ts index 21dfba94b..730d5750e 100644 --- a/packages/quicktype-core/src/language/CPlusPlus/language.ts +++ b/packages/quicktype-core/src/language/CPlusPlus/language.ts @@ -67,12 +67,12 @@ export const cPlusPlusOptions = { namespace: new StringOption("namespace", "Name of the generated namespace(s)", "NAME", "quicktype"), enumType: new StringOption("enum-type", "Type of enum class", "NAME", "int", "secondary"), typeNamingStyle: new EnumOption("type-style", "Naming style for types", namingStyles, "pascal-case"), - memberNamingStyle: new EnumOption("member-style", "Naming style for members", namingStyles, "pascal-case"), + memberNamingStyle: new EnumOption("member-style", "Naming style for members", namingStyles, "underscore-case"), enumeratorNamingStyle: new EnumOption( "enumerator-style", "Naming style for enumerators", namingStyles, - "pascal-case" + "upper-underscore-case" ), boost: new BooleanOption("boost", "Require a dependency on boost. Without boost, C++17 is required", true), hideNullOptional: new BooleanOption("hide-null-optional", "Hide null value for optional field", false) From c34b526147643f90df8d44b544ece03c11e9cdf6 Mon Sep 17 00:00:00 2001 From: inferrinizzard Date: Sun, 27 Apr 2025 09:04:31 -0700 Subject: [PATCH 94/94] revert swift --- .github/workflows/test-pr.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-pr.yaml b/.github/workflows/test-pr.yaml index 1532ae4a5..dc8526afe 100644 --- a/.github/workflows/test-pr.yaml +++ b/.github/workflows/test-pr.yaml @@ -32,7 +32,7 @@ jobs: - csharp,schema-csharp,schema-json-csharp,graphql-csharp,csharp-SystemTextJson - json-ts-csharp - dart,schema-dart - # - swift,schema-swift + - swift,schema-swift - javascript-prop-types - ruby - php