Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/GraphQLIntrospection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export async function introspectServer(
headers[matches[1]] = matches[2];
}

// biome-ignore lint/suspicious/noImplicitAnyLet: <explanation>
let result;
try {
const response = await fetch(url, {
Expand Down
45 changes: 28 additions & 17 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env node

import * as fs from "node:fs";
import * as path from "node:path";

Expand Down Expand Up @@ -67,7 +68,6 @@ import type {
} 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);
Expand Down Expand Up @@ -389,13 +389,14 @@ function makeLangTypeLabel(targetLanguages: readonly TargetLanguage[]): string {
.join("|");
}

function negatedInferenceFlagName(name: string): string {
function negatedInferenceFlagName(inputName: string): string {
let name = inputName;
const prefix = "infer";
if (name.startsWith(prefix)) {
name = name.slice(prefix.length);
}

return "no" + capitalize(name);
return `no${capitalize(name)}`;
}

function dashedFromCamelCase(name: string): string {
Expand Down Expand Up @@ -469,6 +470,7 @@ function makeOptionDefinitions(
return {
name: dashedFromCamelCase(negatedInferenceFlagName(name)),
optionType: "boolean" as const,
// biome-ignore lint/style/useTemplate: <explanation>
description: flag.negationDescription + ".",
kind: "cli" as const,
};
Expand Down Expand Up @@ -674,16 +676,15 @@ const sectionsAfterRenderers: UsageSection[] = [

export function parseCLIOptions(
argv: string[],
targetLanguage?: TargetLanguage,
inputTargetLanguage?: TargetLanguage,
): CLIOptions {
if (argv.length === 0) {
return inferCLIOptions({ help: true }, targetLanguage);
return inferCLIOptions({ help: true }, inputTargetLanguage);
}

const targetLanguages =
targetLanguage === undefined
? defaultTargetLanguages
: [targetLanguage];
const targetLanguages = inputTargetLanguage
? [inputTargetLanguage]
: defaultTargetLanguages;
const optionDefinitions = makeOptionDefinitions(targetLanguages);

// We can only fully parse the options once we know which renderer is selected,
Expand All @@ -692,9 +693,11 @@ export function parseCLIOptions(
// twice. This is the first parse to get the renderer:
const incompleteOptions = inferCLIOptions(
parseOptions(optionDefinitions, argv, true),
targetLanguage,
inputTargetLanguage,
);
if (targetLanguage === undefined) {

let targetLanguage = inputTargetLanguage as TargetLanguage;
if (inputTargetLanguage === undefined) {
const languageName = isLanguageName(incompleteOptions.lang)
? incompleteOptions.lang
: "typescript";
Expand Down Expand Up @@ -828,7 +831,11 @@ async function typeSourcesForURIs(
case "schema":
return uris.map(
(uri) =>
({ kind: "schema", name, uris: [uri] }) as SchemaTypeSource,
({
kind: "schema",
name,
uris: [uri],
}) as SchemaTypeSource,
);
default:
return panic(
Expand Down Expand Up @@ -879,15 +886,18 @@ function makeTypeScriptSource(fileNames: string[]): SchemaTypeSource {
}

export function jsonInputForTargetLanguage(
targetLanguage: string | TargetLanguage,
_targetLanguage: string | TargetLanguage,
languages?: TargetLanguage[],
handleJSONRefs = false,
): JSONInput<Readable> {
if (typeof targetLanguage === "string") {
const languageName = isLanguageName(targetLanguage)
? targetLanguage
let targetLanguage: TargetLanguage;
if (typeof _targetLanguage === "string") {
const languageName = isLanguageName(_targetLanguage)
? _targetLanguage
: "typescript";
targetLanguage = defined(languageNamed(languageName, languages));
} else {
targetLanguage = _targetLanguage;
}

const compressedJSON = new CompressedJSONFromStream(
Expand Down Expand Up @@ -983,7 +993,7 @@ export async function makeQuicktypeOptions(
let leadingComments: string[] | undefined = undefined;
let fixedTopLevels = false;
switch (options.srcLang) {
case "graphql":
case "graphql": {
let schemaString: string | undefined = undefined;
let wroteSchemaToFile = false;
if (options.graphqlIntrospect !== undefined) {
Expand Down Expand Up @@ -1040,6 +1050,7 @@ export async function makeQuicktypeOptions(

sources = gqlSources;
break;
}
case "json":
case "schema":
sources = await getSources(options);
Expand Down
10 changes: 5 additions & 5 deletions test/buildkite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,18 @@ function getChangedFiles(base: string, commit: string): string[] {
return diff.trim().split("\n");
}

export function affectedFixtures(
changedFiles: string[] | undefined = undefined,
): Fixture[] {
if (changedFiles === undefined) {
export function affectedFixtures(_changedFiles?: string[]): Fixture[] {
if (_changedFiles === undefined) {
const { GITHUB_BASE_REF: base, GITHUB_SHA: commit } = process.env;
return commit === undefined
? allFixtures
: affectedFixtures(getChangedFiles(base || "master", commit));
}

// We can ignore changes in Markdown files
changedFiles = _.reject(changedFiles, (file) => _.endsWith(file, ".md"));
const changedFiles = _.reject(_changedFiles, (file) =>
_.endsWith(file, ".md"),
);

// All fixtures are dirty if any changed file is not included as a sourceFile of some fixture.
const fileDependencies = _.flatMap(
Expand Down
6 changes: 1 addition & 5 deletions test/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ function runEnvForLanguage(
const newEnv = Object.assign({}, process.env);

for (const option of Object.keys(additionalRendererOptions)) {
newEnv["QUICKTYPE_" + option.toUpperCase().replace("-", "_")] = (
newEnv[`QUICKTYPE_${option.toUpperCase().replace("-", "_")}`] = (
additionalRendererOptions[
option as keyof typeof additionalRendererOptions
] as Option<string, unknown>
Expand Down Expand Up @@ -216,10 +216,6 @@ export abstract class Fixture {
}

abstract class LanguageFixture extends Fixture {
constructor(language: languages.Language) {
super(language);
}

async setup() {
const setupCommand = this.language.setupCommand;
if (!setupCommand || ONLY_OUTPUT) {
Expand Down
6 changes: 3 additions & 3 deletions test/languages.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { LanguageName } from "quicktype-core";

import * as process from "process";
import * as process from "node:process";
// @ts-ignore
import type { RendererOptions } from "../dist/quicktype-core/Run";

Expand Down Expand Up @@ -672,7 +672,7 @@ export const ElmLanguage: Language = {
export const SwiftLanguage: Language = {
name: "swift",
base: "test/fixtures/swift",
compileCommand: `swiftc -o quicktype main.swift quicktype.swift`,
compileCommand: "swiftc -o quicktype main.swift quicktype.swift",
runCommand(sample: string) {
return `./quicktype "${sample}"`;
},
Expand Down Expand Up @@ -760,7 +760,7 @@ export const SwiftLanguage: Language = {
export const ObjectiveCLanguage: Language = {
name: "objective-c",
base: "test/fixtures/objective-c",
compileCommand: `clang -Werror -framework Foundation *.m -o test`,
compileCommand: "clang -Werror -framework Foundation *.m -o test",
runCommand(sample: string) {
return `cp "${sample}" sample.json && ./test sample.json`;
},
Expand Down
9 changes: 7 additions & 2 deletions test/lib/deepEquals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { Moment } from "moment";
import type { ComparisonRelaxations } from "../utils";

function pathToString(path: string[]): string {
// biome-ignore lint/style/useTemplate: <explanation>
return "." + path.join(".");
}

Expand All @@ -13,9 +14,13 @@ declare namespace Math {

function tryParseMoment(s: string): [Moment | undefined, boolean] {
let m = moment(s);
if (m.isValid()) return [m, false];
if (m.isValid()) {
return [m, false];
}
m = moment(s, "HH:mm:ss.SSZ");
if (m.isValid()) return [m, true];
if (m.isValid()) {
return [m, true];
}
return [undefined, false];
}

Expand Down
15 changes: 7 additions & 8 deletions test/lib/multicore.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import cluster from "cluster";
import process from "process";
import * as _ from "lodash";
import cluster from "node:cluster";
import process from "node:process";

const exit = require("exit");

Expand All @@ -18,8 +17,8 @@ function randomPick<T>(arr: T[]): T {
}

function guys(n: number): string {
return _.range(n)
.map((_i) => randomPick(WORKERS))
return Array.from({ length: n })
.map(() => randomPick(WORKERS))
.join(" ");
}

Expand Down Expand Up @@ -63,13 +62,13 @@ export async function inParallel<Item, Result, Acc>(
await map(item, i);
}
} else {
_.range(workers).forEach((i) =>
for (let i = 0; i < workers; i++) {
cluster.fork({
worker: i,
// https://github.com/TypeStrong/ts-node/issues/367
TS_NODE_PROJECT: "test/tsconfig.json",
}),
);
});
}
}
} else {
// Setup a worker
Expand Down
38 changes: 19 additions & 19 deletions test/test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import * as os from "os";
import * as _ from "lodash";
import * as os from "node:os";

import { inParallel } from "./lib/multicore";
import { execAsync, type Sample } from "./utils";
import { type Fixture, allFixtures } from "./fixtures";
import { allFixtures } from "./fixtures";
import { affectedFixtures, divideParallelJobs } from "./buildkite";

const exit = require("exit");
Expand All @@ -20,8 +19,8 @@ async function main(sources: string[]) {
const fixturesFromCmdline = process.env.FIXTURE;
if (fixturesFromCmdline) {
const fixtureNames = fixturesFromCmdline.split(",");
fixtures = _.filter(fixtures, (fixture) =>
_.some(fixtureNames, (name) => fixture.runForName(name)),
fixtures = fixtures.filter((fixture) =>
fixtureNames.some(fixture.runForName),
);
}

Expand All @@ -34,24 +33,24 @@ async function main(sources: string[]) {
// Get an array of all { sample, fixtureName } objects we'll run.
// We can't just put the fixture in there because these WorkItems
// will be sent in a message, removing all code.
const samples = _.map(fixtures, (fixture) => ({
const samples = fixtures.map((fixture) => ({
fixtureName: fixture.name,
samples: fixture.getSamples(sources),
}));
const priority = _.flatMap(samples, (x) =>
_.map(x.samples.priority, (s) => ({
fixtureName: x.fixtureName,
sample: s,
const priority = samples.flatMap((sample) =>
sample.samples.priority.map((prioritySample) => ({
fixtureName: sample.fixtureName,
sample: prioritySample,
})),
);
const others = _.flatMap(samples, (x) =>
_.map(x.samples.others, (s) => ({
fixtureName: x.fixtureName,
sample: s,
const others = samples.flatMap((sample) =>
sample.samples.others.map((otherSample) => ({
fixtureName: sample.fixtureName,
sample: otherSample,
})),
);

const tests = divideParallelJobs(_.concat(priority, others));
const tests = divideParallelJobs(priority.concat(others));

await inParallel({
queue: tests,
Expand All @@ -63,17 +62,18 @@ async function main(sources: string[]) {
);

for (const fixture of fixtures) {
await execAsync(`rm -rf test/runs`);
await execAsync(`mkdir -p test/runs`);
await execAsync("rm -rf test/runs");
await execAsync("mkdir -p test/runs");

await fixture.setup();
}
},

map: async ({ sample, fixtureName }: WorkItem, index) => {
const fixture = _.find(fixtures, { name: fixtureName }) as Fixture;
const fixture = fixtures.find(({ name }) => name === fixtureName);

try {
await fixture.runWithSample(sample, index, tests.length);
await fixture?.runWithSample(sample, index, tests.length);
} catch (e) {
console.trace(e);
exit(1);
Expand Down
13 changes: 5 additions & 8 deletions test/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,16 @@ export function callAndExpectFailure<T>(message: string, f: () => T): void {
}

export function exec(
s: string,
env: NodeJS.ProcessEnv | undefined,
str: string,
env: NodeJS.ProcessEnv = process.env,
printFailure = true,
): { stdout: string; code: number } {
debug(s);
if (env === undefined) {
env = process.env;
}
const result = shell.exec(s, { silent: !DEBUG, env });
debug(str);
const result = shell.exec(str, { silent: !DEBUG, env });

if (result.code !== 0) {
const failureObj = {
command: s,
command: str,
code: result.code,
};
if (!printFailure) {
Expand Down
Loading