Skip to content

Commit

Permalink
Add eslint (#225)
Browse files Browse the repository at this point in the history
* let there be lint

* use strict checking with a few rules off

* uhhh don't disable linting in the one file I actually care about

* fix remaining lint errors that would make console mad

* fix the last lint error
  • Loading branch information
david-crespo authored Dec 2, 2023
1 parent bb159f8 commit 4595cbb
Show file tree
Hide file tree
Showing 18 changed files with 1,600 additions and 203 deletions.
23 changes: 23 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* eslint-env node */
module.exports = {
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/strict",
"plugin:@typescript-eslint/stylistic",
],
parser: "@typescript-eslint/parser",
plugins: ["@typescript-eslint"],
root: true,
ignorePatterns: ["dist/"],
rules: {
"@typescript-eslint/array-type": "off",
"@typescript-eslint/consistent-type-definitions": "off",
"@typescript-eslint/consistent-type-imports": [
"error",
{ prefer: "type-imports" },
],
"@typescript-eslint/no-empty-interface": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
},
};
17 changes: 10 additions & 7 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: "18"
- name: TypeCheck and Test
shell: bash
run: |
npm install
npm run gen
npm run tsc
npm test
- name: npm install
run: npm install
- name: Generate client
run: npm run gen
- name: TypeCheck
run: npm run tsc
- name: Lint
run: npx eslint .
- name: Test
run: npm test
11 changes: 5 additions & 6 deletions client/msw-handlers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* eslint-disable */

/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
Expand All @@ -10,16 +8,16 @@

import {
http,
HttpHandler,
type HttpHandler,
HttpResponse,
StrictResponse,
PathParams,
type StrictResponse,
type PathParams,
} from "msw";
import type {
SnakeCasedPropertiesDeep as Snakify,
Promisable,
} from "type-fest";
import { z, ZodSchema } from "zod";
import { type ZodSchema } from "zod";
import type * as Api from "./Api";
import { snakeify } from "./util";
import * as schema from "./validate";
Expand Down Expand Up @@ -1088,6 +1086,7 @@ const handler =
// TypeScript can't narrow the handler down because there's not an explicit relationship between the schema
// being present and the shape of the handler API. The type of this function could be resolved such that the
// relevant schema is required if and only if the handler has a type that matches the inferred schema
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const result = await (handler as any).apply(null, [
{ path, query, body, req, cookies },
]);
Expand Down
6 changes: 3 additions & 3 deletions client/type-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
* Copyright Oxide Computer Company
*/

import { z } from "zod";
import { assert, Equals } from "tsafe";
import { type z } from "zod";
import { assert, type Equals } from "tsafe";
import type * as A from "./Api";
import * as V from "./validate";
import type * as V from "./validate";

assert<Equals<A.Ipv4Net, z.infer<typeof V.Ipv4Net>>>();
assert<Equals<A.Ipv6Net, z.infer<typeof V.Ipv6Net>>>();
Expand Down
3 changes: 2 additions & 1 deletion generator/client/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import {
snakeToPascal,
} from "../util";
import { initIO } from "../io";
import { refToSchemaName, Schema } from "../schema/base";
import type { Schema } from "../schema/base";
import { refToSchemaName } from "../schema/base";
import {
contentRef,
docComment,
Expand Down
29 changes: 12 additions & 17 deletions generator/client/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
* Copyright Oxide Computer Company
*/

import { OpenAPIV3 } from "openapi-types";
import { snakeToPascal, topologicalSort } from "../util";
import { IO } from "../io";
import { Schema } from "../schema/base";
import type { OpenAPIV3 } from "openapi-types";
import { topologicalSort } from "../util";
import type { IO } from "../io";
import type { Schema } from "../schema/base";
import { OpenAPIV3 as O } from "openapi-types";
const HttpMethods = O.HttpMethods;

Expand Down Expand Up @@ -67,20 +67,15 @@ export function docComment(

type PathConfig = ReturnType<typeof iterPathConfig>[number];
export function iterPathConfig(paths: OpenAPIV3.Document["paths"]) {
return Object.entries(paths)
.flatMap(([path, handlers]) => {
return Object.values(HttpMethods).map((method) => {
const conf = handlers![method]!;
return Object.entries(paths).flatMap(([path, handlers]) => {
if (!handlers) return [];

return {
path,
conf,
method,
opId: conf?.operationId!,
};
});
})
.filter(({ conf }) => conf && conf.operationId);
return Object.values(HttpMethods).flatMap((method) => {
const conf = handlers[method];
if (!conf || !conf.operationId) return [];
return { path, conf, method, opId: conf.operationId };
});
});
}

type Param = Omit<OpenAPIV3.ParameterObject, "schema"> &
Expand Down
15 changes: 6 additions & 9 deletions generator/client/msw-handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ const formatPath = (path: string) =>
export function generateMSWHandlers(spec: OpenAPIV3.Document) {
if (!spec.components) return;

w("/* eslint-disable */\n");

w(`
/**
* This Source Code Form is subject to the terms of the Mozilla Public
Expand All @@ -31,18 +29,16 @@ export function generateMSWHandlers(spec: OpenAPIV3.Document) {
*
* Copyright Oxide Computer Company
*/
`);
w(`
import {
http,
HttpHandler,
type HttpHandler,
HttpResponse,
StrictResponse,
PathParams,
type StrictResponse,
type PathParams,
} from "msw";
import type { SnakeCasedPropertiesDeep as Snakify, Promisable } from "type-fest";
import { z, ZodSchema } from "zod";
import { type ZodSchema } from "zod";
import type * as Api from "./Api";
import { snakeify } from "./util";
import * as schema from "./validate";
Expand Down Expand Up @@ -173,6 +169,7 @@ export function generateMSWHandlers(spec: OpenAPIV3.Document) {
// TypeScript can't narrow the handler down because there's not an explicit relationship between the schema
// being present and the shape of the handler API. The type of this function could be resolved such that the
// relevant schema is required if and only if the handler has a type that matches the inferred schema
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const result = await (handler as any).apply(null, [{path, query, body, req, cookies}])
if (typeof result === "number") {
return new HttpResponse(null, { status: result });
Expand Down Expand Up @@ -214,7 +211,7 @@ export function generateMSWHandlers(spec: OpenAPIV3.Document) {
bodyTypeRef && (method === "post" || method === "put")
? `schema.${refToSchemaName(bodyTypeRef)}`
: "null";
const paramSchema = !!conf.parameters?.length
const paramSchema = conf.parameters?.length
? `schema.${snakeToPascal(opId)}Params`
: "null";

Expand Down
10 changes: 4 additions & 6 deletions generator/client/type-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* Copyright Oxide Computer Company
*/

import { OpenAPIV3 } from "openapi-types";
import type { OpenAPIV3 } from "openapi-types";
import { initIO } from "../io";
import { getSortedSchemas } from "./base";

Expand All @@ -26,13 +26,11 @@ export function generateTypeTests(spec: OpenAPIV3.Document) {
*
* Copyright Oxide Computer Company
*/
`);
w(`
import { z } from "zod";
import { assert, Equals } from "tsafe"
import { type z } from "zod";
import { assert, type Equals } from "tsafe"
import type * as A from "./Api"
import * as V from "./validate"
import type * as V from "./validate"
`);

for (const name of schemaNames) {
Expand Down
2 changes: 1 addition & 1 deletion generator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

import SwaggerParser from "@apidevtools/swagger-parser";
import { OpenAPIV3 } from "openapi-types";
import type { OpenAPIV3 } from "openapi-types";

import { generateApi } from "./client/api";
import { generateMSWHandlers } from "./client/msw-handlers";
Expand Down
4 changes: 2 additions & 2 deletions generator/schema/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
*/

import { match, P } from "ts-pattern";
import { OpenAPIV3 } from "openapi-types";
import { IO } from "../io";
import type { OpenAPIV3 } from "openapi-types";
import type { IO } from "../io";

export type Schema = OpenAPIV3.ReferenceObject | OpenAPIV3.SchemaObject;

Expand Down
3 changes: 2 additions & 1 deletion generator/schema/zod.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
*/

import { expect, test, beforeEach } from "vitest";
import { initIO, TestWritable } from "../io";
import type { TestWritable } from "../io";
import { initIO } from "../io";
import { schemaToZod } from "./zod";

const io = initIO();
Expand Down
4 changes: 2 additions & 2 deletions generator/schema/zod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
* Copyright Oxide Computer Company
*/

import { IO } from "../io";
import { type IO } from "../io";
import { makeSchemaGenerator, refToSchemaName } from "./base";
import { OpenAPIV3 } from "openapi-types";
import { type OpenAPIV3 } from "openapi-types";
import { snakeToCamel } from "../util";

export const schemaToZod = makeSchemaGenerator({
Expand Down
4 changes: 2 additions & 2 deletions generator/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* Copyright Oxide Computer Company
*/

import { OpenAPIV3 } from "openapi-types";
import type { OpenAPIV3 } from "openapi-types";

const snakeTo = (fn: (w: string, i: number) => string) => (s: string) =>
s.split("_").map(fn).join("");
Expand All @@ -29,7 +29,7 @@ export const processParamName = (s: string) => snakeToCamel(renameParam(s));

/** `{project_name}` -> `${projectName}`. if no brackets, leave it alone */
const segmentToInterpolation = (s: string) =>
s.startsWith("{") ? `\$\{path.${processParamName(s.slice(1, -1))}\}` : s;
s.startsWith("{") ? `$\{path.${processParamName(s.slice(1, -1))}}` : s;

export const pathToTemplateStr = (s: string) =>
"`" + s.split("/").map(segmentToInterpolation).join("/") + "`";
Expand Down
Loading

0 comments on commit 4595cbb

Please sign in to comment.