diff --git a/.github/workflows/test-pr.yaml b/.github/workflows/test-pr.yaml index b18612a7c..dc8526afe 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 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/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/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); diff --git a/packages/quicktype-core/src/RendererOptions.ts b/packages/quicktype-core/src/RendererOptions.ts deleted file mode 100644 index 77f95c228..000000000 --- a/packages/quicktype-core/src/RendererOptions.ts +++ /dev/null @@ -1,193 +0,0 @@ -// 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"; - -/** - * 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?: FixMeOptionsAnyType; - description: string; - kind?: OptionKind; - legalValues?: string[]; - multiple?: boolean; - name: string; - renderer?: boolean; - type: StringConstructor | BooleanConstructor; - typeLabel?: string; -} - -/** - * The superclass for target language options. You probably want to use one of its - * subclasses, `BooleanOption`, `EnumOption`, or `StringOption`. - */ -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"); - } - - public getValue(values: FixMeOptionsType): T { - const value = values[this.definition.name]; - if (value === undefined) { - return this.definition.defaultValue; - } - - return value; - } - - public get cliDefinitions(): { actual: OptionDefinition[]; display: OptionDefinition[] } { - return { actual: [this.definition], display: [this.definition] }; - } -} - -export type OptionValueType = O extends Option ? T : never; -export type OptionValues = { [P in keyof T]: OptionValueType }; - -export function getOptionValues }>( - options: T, - untypedOptionValues: FixMeOptionsType -): OptionValues { - const optionValues: FixMeOptionsType = {}; - for (const name of Object.getOwnPropertyNames(options)) { - optionValues[name] = options[name].getValue(untypedOptionValues); - } - - return optionValues as OptionValues; -} - -/** - * A target language option that allows setting a boolean flag. - */ -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. - */ - public constructor(name: string, description: string, defaultValue: boolean, kind: OptionKind = "primary") { - super({ - name, - kind, - type: Boolean, - description, - defaultValue - }); - } - - public get cliDefinitions(): { actual: OptionDefinition[]; display: OptionDefinition[] } { - const negated = Object.assign({}, this.definition, { - name: `no-${this.definition.name}`, - 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)` - }); - return { - display: [display], - actual: [this.definition, negated] - }; - } - - public getValue(values: FixMeOptionsType): boolean { - let value = values[this.definition.name]; - if (value === undefined) { - value = this.definition.defaultValue; - } - - let negated = values[`no-${this.definition.name}`]; - if (negated === undefined) { - negated = !this.definition.defaultValue; - } - - if (value === "true") { - value = true; - } else if (value === "false") { - value = false; - } - - if (this.definition.defaultValue) { - return value && !negated; - } else { - return value || !negated; - } - } -} - -export class StringOption extends Option { - public constructor( - name: string, - description: string, - typeLabel: string, - defaultValue: string, - kind: OptionKind = "primary" - ) { - const definition = { - name, - kind, - type: String, - description, - typeLabel, - defaultValue - }; - super(definition); - } -} - -export class EnumOption extends Option { - private readonly _values: { [name: string]: T }; - - public constructor( - name: string, - description: string, - values: Array<[string, T]>, - defaultValue: string | undefined = undefined, - 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), - defaultValue - }; - super(definition); - - this._values = {}; - for (const [n, v] of values) { - this._values[n] = v; - } - } - - public getValue(values: FixMeOptionsType): 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/RendererOptions/index.ts b/packages/quicktype-core/src/RendererOptions/index.ts new file mode 100644 index 000000000..c8a9f66e9 --- /dev/null +++ b/packages/quicktype-core/src/RendererOptions/index.ts @@ -0,0 +1,178 @@ +import { messageError } from "../Messages"; +import { assert } from "../support/Support"; +import { type FixMeOptionsType, type NoInfer } from "../types"; + +import type { OptionDefinition, OptionKind, OptionValues } from "./types"; + +export * from "./types"; + +/** + * The superclass for target language options. You probably want to use one of its + * subclasses, `BooleanOption`, `EnumOption`, or `StringOption`. + */ +export abstract class Option { + public readonly definition: OptionDefinition; + + public constructor(definition: OptionDefinition) { + this.definition = definition; + assert(definition.kind !== undefined, "Renderer option kind must be defined"); + } + + public get name(): Name { + return this.definition.name; + } + + public getValue(values: Record): T { + return (values[this.name] ?? this.definition.defaultValue) as T; + } + + public get cliDefinitions(): { + actual: Array>; + display: Array>; + } { + return { actual: [this.definition], display: [this.definition] }; + } +} + +export function getOptionValues>>( + options: Options, + untypedOptionValues: FixMeOptionsType +): OptionValues { + const optionValues: FixMeOptionsType = {}; + + for (const [key, option] of Object.entries(options)) { + const value = option.getValue(untypedOptionValues); + if (option instanceof EnumOption) { + optionValues[key] = option.getEnumValue(value as string); + } else { + optionValues[key] = value; + } + } + + return optionValues as OptionValues; +} + +/** + * A target language option that allows setting a boolean flag. + */ +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. + */ + public constructor(name: Name, description: string, defaultValue: boolean, kind: OptionKind = "primary") { + super({ + name, + kind, + type: Boolean, + description, + defaultValue + }); + } + + public get cliDefinitions(): { + actual: Array>; + display: Array>; + } { + const negated = Object.assign({}, this.definition, { + name: `no-${this.name}`, + defaultValue: !this.definition.defaultValue + }); + const display = Object.assign({}, this.definition, { + name: `[no-]${this.name}`, + description: `${this.definition.description} (${this.definition.defaultValue ? "on" : "off"} by default)` + }); + return { + display: [display], + actual: [this.definition, negated] + }; + } + + public getValue(values: Record): boolean { + let value = values[this.name]; + if (value === undefined) { + value = this.definition.defaultValue; + } + + let negated = values[`no-${this.name}`]; + if (negated === undefined) { + negated = !this.definition.defaultValue; + } + + if (value === "true") { + value = true; + } else if (value === "false") { + value = false; + } + + if (this.definition.defaultValue) { + return (value && !negated) as boolean; + } else { + return (value || !negated) as boolean; + } + } +} + +export class StringOption extends Option { + public constructor( + name: Name, + description: string, + typeLabel: string, + defaultValue: string, + kind: OptionKind = "primary" + ) { + const definition = { + name, + kind, + type: String, + description, + typeLabel, + defaultValue + }; + super(definition); + } +} + +// FIXME: use const generics here +export class EnumOption< + Name extends string, + EnumMap extends Record, + EnumKey extends Extract = Extract +> extends Option { + private readonly _values: EnumMap; + + public constructor( + name: Name, + description: string, + values: EnumMap, + defaultValue: NoInfer, + kind: OptionKind = "primary" + ) { + const definition = { + name, + kind, + type: String, + description, + typeLabel: Object.keys(values).join("|"), + defaultValue + }; + super(definition); + + this._values = values; + } + + 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 }); + } + + return this._values[name]; + } +} diff --git a/packages/quicktype-core/src/RendererOptions/types.ts b/packages/quicktype-core/src/RendererOptions/types.ts new file mode 100644 index 000000000..cdca12570 --- /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; + multiple?: boolean; + name: Name; + type: StringConstructor | BooleanConstructor; + typeLabel?: string; +} + +export type OptionName = O extends Option ? Name : never; +export type OptionValue = + O extends EnumOption + ? EnumMap[EnumKey] + : O extends Option + ? Value + : never; + +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 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 diff --git a/packages/quicktype-core/src/Run.ts b/packages/quicktype-core/src/Run.ts index f4f8770d4..e05efe5c6 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 { RendererOptions } 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: RendererOptions; } export type Options = NonInferenceOptions & InferenceFlags; diff --git a/packages/quicktype-core/src/TargetLanguage.ts b/packages/quicktype-core/src/TargetLanguage.ts index 127a14d80..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 7c2fa1319..53a790253 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, @@ -21,7 +20,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, @@ -83,6 +82,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/All.ts b/packages/quicktype-core/src/language/All.ts index 889457849..637edb373 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"; @@ -24,6 +23,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/CJSON/language.ts b/packages/quicktype-core/src/language/CJSON/language.ts index 6ef2c6607..7c3854c9c 100644 --- a/packages/quicktype-core/src/language/CJSON/language.ts +++ b/packages/quicktype-core/src/language/CJSON/language.ts @@ -22,42 +22,43 @@ */ 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"; /* 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 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 = { 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 +71,31 @@ 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", [ - 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, "pascal-case"), + memberNamingStyle: new EnumOption("member-style", "Naming style for members", namingStyles, "underscore-case"), + enumeratorNamingStyle: new EnumOption( + "enumerator-style", + "Naming style for enumerators", + namingStyles, + "upper-underscore-case" + ) }; /* cJSON generator target language */ @@ -129,17 +114,8 @@ export class CJSONTargetLanguage extends TargetLanguage> { - return [ - cJSONOptions.typeSourceStyle, - cJSONOptions.typeIntegerSize, - cJSONOptions.addTypedefAlias, - cJSONOptions.printStyle, - cJSONOptions.hashtableSize, - cJSONOptions.typeNamingStyle, - cJSONOptions.memberNamingStyle, - cJSONOptions.enumeratorNamingStyle - ]; + public getOptions(): typeof cJSONOptions { + return cJSONOptions; } /** diff --git a/packages/quicktype-core/src/language/CPlusPlus/language.ts b/packages/quicktype-core/src/language/CPlusPlus/language.ts index 248188d3f..730d5750e 100644 --- a/packages/quicktype-core/src/language/CPlusPlus/language.ts +++ b/packages/quicktype-core/src/language/CPlusPlus/language.ts @@ -1,93 +1,79 @@ import { type RenderContext } from "../../Renderer"; -import { BooleanOption, EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions"; -import { type NamingStyle } from "../../support/Strings"; +import { BooleanOption, EnumOption, StringOption, getOptionValues } from "../../RendererOptions"; import { TargetLanguage } from "../../TargetLanguage"; -import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types"; +import { 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"]; +// FIXME: share with CJSON +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( "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" ), includeLocation: new EnumOption( "include-location", "Whether json.hpp is to be located globally or locally", - [ - ["local-include", true], - ["global-include", false] - ], + { + "local-include": true, + "global-include": false + } as const, "local-include", "secondary" ), codeFormat: new EnumOption( "code-format", "Generate classes with getters/setters, instead of structs", - [ - ["with-struct", false], - ["with-getter-setter", true] - ], + { + "with-struct": false, + "with-getter-setter": true + } as const, "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": false, + "use-wstring": true + } as const, "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": true, + "east-const": false + } as const, "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 - ]), + typeNamingStyle: new EnumOption("type-style", "Naming style for types", 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, + "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) }; @@ -103,22 +89,8 @@ export class CPlusPlusTargetLanguage 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 4e9007b44..293dc101d 100644 --- a/packages/quicktype-core/src/language/CSharp/language.ts +++ b/packages/quicktype-core/src/language/CSharp/language.ts @@ -1,22 +1,16 @@ 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"; 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,88 @@ 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 + }, + "array" + ), 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, + "complete" + ), 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, {}); @@ -112,21 +116,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 { @@ -158,13 +149,13 @@ export class CSharpTargetLanguage 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 79e63f863..d77d3b332 100644 --- a/packages/quicktype-core/src/language/Elm/language.ts +++ b/packages/quicktype-core/src/language/Elm/language.ts @@ -1,16 +1,21 @@ 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"; 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] - ]), + 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") }; @@ -26,8 +31,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 2884bcb8d..e7c35f9cf 100644 --- a/packages/quicktype-core/src/language/Haskell/language.ts +++ b/packages/quicktype-core/src/language/Haskell/language.ts @@ -1,16 +1,21 @@ 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"; 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] - ]), + 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") }; @@ -25,8 +30,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 6dc1e9ee0..368757a02 100644 --- a/packages/quicktype-core/src/language/Java/language.ts +++ b/packages/quicktype-core/src/language/Java/language.ts @@ -1,32 +1,21 @@ 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"; export const javaOptions = { - useList: new EnumOption( - "array-type", - "Use T[] or List", - [ - ["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), @@ -47,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 8eb0862e7..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"; @@ -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" ) @@ -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 39a388de7..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"; @@ -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" ) }; @@ -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 55254f807..27d149a3b 100644 --- a/packages/quicktype-core/src/language/Kotlin/language.ts +++ b/packages/quicktype-core/src/language/Kotlin/language.ts @@ -1,33 +1,26 @@ 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"; 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), @@ -45,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 { @@ -61,13 +54,13 @@ export class KotlinTargetLanguage 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 58807c826..5b02fab98 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"; @@ -16,14 +16,14 @@ export interface PythonFeatures { } export const pythonOptions = { - features: new EnumOption( + 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), @@ -38,13 +38,8 @@ export class PythonTargetLanguage extends TargetLanguage> { - return [ - pythonOptions.features, - pythonOptions.justTypes, - pythonOptions.nicePropertyNames, - pythonOptions.pydanticBaseModel - ]; + 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 34f9b4747..e96c0109c 100644 --- a/packages/quicktype-core/src/language/Ruby/language.ts +++ b/packages/quicktype-core/src/language/Ruby/language.ts @@ -1,18 +1,23 @@ 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"; 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, + "strict" + ), namespace: new StringOption("namespace", "Specify a wrapping Namespace", "NAME", "", "secondary") }; @@ -27,8 +32,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 855a28f6b..ac61b6fca 100644 --- a/packages/quicktype-core/src/language/Rust/language.ts +++ b/packages/quicktype-core/src/language/Rust/language.ts @@ -1,28 +1,38 @@ 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, + "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), 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", @@ -35,20 +45,11 @@ export class RustTargetLanguage extends TargetLanguage> { - return [ - rustOptions.density, - rustOptions.visibility, - rustOptions.deriveDebug, - rustOptions.deriveClone, - rustOptions.derivePartialEq, - rustOptions.edition2018, - rustOptions.leadingComments, - rustOptions.skipSerializingNone - ]; + protected makeRenderer(renderContext: RenderContext, untypedOptionValues: FixMeOptionsType): RustRenderer { + return new RustRenderer(this, renderContext, getOptionValues(rustOptions, untypedOptionValues)); } } diff --git a/packages/quicktype-core/src/language/Scala3/language.ts b/packages/quicktype-core/src/language/Scala3/language.ts index ad8b2f87f..519034caf 100644 --- a/packages/quicktype-core/src/language/Scala3/language.ts +++ b/packages/quicktype-core/src/language/Scala3/language.ts @@ -1,30 +1,24 @@ 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 { 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 + { + "just-types": "None", + "circe": "Circe", + "upickle": "Upickle" + } as const, + "just-types" ), packageName: new StringOption("package", "Package", "PACKAGE", "quicktype") }; @@ -40,8 +34,8 @@ export class Scala3TargetLanguage extends TargetLanguage> { - return [scala3Options.framework, scala3Options.packageName]; + public getOptions(): typeof scala3Options { + return scala3Options; } public get supportsOptionalClassProperties(): boolean { @@ -56,11 +50,11 @@ export class Scala3TargetLanguage 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 3419fd9f8..6f10c198d 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"; @@ -23,19 +23,24 @@ export const swiftOptions = { ), 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] - ]), + useClasses: new EnumOption( + "struct-or-class", + "Structs or classes", + { + struct: false, + class: true + } as const, + "struct" + ), 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: true, + normal: false + } as const, "dense", "secondary" ), @@ -56,21 +61,21 @@ export const swiftOptions = { accessLevel: new EnumOption( "access-level", "Access level", - [ - ["internal", "internal"], - ["public", "public"] - ], + { + internal: "internal", + public: "public" + } as const, "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: { equatable: false, hashable: false }, + equatable: { equatable: true, hashable: false }, + hashable: { equatable: false, hashable: true } + } as const, "none", "secondary" ) @@ -87,27 +92,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 { diff --git a/packages/quicktype-core/src/language/index.ts b/packages/quicktype-core/src/language/index.ts index 024a52494..ee9515c3b 100644 --- a/packages/quicktype-core/src/language/index.ts +++ b/packages/quicktype-core/src/language/index.ts @@ -24,3 +24,7 @@ export * from "./Swift"; export * from "./TypeScriptFlow"; export * from "./TypeScriptEffectSchema"; export * from "./TypeScriptZod"; + +export { all as defaultTargetLanguages, languageNamed, isLanguageName } from "./All"; +export type { LanguageName, LanguageDisplayName } from "./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 new file mode 100644 index 000000000..c0addc16a --- /dev/null +++ b/packages/quicktype-core/src/language/options.types.ts @@ -0,0 +1,15 @@ +import type { OptionMap } from "../RendererOptions"; + +import type { LanguageName, LanguageNameMap } from "./types"; + +export type LanguageRawOptionMap = Readonly<{ + [Lang in keyof LanguageNameMap]: ReturnType; +}>; + +export type LanguageOptionMap = Readonly<{ + [Lang in keyof LanguageRawOptionMap]: OptionMap; +}>; + +export type RendererOptions = { + -readonly [K in keyof Options]: Options[K]; +}; 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/support/Acronyms.ts b/packages/quicktype-core/src/support/Acronyms.ts index fa9d29f1b..a5c715408 100644 --- a/packages/quicktype-core/src/support/Acronyms.ts +++ b/packages/quicktype-core/src/support/Acronyms.ts @@ -9,16 +9,16 @@ export enum AcronymStyleOptions { Pascal = "pascal" } -export const acronymOption = function (defaultOption: AcronymStyleOptions): EnumOption { +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" ); diff --git a/packages/quicktype-core/src/types.ts b/packages/quicktype-core/src/types.ts index b276ed93f..22a702b5a 100644 --- a/packages/quicktype-core/src/types.ts +++ b/packages/quicktype-core/src/types.ts @@ -1,21 +1,9 @@ -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; -}; +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; +// FIXME: Remove this post TS5.4 +export type NoInfer = [T][T extends any ? 0 : never]; diff --git a/packages/quicktype-vscode/src/extension.ts b/packages/quicktype-vscode/src/extension.ts index b82f2bcfb..fecc619aa 100644 --- a/packages/quicktype-vscode/src/extension.ts +++ b/packages/quicktype-vscode/src/extension.ts @@ -103,10 +103,10 @@ async function runQuicktype( if (justTypes) { // FIXME: The target language should have a property to return these options. if (lang.name === "csharp") { - rendererOptions.features = "just-types"; + (rendererOptions as RendererOptions<"csharp">).features = "just-types"; } else if (lang.name === "kotlin") { - rendererOptions.framework = "just-types"; - } else { + (rendererOptions as RendererOptions<"kotlin">).framework = "just-types"; + } else if ("just-types" in rendererOptions) { rendererOptions["just-types"] = "true"; } } @@ -203,7 +203,7 @@ async function pasteAsTypes(editor: vscode.TextEditor, kind: InputKind, justType } } - // @ts-expect-error FIXME: resolve this after above ^ + // @ts-expect-error const text = result.lines.join("\n"); const selection = editor.selection; return await editor.edit(builder => { diff --git a/src/index.ts b/src/index.ts index eb9f8f0d4..ad9f3d82b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -61,7 +61,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; @@ -75,13 +75,13 @@ export interface CLIOptions { help: boolean; httpHeader?: string[]; httpMethod?: string; - lang: LanguageName; + lang: Lang; noRender: boolean; out?: string; quiet: boolean; - rendererOptions: RendererOptions; + rendererOptions: RendererOptions; src: string[]; srcLang: string; @@ -618,14 +618,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: RendererOptions } = { rendererOptions: {} }; + for (const optionDefinition of definitions) { + if (!hasOwnProperty(opts, optionDefinition.name)) { + continue; + } + const v = opts[optionDefinition.name] as string; + if (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; } } 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; } 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 = {