diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 83ef74676..000000000 --- a/.eslintignore +++ /dev/null @@ -1,3 +0,0 @@ -coverage -dist -examples diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index 695bbb1ac..000000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,68 +0,0 @@ -/** @type {import('@types/eslint').Linter.BaseConfig} */ -module.exports = { - parser: "@typescript-eslint/parser", - parserOptions: { - project: ["./tsconfig.json"], - }, - extends: [ - "eslint:recommended", - "plugin:@typescript-eslint/strict", - "plugin:vitest/recommended", - ], - plugins: [ - "@typescript-eslint", - "import", - "no-only-tests", - "prettier", - "vitest", - ], - rules: { - "@typescript-eslint/consistent-indexed-object-style": "off", // sometimes naming keys is more user-friendly - "@typescript-eslint/consistent-type-imports": [ - "error", - { prefer: "type-imports", fixStyle: "inline-type-imports" }, - ], - "@typescript-eslint/no-dynamic-delete": "off", // delete is OK - "@typescript-eslint/no-non-null-assertion": "off", // this is better than "as" - "@typescript-eslint/no-shadow": "error", - "@typescript-eslint/no-unnecessary-condition": "off", // this gives bad advice - "arrow-body-style": ["error", "as-needed"], - "dot-notation": "error", - "import/newline-after-import": "error", - "import/order": [ - "error", - { - alphabetize: { - order: "asc", - orderImportKind: "asc", - caseInsensitive: true, - }, - groups: [ - ["builtin", "external"], - "internal", - "parent", - "index", - "sibling", - ], - }, - ], - curly: "error", - "object-shorthand": "error", // don’t use foo["bar"] - "no-console": "error", - "no-global-assign": "error", - "no-undef": "off", // handled by TS - "no-unused-vars": "off", - }, - overrides: [ - { - files: ["**/*.test.*"], - rules: { - "@typescript-eslint/ban-ts-comment": "off", // allow @ts-ignore only in tests - "@typescript-eslint/no-empty-function": "off", // don’t enforce this in tests - "@typescript-eslint/no-explicit-any": "off", // tests sometimes need this - "no-only-tests/no-only-tests": "error", - "vitest/valid-title": "off", // doesn’t work? - }, - }, - ], -}; diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index 420052dbc..000000000 --- a/.prettierignore +++ /dev/null @@ -1,3 +0,0 @@ -packages/openapi-typescript/examples -*.yaml -*.yml diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 6e1cd9220..000000000 --- a/.prettierrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "singleAttributePerLine": true -} diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 000000000..699ed7331 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["biomejs.biome"] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..47555f79d --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,14 @@ +{ + "[javascript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[json]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[markdown]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[typescript]": { + "editor.defaultFormatter": "biomejs.biome" + } +} diff --git a/biome.json b/biome.json new file mode 100644 index 000000000..56dea8598 --- /dev/null +++ b/biome.json @@ -0,0 +1,32 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.7.0/schema.json", + "organizeImports": { + "enabled": false + }, + "files": { + "ignore": ["**/dist/**"] + }, + "formatter": { + "indentStyle": "space", + "indentWidth": 2, + "lineWidth": 120 + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "complexity": { + "noExcessiveNestedTestSuites": "off", + "useArrowFunction": "off" + }, + "suspicious": { + "noConsoleLog": "error", + "noExplicitAny": "off" + }, + "style": { + "noUselessElse": "off", + "useBlockStatements": "error" + } + } + } +} diff --git a/docs/scripts/update-contributors.js b/docs/scripts/update-contributors.js index 146c5f3a2..dec9622fa 100644 --- a/docs/scripts/update-contributors.js +++ b/docs/scripts/update-contributors.js @@ -206,7 +206,7 @@ async function main() { lastFetch: new Date().getTime(), }; upsert(contributors[repo], userData); - console.log(`Updated old contributor data for ${username}`); // eslint-disable-line no-console + console.log(`Updated old contributor data for ${username}`); // biome-disable-line no-console fs.writeFileSync( new URL("../data/contributors.json", import.meta.url), JSON.stringify(contributors), diff --git a/package.json b/package.json index 5ace0ca2b..83ddc1245 100644 --- a/package.json +++ b/package.json @@ -10,21 +10,15 @@ "scripts": { "build": "pnpm run -r --parallel --filter \"!*docs\" build", "lint": "pnpm run -r --parallel lint", + "format": "pnpm run -r --parallel format", "test": "pnpm run -r --parallel test", "version": "pnpm run build && changeset version && pnpm i" }, "devDependencies": { + "@biomejs/biome": "^1.7.1", "@changesets/changelog-github": "^0.5.0", "@changesets/cli": "^2.27.1", - "@typescript-eslint/eslint-plugin": "^7.7.1", - "@typescript-eslint/parser": "^7.7.1", "del-cli": "^5.1.0", - "eslint": "^8.57.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-no-only-tests": "^3.1.0", - "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-vitest": "^0.2.8", "prettier": "^3.2.5", "typescript": "^5.4.5" } diff --git a/packages/openapi-fetch/.eslintignore b/packages/openapi-fetch/.eslintignore deleted file mode 100644 index a843dc44a..000000000 --- a/packages/openapi-fetch/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -test/fixtures diff --git a/packages/openapi-fetch/.npmignore b/packages/openapi-fetch/.npmignore index 2c7a90b40..e7b8e47e0 100644 --- a/packages/openapi-fetch/.npmignore +++ b/packages/openapi-fetch/.npmignore @@ -1,5 +1,3 @@ -.eslintignore -.prettierignore examples test vitest.config.ts diff --git a/packages/openapi-fetch/.prettierignore b/packages/openapi-fetch/.prettierignore deleted file mode 100644 index e6b7da6b4..000000000 --- a/packages/openapi-fetch/.prettierignore +++ /dev/null @@ -1,3 +0,0 @@ -test/v1.d.ts -test/v1.yaml -test/fixtures/ diff --git a/packages/openapi-fetch/CONTRIBUTING.md b/packages/openapi-fetch/CONTRIBUTING.md index 2d6a8a442..feae02eb9 100644 --- a/packages/openapi-fetch/CONTRIBUTING.md +++ b/packages/openapi-fetch/CONTRIBUTING.md @@ -54,6 +54,14 @@ npx vitest As this is just a minimal fetch wrapper meant to provide deep type inference for API schemas, **testing TS types** is arguably more important than testing the runtime. So please make liberal use of `// @ts-expect-error`, and as a general rule of thumb, write more **unwanted** output tests than _wanted_ output tests. +### Running linting + +Linting is handled via [Biome](https://biomejs.dev), a faster ESLint replacement. It was installed with `pnpm i` and can be run with: + +```bash +pnpm run lint +``` + ### Changelogs The changelog is generated via [changesets](https://github.com/changesets/changesets), and is separate from Git commit messages and pull request titles. To write a human-readable changelog for your changes, run: diff --git a/packages/openapi-fetch/biome.json b/packages/openapi-fetch/biome.json new file mode 100644 index 000000000..1737c6cf4 --- /dev/null +++ b/packages/openapi-fetch/biome.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.7.0/schema.json", + "extends": ["../../biome.json"], + "files": { + "include": ["./src/", "./test/"], + "ignore": ["**/fixtures/**/*"] + } +} diff --git a/packages/openapi-fetch/package.json b/packages/openapi-fetch/package.json index d321b3130..35d2414d2 100644 --- a/packages/openapi-fetch/package.json +++ b/packages/openapi-fetch/package.json @@ -52,9 +52,8 @@ "build:js": "mkdir -p dist && cp src/* dist", "build:js-min": "esbuild --bundle src/index.js --format=esm --minify --outfile=dist/index.min.js && cp dist/index.d.ts dist/index.min.d.ts", "build:cjs": "esbuild --bundle src/index.js --format=cjs --outfile=dist/cjs/index.cjs && cp dist/index.d.ts dist/cjs/index.d.cts", - "lint": "pnpm run \"/^lint:/\"", - "lint:js": "eslint \"{src,test}/**/*.{js,ts}\"", - "lint:prettier": "prettier --check \"{src,test}/**/*\"", + "format": "biome format . --write", + "lint": "biome check .", "generate-types": "cd ../openapi-typescript && pnpm run build && cd ../openapi-fetch && ../openapi-typescript/bin/cli.js ./test/fixtures/api.yaml -o ./test/fixtures/v7-beta.d.ts && npx openapi-typescript ./test/fixtures/api.yaml -o ./test/fixtures/api.d.ts", "pretest": "pnpm run generate-types", "test": "pnpm run \"/^test:/\"", diff --git a/packages/openapi-fetch/src/index.d.ts b/packages/openapi-fetch/src/index.d.ts index 75bbb0054..2679647bb 100644 --- a/packages/openapi-fetch/src/index.d.ts +++ b/packages/openapi-fetch/src/index.d.ts @@ -11,10 +11,6 @@ import type { SuccessResponse, } from "openapi-typescript-helpers"; -// Note: though "any" is considered bad practice in general, this library relies -// on "any" for type inference only it can give. Same goes for the "{}" type. -/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types */ - /** Options for each client instance */ export interface ClientOptions extends Omit { /** set the common root URL for all API requests */ @@ -30,20 +26,10 @@ export interface ClientOptions extends Omit { export type HeadersOptions = | HeadersInit - | Record< - string, - | string - | number - | boolean - | (string | number | boolean)[] - | null - | undefined - >; + | Record; export type QuerySerializer = ( - query: T extends { parameters: any } - ? NonNullable - : Record, + query: T extends { parameters: any } ? NonNullable : Record, ) => string; /** @see https://swagger.io/docs/specification/serialization/#query */ @@ -102,24 +88,18 @@ export type ParamsOption = T extends { : { params: T["parameters"] } : DefaultParamsOption; -export type RequestBodyOption = - OperationRequestBodyContent extends never - ? { body?: never } - : undefined extends OperationRequestBodyContent - ? { body?: OperationRequestBodyContent } - : { body: OperationRequestBodyContent }; +export type RequestBodyOption = OperationRequestBodyContent extends never + ? { body?: never } + : undefined extends OperationRequestBodyContent + ? { body?: OperationRequestBodyContent } + : { body: OperationRequestBodyContent }; -export type FetchOptions = RequestOptions & - Omit; +export type FetchOptions = RequestOptions & Omit; export type FetchResponse = | { data: ParseAsResponse< - GetValueWithDefault< - SuccessResponse>, - Media, - Record - >, + GetValueWithDefault>, Media, Record>, O >; error?: never; @@ -127,11 +107,7 @@ export type FetchResponse = } | { data?: never; - error: GetValueWithDefault< - ErrorResponse>, - Media, - Record - >; + error: GetValueWithDefault>, Media, Record>; response: Response; }; @@ -168,29 +144,24 @@ export function onRequest( req: MiddlewareRequest, options: MergedOptions, ): Request | undefined | Promise; -export function onResponse( - res: Response, - options: MergedOptions, -): Response | undefined | Promise; +export function onResponse(res: Response, options: MergedOptions): Response | undefined | Promise; export interface Middleware { onRequest?: typeof onRequest; onResponse?: typeof onResponse; } +// biome-ignore lint/complexity/noBannedTypes: though extending "{}" is a bad practice in general, this library relies on complex layers of inference, and extending off generic objects is necessary type PathMethods = Partial>; /** This type helper makes the 2nd function param required if params/requestBody are required; otherwise, optional */ -export type MaybeOptionalInit

= - HasRequiredKeys>> extends never - ? [(FetchOptions> | undefined)?] - : [FetchOptions>]; +export type MaybeOptionalInit

= HasRequiredKeys< + FetchOptions> +> extends never + ? [(FetchOptions> | undefined)?] + : [FetchOptions>]; -export type ClientMethod< - Paths extends Record, - M extends HttpMethod, - Media extends MediaType, -> = < +export type ClientMethod, M extends HttpMethod, Media extends MediaType> = < P extends PathsWithMethod, I extends MaybeOptionalInit, >( @@ -198,10 +169,7 @@ export type ClientMethod< ...init: I ) => Promise>; -export default function createClient< - Paths extends {}, - Media extends MediaType = MediaType, ->( +export default function createClient( clientOptions?: ClientOptions, ): { /** Call a GET endpoint */ @@ -249,13 +217,7 @@ export declare function serializeArrayParam( name: string, value: unknown[], options: { - style: - | "simple" - | "label" - | "matrix" - | "form" - | "spaceDelimited" - | "pipeDelimited"; + style: "simple" | "label" | "matrix" | "form" | "spaceDelimited" | "pipeDelimited"; explode: boolean; allowReserved?: boolean; }, @@ -271,10 +233,7 @@ export declare function createQuerySerializer( * @type {import("./index.js").defaultPathSerializer} * @see https://swagger.io/docs/specification/serialization/#path */ -export declare function defaultPathSerializer( - pathname: string, - pathParams: Record, -): string; +export declare function defaultPathSerializer(pathname: string, pathParams: Record): string; /** Serialize body object to string */ export declare function defaultBodySerializer(body: T): string; @@ -293,8 +252,4 @@ export declare function createFinalURL( ): string; /** Merge headers a and b, with b taking priority */ -export declare function mergeHeaders( - ...allHeaders: (HeadersOptions | undefined)[] -): Headers; - -export {}; +export declare function mergeHeaders(...allHeaders: (HeadersOptions | undefined)[]): Headers; diff --git a/packages/openapi-fetch/src/index.js b/packages/openapi-fetch/src/index.js index b9a1bcc37..c4cede7ef 100644 --- a/packages/openapi-fetch/src/index.js +++ b/packages/openapi-fetch/src/index.js @@ -30,7 +30,7 @@ export default function createClient(clientOptions) { * @param {import('./index.js').FetchOptions} fetchOptions */ async function coreFetch(url, fetchOptions) { - let { + const { fetch = baseFetch, headers, params = {}, @@ -49,9 +49,7 @@ export default function createClient(clientOptions) { typeof requestQuerySerializer === "function" ? requestQuerySerializer : createQuerySerializer({ - ...(typeof globalQuerySerializer === "object" - ? globalQuerySerializer - : {}), + ...(typeof globalQuerySerializer === "object" ? globalQuerySerializer : {}), ...requestQuerySerializer, }); } @@ -69,10 +67,7 @@ export default function createClient(clientOptions) { if (requestInit.body instanceof FormData) { requestInit.headers.delete("Content-Type"); } - let request = new Request( - createFinalURL(url, { baseUrl, params, querySerializer }), - requestInit, - ); + let request = new Request(createFinalURL(url, { baseUrl, params, querySerializer }), requestInit); // middleware (request) const mergedOptions = { baseUrl, @@ -88,9 +83,7 @@ export default function createClient(clientOptions) { const result = await m.onRequest(request, mergedOptions); if (result) { if (!(result instanceof Request)) { - throw new Error( - `Middleware must return new Request() when modifying the request`, - ); + throw new Error("Middleware must return new Request() when modifying the request"); } request = result; } @@ -108,9 +101,7 @@ export default function createClient(clientOptions) { const result = await m.onResponse(response, mergedOptions); if (result) { if (!(result instanceof Response)) { - throw new Error( - `Middleware must return new Response() when modifying the response`, - ); + throw new Error("Middleware must return new Response() when modifying the response"); } response = result; } @@ -119,10 +110,7 @@ export default function createClient(clientOptions) { // handle empty content // note: we return `{}` because we want user truthy checks for `.data` or `.error` to succeed - if ( - response.status === 204 || - response.headers.get("Content-Length") === "0" - ) { + if (response.status === 204 || response.headers.get("Content-Length") === "0") { return response.ok ? { data: {}, response } : { error: {}, response }; } @@ -185,9 +173,7 @@ export default function createClient(clientOptions) { continue; } if (typeof m !== "object" || !("onRequest" in m || "onResponse" in m)) { - throw new Error( - "Middleware must be an object with one of `onRequest()` or `onResponse()`", - ); + throw new Error("Middleware must be an object with one of `onRequest()` or `onResponse()`"); } middlewares.push(m); } @@ -216,7 +202,7 @@ export function serializePrimitiveParam(name, value, options) { } if (typeof value === "object") { throw new Error( - `Deeply-nested arrays/objects aren’t supported. Provide your own \`querySerializer()\` to handle these.`, + "Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.", ); } return `${name}=${options?.allowReserved === true ? value : encodeURIComponent(value)}`; @@ -241,12 +227,7 @@ export function serializeObjectParam(name, value, options) { // explode: false if (options.style !== "deepObject" && options.explode === false) { for (const k in value) { - values.push( - k, - options.allowReserved === true - ? value[k] - : encodeURIComponent(value[k]), - ); + values.push(k, options.allowReserved === true ? value[k] : encodeURIComponent(value[k])); } const final = values.join(","); // note: values are always joined by comma in explode: false (but joiner can prefix) switch (options.style) { @@ -271,9 +252,7 @@ export function serializeObjectParam(name, value, options) { values.push(serializePrimitiveParam(finalName, value[k], options)); } const final = values.join(joiner); - return options.style === "label" || options.style === "matrix" - ? `${joiner}${final}` - : final; + return options.style === "label" || options.style === "matrix" ? `${joiner}${final}` : final; } /** @@ -287,14 +266,8 @@ export function serializeArrayParam(name, value, options) { // explode: false if (options.explode === false) { - const joiner = - { form: ",", spaceDelimited: "%20", pipeDelimited: "|" }[options.style] || - ","; // note: for arrays, joiners vary wildly based on style + explode behavior - const final = ( - options.allowReserved === true - ? value - : value.map((v) => encodeURIComponent(v)) - ).join(joiner); + const joiner = { form: ",", spaceDelimited: "%20", pipeDelimited: "|" }[options.style] || ","; // note: for arrays, joiners vary wildly based on style + explode behavior + const final = (options.allowReserved === true ? value : value.map((v) => encodeURIComponent(v))).join(joiner); switch (options.style) { case "simple": { return final; @@ -305,8 +278,8 @@ export function serializeArrayParam(name, value, options) { case "matrix": { return `;${name}=${final}`; } - case "spaceDelimited": - case "pipeDelimited": + // case "spaceDelimited": + // case "pipeDelimited": default: { return `${name}=${final}`; } @@ -392,37 +365,23 @@ export function defaultPathSerializer(pathname, pathParams) { style = "matrix"; name = name.substring(1); } - if ( - !pathParams || - pathParams[name] === undefined || - pathParams[name] === null - ) { + if (!pathParams || pathParams[name] === undefined || pathParams[name] === null) { continue; } const value = pathParams[name]; if (Array.isArray(value)) { - nextURL = nextURL.replace( - match, - serializeArrayParam(name, value, { style, explode }), - ); + nextURL = nextURL.replace(match, serializeArrayParam(name, value, { style, explode })); continue; } if (typeof value === "object") { - nextURL = nextURL.replace( - match, - serializeObjectParam(name, value, { style, explode }), - ); + nextURL = nextURL.replace(match, serializeObjectParam(name, value, { style, explode })); continue; } if (style === "matrix") { - nextURL = nextURL.replace( - match, - `;${serializePrimitiveParam(name, value)}`, - ); + nextURL = nextURL.replace(match, `;${serializePrimitiveParam(name, value)}`); continue; } nextURL = nextURL.replace(match, style === "label" ? `.${value}` : value); - continue; } return nextURL; } diff --git a/packages/openapi-fetch/test/fixtures/mock-server.ts b/packages/openapi-fetch/test/fixtures/mock-server.ts index 1645ac535..0ea5721e6 100644 --- a/packages/openapi-fetch/test/fixtures/mock-server.ts +++ b/packages/openapi-fetch/test/fixtures/mock-server.ts @@ -81,44 +81,33 @@ export function useMockRequestHandler< Params extends PathParams = PathParams, RequestBodyType extends DefaultBodyType = DefaultBodyType, ResponseBodyType extends DefaultBodyType = undefined, ->({ - baseUrl: requestBaseUrl, - method, - path, - body, - headers, - status, - handler, -}: MockRequestHandlerOptions) { +>({ baseUrl: requestBaseUrl, method, path, body, headers, status, handler }: MockRequestHandlerOptions) { let requestUrl = ""; - let receivedRequest: null | StrictRequest = null; - let receivedCookies: null | Record = null; + let receivedRequest: StrictRequest; + let receivedCookies: Record = {}; const resolvedPath = toAbsoluteURL(path, requestBaseUrl); server.use( - http[method]( - resolvedPath, - (args) => { - requestUrl = args.request.url; - receivedRequest = args.request.clone(); - receivedCookies = { ...args.cookies }; - - if (handler) { - return handler(args); - } - - return HttpResponse.json(body as any, { - status: status ?? 200, - headers, - }) as AsyncResponseResolverReturnType; - }, - ), + http[method](resolvedPath, (args) => { + requestUrl = args.request.url; + receivedRequest = args.request.clone(); + receivedCookies = { ...args.cookies }; + + if (handler) { + return handler(args); + } + + return HttpResponse.json(body as any, { + status: status ?? 200, + headers, + }) as AsyncResponseResolverReturnType; + }), ); return { - getRequestCookies: () => receivedCookies!, - getRequest: () => receivedRequest!, + getRequestCookies: () => receivedCookies, + getRequest: () => receivedRequest, getRequestUrl: () => new URL(requestUrl), }; } diff --git a/packages/openapi-fetch/test/index.bench.js b/packages/openapi-fetch/test/index.bench.js index e5bc8b2c0..cd1b59e9b 100644 --- a/packages/openapi-fetch/test/index.bench.js +++ b/packages/openapi-fetch/test/index.bench.js @@ -27,9 +27,7 @@ const server = setupServer( // Ensure we are listening early enough so all the requests are intercepted server.listen({ onUnhandledRequest: (request) => { - throw new Error( - `No request handler found for ${request.method} ${request.url}`, - ); + throw new Error(`No request handler found for ${request.method} ${request.url}`); }, }); @@ -60,14 +58,14 @@ describe("setup", () => { }); describe("get (only URL)", () => { - let openapiFetch = createClient({ baseUrl: BASE_URL }); - let openapiTSFetch = Fetcher.for(); + const openapiFetch = createClient({ baseUrl: BASE_URL }); + const openapiTSFetch = Fetcher.for(); openapiTSFetch.configure({ baseUrl: BASE_URL, }); - let openapiTSFetchGET = openapiTSFetch.path("/url").method("get").create(); + const openapiTSFetchGET = openapiTSFetch.path("/url").method("get").create(); - let axiosInstance = axios.create({ + const axiosInstance = axios.create({ baseURL: BASE_URL, }); @@ -93,18 +91,18 @@ describe("get (only URL)", () => { }); describe("get (headers)", () => { - let openapiFetch = createClient({ + const openapiFetch = createClient({ baseUrl: BASE_URL, headers: { "x-base-header": 123 }, }); - let openapiTSFetch = Fetcher.for(); + const openapiTSFetch = Fetcher.for(); openapiTSFetch.configure({ baseUrl: BASE_URL, init: { headers: { "x-base-header": 123 } }, }); - let openapiTSFetchGET = openapiTSFetch.path("/url").method("get").create(); + const openapiTSFetchGET = openapiTSFetch.path("/url").method("get").create(); - let axiosInstance = axios.create({ + const axiosInstance = axios.create({ baseURL: BASE_URL, }); @@ -131,9 +129,6 @@ describe("get (headers)", () => { }); bench("superagent", async () => { - await superagent - .get(`${BASE_URL}/url`) - .set("x-header-1", 123) - .set("x-header-2", 456); + await superagent.get(`${BASE_URL}/url`).set("x-header-1", 123).set("x-header-2", 456); }); }); diff --git a/packages/openapi-fetch/test/index.test-d.ts b/packages/openapi-fetch/test/index.test-d.ts index 943135c76..924305446 100644 --- a/packages/openapi-fetch/test/index.test-d.ts +++ b/packages/openapi-fetch/test/index.test-d.ts @@ -12,7 +12,6 @@ interface Blogpost { } // This is a type test that will not be executed -// eslint-disable-next-line vitest/expect-expect test("the error type works properly", async () => { const value = await GET("/blogposts"); @@ -20,11 +19,7 @@ test("the error type works properly", async () => { expectTypeOf(value.data).toEqualTypeOf>(); } else { expectTypeOf(value.data).toBeUndefined(); - expectTypeOf(value.error) - .extract<{ code: number }>() - .toEqualTypeOf<{ code: number; message: string }>(); - expectTypeOf(value.error) - .exclude<{ code: number }>() - .toEqualTypeOf>(); + expectTypeOf(value.error).extract<{ code: number }>().toEqualTypeOf<{ code: number; message: string }>(); + expectTypeOf(value.error).exclude<{ code: number }>().toEqualTypeOf>(); } }); diff --git a/packages/openapi-fetch/test/index.test.ts b/packages/openapi-fetch/test/index.test.ts index d0e39d2c6..f86ab768e 100644 --- a/packages/openapi-fetch/test/index.test.ts +++ b/packages/openapi-fetch/test/index.test.ts @@ -1,23 +1,12 @@ import { HttpResponse, type StrictResponse } from "msw"; -import createClient, { - type Middleware, - type MiddlewareRequest, - type QuerySerializerOptions, -} from "../src/index.js"; +import createClient, { type Middleware, type MiddlewareRequest, type QuerySerializerOptions } from "../src/index.js"; import type { paths } from "./fixtures/api.js"; -import { - server, - baseUrl, - useMockRequestHandler, - toAbsoluteURL, -} from "./fixtures/mock-server.js"; +import { server, baseUrl, useMockRequestHandler, toAbsoluteURL } from "./fixtures/mock-server.js"; beforeAll(() => { server.listen({ onUnhandledRequest: (request) => { - throw new Error( - `No request handler found for ${request.method} ${request.url}`, - ); + throw new Error(`No request handler found for ${request.method} ${request.url}`); }, }); }); @@ -142,7 +131,7 @@ describe("client", () => { useMockRequestHandler<{ post_id: string }>({ baseUrl, method: "get", - path: `/blogposts/:post_id`, + path: "/blogposts/:post_id", handler: ({ params }) => { calledPostId = params.post_id; return HttpResponse.json({ message: "OK" }, { status: 200 }); @@ -165,7 +154,7 @@ describe("client", () => { const { getRequestUrl } = useMockRequestHandler({ baseUrl, method: "get", - path: `/path-params/*`, + path: "/path-params/*", }); await client.GET( @@ -232,9 +221,7 @@ describe("client", () => { // expect post_id to be encoded properly const url = getRequestUrl(); expect(url.searchParams.get("id ")).toBe(" 🥴"); - expect(url.pathname + url.search).toBe( - `/blogposts/post?id%20=%20%F0%9F%A5%B4`, - ); + expect(url.pathname + url.search).toBe("/blogposts/post?id%20=%20%F0%9F%A5%B4"); }); }); @@ -253,10 +240,7 @@ describe("client", () => { { status: 500 }, ) as StrictResponse; } - return HttpResponse.json( - { status: header }, - { status: 200, headers: request.headers }, - ); + return HttpResponse.json({ status: header }, { status: 200, headers: request.headers }); }, }); @@ -282,9 +266,7 @@ describe("client", () => { }); // expect param passed correctly - expect(response.response.headers.get("x-required-header")).toBe( - "correct", - ); + expect(response.response.headers.get("x-required-header")).toBe("correct"); }); describe("query", () => { @@ -304,9 +286,7 @@ describe("client", () => { }, }); - expect(getRequestUrl().search).toBe( - "?string=string&number=0&boolean=false", - ); + expect(getRequestUrl().search).toBe("?string=string&number=0&boolean=false"); }); it("array params (empty)", async () => { @@ -500,12 +480,8 @@ describe("client", () => { }, }); - expect(getRequestUrl().search).toBe( - "?string=bad/character%F0%9F%90%B6", - ); - expect(getRequestUrl().searchParams.get("string")).toBe( - "bad/character🐶", - ); + expect(getRequestUrl().search).toBe("?string=bad/character%F0%9F%90%B6"); + expect(getRequestUrl().searchParams.get("string")).toBe("bad/character🐶"); await client.GET("/query-params", { params: { @@ -518,12 +494,8 @@ describe("client", () => { }, }); - expect(getRequestUrl().search).toBe( - "?string=bad%2Fcharacter%F0%9F%90%B6", - ); - expect(getRequestUrl().searchParams.get("string")).toBe( - "bad/character🐶", - ); + expect(getRequestUrl().search).toBe("?string=bad%2Fcharacter%F0%9F%90%B6"); + expect(getRequestUrl().searchParams.get("string")).toBe("bad/character🐶"); }); describe("function", () => { @@ -547,9 +519,7 @@ describe("client", () => { }); const url = getRequestUrl(); - expect(url.pathname + url.search).toBe( - "/blogposts/my-post?alpha=2&beta=json", - ); + expect(url.pathname + url.search).toBe("/blogposts/my-post?alpha=2&beta=json"); }); it("per-request", async () => { @@ -573,9 +543,7 @@ describe("client", () => { }); const url = getRequestUrl(); - expect(url.pathname + url.search).toBe( - "/blogposts/my-post?alpha=2&beta=json", - ); + expect(url.pathname + url.search).toBe("/blogposts/my-post?alpha=2&beta=json"); }); }); @@ -604,7 +572,6 @@ describe("client", () => { describe("body", () => { // these are pure type tests; no runtime assertions needed - /* eslint-disable vitest/expect-expect */ it("requires necessary requestBodies", async () => { const client = createClient({ baseUrl }); @@ -686,7 +653,6 @@ describe("client", () => { }); }); }); - /* eslint-enable vitest/expect-expect */ }); describe("options", () => { @@ -875,7 +841,7 @@ describe("client", () => { const { getRequest } = useMockRequestHandler({ baseUrl, method: "options", - path: `https://foo.bar/api/v1`, + path: "https://foo.bar/api/v1", status: 200, body: {}, }); @@ -1027,7 +993,7 @@ describe("client", () => { it("receives OpenAPI options passed in from parent", async () => { useMockRequestHandler({ method: "put", - path: `https://api.foo.bar/v1/tag*`, + path: "https://api.foo.bar/v1/tag*", status: 200, body: {}, }); @@ -1055,8 +1021,8 @@ describe("client", () => { }); client.use({ onRequest(req) { - receivedPath = req!.schemaPath; - receivedParams = req!.params; + receivedPath = req.schemaPath; + receivedParams = req.params; return undefined; }, }); @@ -1214,9 +1180,7 @@ describe("client", () => { // discard `data` object if (!error) { - throw new Error( - "treats `default` as an error: error response should be present", - ); + throw new Error("treats `default` as an error: error response should be present"); } // assert `error.message` doesn’t throw TS error @@ -1236,7 +1200,7 @@ describe("client", () => { parseAs: "text", })) satisfies { data?: string }; if (error) { - throw new Error(`parseAs text: error`); + throw new Error("parseAs text: error"); } expect(data).toBe("{}"); }); @@ -1253,7 +1217,7 @@ describe("client", () => { parseAs: "arrayBuffer", })) satisfies { data?: ArrayBuffer }; if (error) { - throw new Error(`parseAs arrayBuffer: error`); + throw new Error("parseAs arrayBuffer: error"); } expect(data.byteLength).toBe(2); }); @@ -1270,7 +1234,7 @@ describe("client", () => { parseAs: "blob", })) satisfies { data?: Blob }; if (error) { - throw new Error(`parseAs blob: error`); + throw new Error("parseAs blob: error"); } expect(data.constructor.name).toBe("Blob"); @@ -1288,13 +1252,13 @@ describe("client", () => { parseAs: "stream", })) satisfies { data?: ReadableStream | null }; if (!data) { - throw new Error(`parseAs stream: error`); + throw new Error("parseAs stream: error"); } expect(data).toBeInstanceOf(ReadableStream); const reader = data.getReader(); const result = await reader.read(); - expect(result.value!.length).toBe(2); + expect(result.value?.length).toBe(2); }); it("use the selected content", async () => { @@ -1328,7 +1292,7 @@ describe("client", () => { | undefined; if (!data) { - throw new Error(`Missing response`); + throw new Error("Missing response"); } expect(data).toEqual({ @@ -1367,12 +1331,9 @@ describe("client", () => { status: 200, body: mockData, }); - const { data, error, response } = await client.GET( - "/blogposts/{post_id}", - { - params: { path: { post_id: "my-post" } }, - }, - ); + const { data, error, response } = await client.GET("/blogposts/{post_id}", { + params: { path: { post_id: "my-post" } }, + }); // assert correct URL was called expect(getRequestUrl().pathname).toBe("/blogposts/my-post"); @@ -1397,15 +1358,12 @@ describe("client", () => { body: mockError, }); - const { data, error, response } = await client.GET( - "/blogposts/{post_id}", - { - params: { path: { post_id: "my-post" } }, - }, - ); + const { data, error, response } = await client.GET("/blogposts/{post_id}", { + params: { path: { post_id: "my-post" } }, + }); // assert correct URL was called - expect(getRequest().url).toBe(baseUrl + "/blogposts/my-post"); + expect(getRequest().url).toBe(`${baseUrl}/blogposts/my-post`); // assert correct method was called expect(getRequest().method).toBe("GET"); @@ -1591,7 +1549,7 @@ describe("client", () => { useMockRequestHandler({ baseUrl, method: "delete", - path: `/blogposts/:post_id`, + path: "/blogposts/:post_id", handler: () => new HttpResponse(null, { status: 200, @@ -1621,7 +1579,7 @@ describe("client", () => { const { getRequest } = useMockRequestHandler({ baseUrl, method: "options", - path: `/anyMethod`, + path: "/anyMethod", }); await client.OPTIONS("/anyMethod"); expect(getRequest().method).toBe("OPTIONS"); @@ -1665,9 +1623,9 @@ describe("client", () => { path: "/anyMethod", }); - await expect( - async () => await client.TRACE("/anyMethod"), - ).rejects.toThrowError("'TRACE' HTTP method is unsupported"); + await expect(async () => await client.TRACE("/anyMethod")).rejects.toThrowError( + "'TRACE' HTTP method is unsupported", + ); }); }); }); @@ -1705,8 +1663,6 @@ describe("examples", () => { await client.GET("/blogposts/{post_id}", { params: { path: { post_id: "1234" } }, }); - expect(getRequest().headers.get("authorization")).toBe( - `Bearer ${accessToken}`, - ); + expect(getRequest().headers.get("authorization")).toBe(`Bearer ${accessToken}`); }); }); diff --git a/packages/openapi-fetch/test/v7-beta.test.ts b/packages/openapi-fetch/test/v7-beta.test.ts index 0b89ec609..f6729989d 100644 --- a/packages/openapi-fetch/test/v7-beta.test.ts +++ b/packages/openapi-fetch/test/v7-beta.test.ts @@ -1,15 +1,6 @@ import { HttpResponse, type StrictResponse } from "msw"; -import createClient, { - type Middleware, - type MiddlewareRequest, - type QuerySerializerOptions, -} from "../src/index.js"; -import { - server, - baseUrl, - useMockRequestHandler, - toAbsoluteURL, -} from "./fixtures/mock-server.js"; +import createClient, { type Middleware, type MiddlewareRequest, type QuerySerializerOptions } from "../src/index.js"; +import { server, baseUrl, useMockRequestHandler, toAbsoluteURL } from "./fixtures/mock-server.js"; import type { paths } from "./fixtures/v7-beta.js"; // Note @@ -20,9 +11,7 @@ import type { paths } from "./fixtures/v7-beta.js"; beforeAll(() => { server.listen({ onUnhandledRequest: (request) => { - throw new Error( - `No request handler found for ${request.method} ${request.url}`, - ); + throw new Error(`No request handler found for ${request.method} ${request.url}`); }, }); }); @@ -147,7 +136,7 @@ describe("client", () => { useMockRequestHandler<{ post_id: string }>({ baseUrl, method: "get", - path: `/blogposts/:post_id`, + path: "/blogposts/:post_id", handler: ({ params }) => { calledPostId = params.post_id; return HttpResponse.json({ message: "OK" }, { status: 200 }); @@ -170,7 +159,7 @@ describe("client", () => { const { getRequestUrl } = useMockRequestHandler({ baseUrl, method: "get", - path: `/path-params/*`, + path: "/path-params/*", }); await client.GET( @@ -237,9 +226,7 @@ describe("client", () => { // expect post_id to be encoded properly const url = getRequestUrl(); expect(url.searchParams.get("id ")).toBe(" 🥴"); - expect(url.pathname + url.search).toBe( - `/blogposts/post?id%20=%20%F0%9F%A5%B4`, - ); + expect(url.pathname + url.search).toBe("/blogposts/post?id%20=%20%F0%9F%A5%B4"); }); }); @@ -258,10 +245,7 @@ describe("client", () => { { status: 500 }, ) as StrictResponse; } - return HttpResponse.json( - { status: header }, - { status: 200, headers: request.headers }, - ); + return HttpResponse.json({ status: header }, { status: 200, headers: request.headers }); }, }); @@ -287,9 +271,7 @@ describe("client", () => { }); // expect param passed correctly - expect(response.response.headers.get("x-required-header")).toBe( - "correct", - ); + expect(response.response.headers.get("x-required-header")).toBe("correct"); }); describe("query", () => { @@ -309,9 +291,7 @@ describe("client", () => { }, }); - expect(getRequestUrl().search).toBe( - "?string=string&number=0&boolean=false", - ); + expect(getRequestUrl().search).toBe("?string=string&number=0&boolean=false"); }); it("array params (empty)", async () => { @@ -505,12 +485,8 @@ describe("client", () => { }, }); - expect(getRequestUrl().search).toBe( - "?string=bad/character%F0%9F%90%B6", - ); - expect(getRequestUrl().searchParams.get("string")).toBe( - "bad/character🐶", - ); + expect(getRequestUrl().search).toBe("?string=bad/character%F0%9F%90%B6"); + expect(getRequestUrl().searchParams.get("string")).toBe("bad/character🐶"); await client.GET("/query-params", { params: { @@ -523,12 +499,8 @@ describe("client", () => { }, }); - expect(getRequestUrl().search).toBe( - "?string=bad%2Fcharacter%F0%9F%90%B6", - ); - expect(getRequestUrl().searchParams.get("string")).toBe( - "bad/character🐶", - ); + expect(getRequestUrl().search).toBe("?string=bad%2Fcharacter%F0%9F%90%B6"); + expect(getRequestUrl().searchParams.get("string")).toBe("bad/character🐶"); }); describe("function", () => { @@ -552,9 +524,7 @@ describe("client", () => { }); const url = getRequestUrl(); - expect(url.pathname + url.search).toBe( - "/blogposts/my-post?alpha=2&beta=json", - ); + expect(url.pathname + url.search).toBe("/blogposts/my-post?alpha=2&beta=json"); }); it("per-request", async () => { @@ -578,9 +548,7 @@ describe("client", () => { }); const url = getRequestUrl(); - expect(url.pathname + url.search).toBe( - "/blogposts/my-post?alpha=2&beta=json", - ); + expect(url.pathname + url.search).toBe("/blogposts/my-post?alpha=2&beta=json"); }); }); @@ -609,7 +577,6 @@ describe("client", () => { describe("body", () => { // these are pure type tests; no runtime assertions needed - /* eslint-disable vitest/expect-expect */ it("requires necessary requestBodies", async () => { const client = createClient({ baseUrl }); @@ -691,7 +658,6 @@ describe("client", () => { }); }); }); - /* eslint-enable vitest/expect-expect */ }); describe("options", () => { @@ -880,7 +846,7 @@ describe("client", () => { const { getRequest } = useMockRequestHandler({ baseUrl, method: "options", - path: `https://foo.bar/api/v1`, + path: "https://foo.bar/api/v1", status: 200, body: {}, }); @@ -1032,7 +998,7 @@ describe("client", () => { it("receives OpenAPI options passed in from parent", async () => { useMockRequestHandler({ method: "put", - path: `https://api.foo.bar/v1/tag*`, + path: "https://api.foo.bar/v1/tag*", status: 200, body: {}, }); @@ -1060,8 +1026,8 @@ describe("client", () => { }); client.use({ onRequest(req) { - receivedPath = req!.schemaPath; - receivedParams = req!.params; + receivedPath = req.schemaPath; + receivedParams = req.params; return undefined; }, }); @@ -1219,9 +1185,7 @@ describe("client", () => { // discard `data` object if (!error) { - throw new Error( - "treats `default` as an error: error response should be present", - ); + throw new Error("treats `default` as an error: error response should be present"); } // assert `error.message` doesn’t throw TS error @@ -1241,7 +1205,7 @@ describe("client", () => { parseAs: "text", })) satisfies { data?: string }; if (error) { - throw new Error(`parseAs text: error`); + throw new Error("parseAs text: error"); } expect(data).toBe("{}"); }); @@ -1258,7 +1222,7 @@ describe("client", () => { parseAs: "arrayBuffer", })) satisfies { data?: ArrayBuffer }; if (error) { - throw new Error(`parseAs arrayBuffer: error`); + throw new Error("parseAs arrayBuffer: error"); } expect(data.byteLength).toBe(2); }); @@ -1275,7 +1239,7 @@ describe("client", () => { parseAs: "blob", })) satisfies { data?: Blob }; if (error) { - throw new Error(`parseAs blob: error`); + throw new Error("parseAs blob: error"); } expect(data.constructor.name).toBe("Blob"); @@ -1293,13 +1257,13 @@ describe("client", () => { parseAs: "stream", })) satisfies { data?: ReadableStream | null }; if (!data) { - throw new Error(`parseAs stream: error`); + throw new Error("parseAs stream: error"); } expect(data).toBeInstanceOf(ReadableStream); const reader = data.getReader(); const result = await reader.read(); - expect(result.value!.length).toBe(2); + expect(result.value?.length).toBe(2); }); it("use the selected content", async () => { @@ -1333,7 +1297,7 @@ describe("client", () => { | undefined; if (!data) { - throw new Error(`Missing response`); + throw new Error("Missing response"); } expect(data).toEqual({ @@ -1372,12 +1336,9 @@ describe("client", () => { status: 200, body: mockData, }); - const { data, error, response } = await client.GET( - "/blogposts/{post_id}", - { - params: { path: { post_id: "my-post" } }, - }, - ); + const { data, error, response } = await client.GET("/blogposts/{post_id}", { + params: { path: { post_id: "my-post" } }, + }); // assert correct URL was called expect(getRequestUrl().pathname).toBe("/blogposts/my-post"); @@ -1402,15 +1363,12 @@ describe("client", () => { body: mockError, }); - const { data, error, response } = await client.GET( - "/blogposts/{post_id}", - { - params: { path: { post_id: "my-post" } }, - }, - ); + const { data, error, response } = await client.GET("/blogposts/{post_id}", { + params: { path: { post_id: "my-post" } }, + }); // assert correct URL was called - expect(getRequest().url).toBe(baseUrl + "/blogposts/my-post"); + expect(getRequest().url).toBe(`${baseUrl}/blogposts/my-post`); // assert correct method was called expect(getRequest().method).toBe("GET"); @@ -1596,7 +1554,7 @@ describe("client", () => { useMockRequestHandler({ baseUrl, method: "delete", - path: `/blogposts/:post_id`, + path: "/blogposts/:post_id", handler: () => new HttpResponse(null, { status: 200, @@ -1626,7 +1584,7 @@ describe("client", () => { const { getRequest } = useMockRequestHandler({ baseUrl, method: "options", - path: `/anyMethod`, + path: "/anyMethod", }); await client.OPTIONS("/anyMethod"); expect(getRequest().method).toBe("OPTIONS"); @@ -1670,9 +1628,9 @@ describe("client", () => { path: "/anyMethod", }); - await expect( - async () => await client.TRACE("/anyMethod"), - ).rejects.toThrowError("'TRACE' HTTP method is unsupported"); + await expect(async () => await client.TRACE("/anyMethod")).rejects.toThrowError( + "'TRACE' HTTP method is unsupported", + ); }); }); }); @@ -1710,8 +1668,6 @@ describe("examples", () => { await client.GET("/blogposts/{post_id}", { params: { path: { post_id: "1234" } }, }); - expect(getRequest().headers.get("authorization")).toBe( - `Bearer ${accessToken}`, - ); + expect(getRequest().headers.get("authorization")).toBe(`Bearer ${accessToken}`); }); }); diff --git a/packages/openapi-fetch/tsconfig.json b/packages/openapi-fetch/tsconfig.json index 959aa82af..384036bb9 100644 --- a/packages/openapi-fetch/tsconfig.json +++ b/packages/openapi-fetch/tsconfig.json @@ -5,8 +5,8 @@ "downlevelIteration": false, "esModuleInterop": true, "lib": ["ESNext", "DOM"], - "module": "NodeNext", - "moduleResolution": "NodeNext", + "module": "ESNext", + "moduleResolution": "Bundler", "noUncheckedIndexedAccess": true, "outDir": "dist", "skipLibCheck": false, diff --git a/packages/openapi-typescript-helpers/biome.json b/packages/openapi-typescript-helpers/biome.json new file mode 100644 index 000000000..11f4ba8e9 --- /dev/null +++ b/packages/openapi-typescript-helpers/biome.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.7.0/schema.json", + "extends": ["../../biome.json"], + "files": { + "include": ["*"] + } +} diff --git a/packages/openapi-typescript-helpers/index.d.ts b/packages/openapi-typescript-helpers/index.d.ts index e4215e458..14a95097f 100644 --- a/packages/openapi-typescript-helpers/index.d.ts +++ b/packages/openapi-typescript-helpers/index.d.ts @@ -1,29 +1,16 @@ -/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types */ - // HTTP types -export type HttpMethod = - | "get" - | "put" - | "post" - | "delete" - | "options" - | "head" - | "patch" - | "trace"; +export type HttpMethod = "get" | "put" | "post" | "delete" | "options" | "head" | "patch" | "trace"; /** 2XX statuses */ export type OkStatus = 200 | 201 | 202 | 203 | 204 | 206 | 207 | "2XX"; -// prettier-ignore /** 4XX and 5XX statuses */ +// biome-ignore format: keep on one line export type ErrorStatus = 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511 | '5XX' | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 429 | 431 | 444 | 450 | 451 | 497 | 498 | 499 | '4XX' | "default"; // OpenAPI type helpers /** Given an OpenAPI **Paths Object**, find all paths that have the given method */ -export type PathsWithMethod< - Paths extends {}, - PathnameMethod extends HttpMethod, -> = { +export type PathsWithMethod = { [Pathname in keyof Paths]: Paths[Pathname] extends { [K in PathnameMethod]: any; } @@ -41,65 +28,46 @@ export type PathItemObject = { [M in HttpMethod]: OperationObject; } & { parameters?: any }; /** Return `responses` for an Operation Object */ -export type ResponseObjectMap = T extends { responses: any } - ? T["responses"] - : unknown; +export type ResponseObjectMap = T extends { responses: any } ? T["responses"] : unknown; /** Return `content` for a Response Object */ -export type ResponseContent = T extends { content: any } - ? T["content"] - : unknown; +export type ResponseContent = T extends { content: any } ? T["content"] : unknown; /** Return `requestBody` for an Operation Object */ -export type OperationRequestBody = T extends { requestBody?: any } - ? T["requestBody"] - : never; +export type OperationRequestBody = T extends { requestBody?: any } ? T["requestBody"] : never; /** Internal helper used in OperationRequestBodyContent */ -export type OperationRequestBodyMediaContent = - undefined extends OperationRequestBody - ? FilterKeys>, "content"> | undefined - : FilterKeys, "content">; +export type OperationRequestBodyMediaContent = undefined extends OperationRequestBody + ? FilterKeys>, "content"> | undefined + : FilterKeys, "content">; /** Return first `content` from a Request Object Mapping, allowing any media type */ -export type OperationRequestBodyContent = - FilterKeys, MediaType> extends never - ? - | FilterKeys< - NonNullable>, - MediaType - > - | undefined - : FilterKeys, MediaType>; +export type OperationRequestBodyContent = FilterKeys, MediaType> extends never + ? FilterKeys>, MediaType> | undefined + : FilterKeys, MediaType>; /** Return first 2XX response from a Response Object Map */ export type SuccessResponse = ResponseContent>; /** Return first 5XX or 4XX response (in that order) from a Response Object Map */ export type ErrorResponse = ResponseContent>; /** Return first JSON-like 2XX response from a path + HTTP method */ -export type SuccessResponseJSON = JSONLike< - SuccessResponse> ->; +export type SuccessResponseJSON = JSONLike>>; /** Return first JSON-like 5XX or 4XX response from a path + HTTP method */ -export type ErrorResponseJSON = JSONLike< - ErrorResponse> ->; +export type ErrorResponseJSON = JSONLike>>; /** Return JSON-like request body from a path + HTTP method */ -export type RequestBodyJSON = JSONLike< - ResponseContent> ->; +export type RequestBodyJSON = JSONLike>>; // Generic TS utils /** Find first match of multiple keys */ export type FilterKeys = Obj[keyof Obj & Matchers]; /** Get the type of a value of an input object with a given key. If the key is not found, return a default type. Works with unions of objects too. */ -export type GetValueWithDefault = Obj extends any ? (FilterKeys extends never ? Default : FilterKeys) : never; +export type GetValueWithDefault = Obj extends any + ? FilterKeys extends never + ? Default + : FilterKeys + : never; /** Return any `[string]/[string]` media type (important because openapi-fetch allows any content response, not just JSON-like) */ export type MediaType = `${string}/${string}`; /** Return any media type containing "json" (works for "application/json", "application/vnd.api+json", "application/vnd.oai.openapi+json") */ export type JSONLike = FilterKeys; /** Filter objects that have required keys */ -export type FindRequiredKeys = K extends unknown - ? undefined extends T[K] - ? never - : K - : K; +export type FindRequiredKeys = K extends unknown ? (undefined extends T[K] ? never : K) : K; /** Does this object contain required keys? */ export type HasRequiredKeys = FindRequiredKeys; diff --git a/packages/openapi-typescript-helpers/package.json b/packages/openapi-typescript-helpers/package.json index 1190d053b..f49ef2979 100644 --- a/packages/openapi-typescript-helpers/package.json +++ b/packages/openapi-typescript-helpers/package.json @@ -34,9 +34,8 @@ }, "scripts": { "build": "cp index.d.ts index.d.cts", - "lint": "pnpm run lint:js", - "lint:js": "eslint \"*.{js,ts}\"", - "lint:prettier": "prettier --check \"{src,test}/**/*\"", + "format": "biome format . --write", + "lint": "biome check .", "test": "tsc --noEmit" }, "devDependencies": { diff --git a/packages/openapi-typescript/.eslintignore b/packages/openapi-typescript/.eslintignore deleted file mode 100644 index a843dc44a..000000000 --- a/packages/openapi-typescript/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -test/fixtures diff --git a/packages/openapi-typescript/CONTRIBUTING.md b/packages/openapi-typescript/CONTRIBUTING.md index b8d148c70..4dc60aa71 100644 --- a/packages/openapi-typescript/CONTRIBUTING.md +++ b/packages/openapi-typescript/CONTRIBUTING.md @@ -119,7 +119,7 @@ npx vitest ### Running linting -To run ESLint on the project: +Linting is handled via [Biome](https://biomejs.dev), a faster ESLint replacement. It was installed with `pnpm i` and can be run with: ```bash pnpm run lint diff --git a/packages/openapi-typescript/bin/cli.js b/packages/openapi-typescript/bin/cli.js index 5259855b2..3d27f7c4c 100755 --- a/packages/openapi-typescript/bin/cli.js +++ b/packages/openapi-typescript/bin/cli.js @@ -4,16 +4,7 @@ import { loadConfig, findConfig, createConfig } from "@redocly/openapi-core"; import fs from "node:fs"; import path from "node:path"; import parser from "yargs-parser"; -import openapiTS, { - astToString, - c, - COMMENT_HEADER, - error, - formatTime, - warn, -} from "../dist/index.js"; - -/* eslint-disable no-console */ +import openapiTS, { astToString, c, COMMENT_HEADER, error, formatTime, warn } from "../dist/index.js"; const HELP = `Usage $ openapi-typescript [input] [options] @@ -46,22 +37,16 @@ const timeStart = performance.now(); const [, , ...args] = process.argv; if (args.includes("-ap")) { - errorAndExit( - `The -ap alias has been deprecated. Use "--additional-properties" instead.`, - ); + errorAndExit(`The -ap alias has been deprecated. Use "--additional-properties" instead.`); } if (args.includes("--immutable-types")) { errorAndExit(`The --immutable-types flag has been renamed to "--immutable".`); } if (args.includes("--support-array-length")) { - errorAndExit( - `The --support-array-length flag has been renamed to "--array-length".`, - ); + errorAndExit(`The --support-array-length flag has been renamed to "--array-length".`); } if (args.includes("-it")) { - errorAndExit( - `The -it alias has been deprecated. Use "--immutable-types" instead.`, - ); + errorAndExit(`The -it alias has been deprecated. Use "--immutable-types" instead.`); } const flags = parser(args, { @@ -121,11 +106,8 @@ function errorAndExit(message) { function done(input, output, time) { // final console output - console.log( - `🚀 ${c.green(`${input} → ${c.bold(output)}`)} ${c.dim( - `[${formatTime(time)}]`, - )}`, - ); + // biome-ignore lint/suspicious/noConsoleLog: this is a CLI and is expected to show output + console.log(`🚀 ${c.green(`${input} → ${c.bold(output)}`)} ${c.dim(`[${formatTime(time)}]`)}`); } async function main() { @@ -133,9 +115,7 @@ async function main() { console.info(HELP); process.exit(0); } - const packageJSON = JSON.parse( - fs.readFileSync(new URL("../package.json", import.meta.url), "utf8"), - ); + const packageJSON = JSON.parse(fs.readFileSync(new URL("../package.json", import.meta.url), "utf8")); if ("version" in flags) { console.info(`v${packageJSON.version}`); process.exit(0); @@ -149,9 +129,7 @@ async function main() { const input = flags._[0]; // load Redocly config - const maybeRedoc = findConfig( - flags.redoc ? path.dirname(flags.redoc) : undefined, - ); + const maybeRedoc = findConfig(flags.redoc ? path.dirname(flags.redoc) : undefined); const redoc = maybeRedoc ? await loadConfig({ configPath: maybeRedoc }) : await createConfig({}, { extends: ["minimal"] }); @@ -160,9 +138,7 @@ async function main() { const hasRedoclyApis = Object.keys(redoc?.apis ?? {}).length > 0; if (hasRedoclyApis) { if (input) { - warn( - "APIs are specified both in Redocly Config and CLI argument. Only using Redocly config.", - ); + warn("APIs are specified both in Redocly Config and CLI argument. Only using Redocly config."); } await Promise.all( Object.entries(redoc.apis).map(async ([name, api]) => { @@ -176,9 +152,7 @@ async function main() { if (!api[REDOC_CONFIG_KEY]?.output) { // TODO: remove in stable v7 if (api["openapi-ts"]) { - errorAndExit( - `Please rename "openapi-ts" to "x-openapi-ts" in your Redoc config.`, - ); + errorAndExit(`Please rename "openapi-ts" to "x-openapi-ts" in your Redoc config.`); } errorAndExit( @@ -218,7 +192,7 @@ async function main() { // throw error on glob if (input.includes("*")) { errorAndExit( - `Globbing has been deprecated in favor of redocly.yaml’s \`apis\` keys. See https://openapi-ts.pages.dev/cli/#multiple-schemas`, + "Globbing has been deprecated in favor of redocly.yaml’s `apis` keys. See https://openapi-ts.pages.dev/cli/#multiple-schemas", ); } const result = await generateSchema(new URL(input, CWD), { diff --git a/packages/openapi-typescript/biome.json b/packages/openapi-typescript/biome.json new file mode 100644 index 000000000..1c954280d --- /dev/null +++ b/packages/openapi-typescript/biome.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.7.0/schema.json", + "extends": ["../../biome.json"], + "files": { + "include": ["./bin/", "./src/", "./test/"], + "ignore": ["**/fixtures/**/*"] + } +} diff --git a/packages/openapi-typescript/package.json b/packages/openapi-typescript/package.json index ebeb04961..092b13f2a 100644 --- a/packages/openapi-typescript/package.json +++ b/packages/openapi-typescript/package.json @@ -25,17 +25,7 @@ "url": "https://github.com/drwpow/openapi-typescript", "directory": "packages/openapi-typescript" }, - "keywords": [ - "swagger", - "typescript", - "ts", - "dts", - "openapi", - "codegen", - "generation", - "openapi 3", - "node" - ], + "keywords": ["swagger", "typescript", "ts", "dts", "openapi", "codegen", "generation", "openapi 3", "node"], "bugs": { "url": "https://github.com/drwpow/openapi-typescript/issues" }, @@ -46,10 +36,8 @@ "build:cjs": "esbuild --bundle --platform=node --target=es2019 --outfile=dist/index.cjs --external:@redocly/ajv --external:@redocly/openapi-core --external:typescript src/index.ts", "dev": "tsc -p tsconfig.build.json --watch", "download:schemas": "vite-node ./scripts/download-schemas.ts", - "format": "prettier --write \"src/**/*\"", - "lint": "pnpm run \"/^lint:/\"", - "lint:js": "eslint \"{src,test}/**/*.{js,ts}\"", - "lint:prettier": "prettier --check \"src/**/*\"", + "format": "biome format . --write", + "lint": "biome check .", "test": "pnpm run \"/^test:/\"", "test:examples": "tsc -p tsconfig.examples.json --noEmit", "test:js": "vitest run", diff --git a/packages/openapi-typescript/scripts/download-schemas.ts b/packages/openapi-typescript/scripts/download-schemas.ts index 21768b236..e88fe928d 100644 --- a/packages/openapi-typescript/scripts/download-schemas.ts +++ b/packages/openapi-typescript/scripts/download-schemas.ts @@ -8,12 +8,11 @@ import { multiFile, singleFile } from "./schemas.js"; const ONE_DAY = 1000 * 60 * 60 * 24; const EXAMPLES_DIR = new URL("../examples/", import.meta.url); -/* eslint-disable no-console */ - export async function download() { const allSchemas = Object.keys({ ...singleFile, ...multiFile }); let done = 0; - console.log("Downloading schemas..."); // eslint-disable-line no-console + // biome-ignore lint/suspicious/noConsoleLog: this is a script + console.log("Downloading schemas..."); await Promise.all([ ...Object.entries(singleFile).map(async ([k, url]) => { const start = performance.now(); @@ -33,11 +32,8 @@ export async function download() { fs.mkdirSync(new URL(".", dest), { recursive: true }); fs.writeFileSync(dest, await result.text()); done++; - console.log( - `✔︎ [${done}/${allSchemas.length}] Downloaded ${k} (${Math.round( - performance.now() - start, - )}ms)`, - ); // eslint-disable-line no-console + // biome-ignore lint/suspicious/noConsoleLog: this is a script + console.log(`✔︎ [${done}/${allSchemas.length}] Downloaded ${k} (${Math.round(performance.now() - start)}ms)`); }), ...Object.entries(multiFile).map(async ([k, meta]) => { const start = performance.now(); @@ -53,14 +49,12 @@ export async function download() { }); await emitter.clone(fileURLToPath(new URL(k, EXAMPLES_DIR))); done++; - console.log( - `✔︎ [${done}/${allSchemas.length}] Downloaded ${k} (${Math.round( - performance.now() - start, - )}ms)`, - ); // eslint-disable-line no-console + // biome-ignore lint/suspicious/noConsoleLog: this is a script + console.log(`✔︎ [${done}/${allSchemas.length}] Downloaded ${k} (${Math.round(performance.now() - start)}ms)`); }), ]); - console.log("Downloading schemas done."); // eslint-disable-line no-console + // biome-ignore lint/suspicious/noConsoleLog: this is a script + console.log("Downloading schemas done."); process.exit(0); // helps process close in npm script } diff --git a/packages/openapi-typescript/scripts/update-examples.ts b/packages/openapi-typescript/scripts/update-examples.ts index 81a8e8f46..15400cf16 100644 --- a/packages/openapi-typescript/scripts/update-examples.ts +++ b/packages/openapi-typescript/scripts/update-examples.ts @@ -2,8 +2,6 @@ import { execa } from "execa"; import path from "node:path"; import { multiFile, singleFile } from "./schemas.js"; -/* eslint-disable no-console */ - async function generateSchemas() { const cwd = new URL("../", import.meta.url); const singleFileSchemas = Object.entries(singleFile); @@ -16,32 +14,27 @@ async function generateSchemas() { const start = performance.now(); try { - await execa( - "./bin/cli.js", - [`./examples/${name}${ext}`, "-o", `./examples/${name}.ts`], - { - cwd: - process.platform === "win32" - ? // execa/cross-spawn can not handle URL objects on Windows, so convert it to string and cut away the protocol - cwd.toString().slice("file:///".length) - : cwd, - }, - ); + await execa("./bin/cli.js", [`./examples/${name}${ext}`, "-o", `./examples/${name}.ts`], { + cwd: + process.platform === "win32" + ? // execa/cross-spawn can not handle URL objects on Windows, so convert it to string and cut away the protocol + cwd + .toString() + .slice("file:///".length) + : cwd, + }); schemasDoneCount++; const timeMs = Math.round(performance.now() - start); - console.log( - `✔︎ [${schemasDoneCount}/${schemaTotalCount}] Updated ${name} (${timeMs}ms)`, - ); + // biome-ignore lint/suspicious/noConsoleLog: this is a script + console.log(`✔︎ [${schemasDoneCount}/${schemaTotalCount}] Updated ${name} (${timeMs}ms)`); } catch (error) { - console.error( - `✘ [${schemasDoneCount}/${schemaTotalCount}] Failed to update ${name}`, - { error: error instanceof Error ? error.message : error }, - ); + console.error(`✘ [${schemasDoneCount}/${schemaTotalCount}] Failed to update ${name}`, { error: error instanceof Error ? error.message : error }); } }; + // biome-ignore lint/suspicious/noConsoleLog: this is a script console.log("Updating examples..."); await Promise.all([ @@ -55,6 +48,7 @@ async function generateSchemas() { }), ]); + // biome-ignore lint/suspicious/noConsoleLog: this is a script console.log("Updating examples done."); process.exit(0); // helps process close in npm script } diff --git a/packages/openapi-typescript/src/index.ts b/packages/openapi-typescript/src/index.ts index d9496de36..5af86c66b 100644 --- a/packages/openapi-typescript/src/index.ts +++ b/packages/openapi-typescript/src/index.ts @@ -42,9 +42,7 @@ export default async function openapiTS( options: OpenAPITSOptions = {} as Partial, ): Promise { if (!source) { - throw new Error( - "Empty schema. Please specify a URL, file path, or Redocly Config", - ); + throw new Error("Empty schema. Please specify a URL, file path, or Redocly Config"); } const redoc = @@ -60,10 +58,7 @@ export default async function openapiTS( const schema = await validateAndBundle(source, { redoc, - cwd: - options.cwd instanceof URL - ? options.cwd - : new URL(`file://${options.cwd ?? process.cwd()}/`), + cwd: options.cwd instanceof URL ? options.cwd : new URL(`file://${options.cwd ?? process.cwd()}/`), silent: options.silent ?? false, }); @@ -80,15 +75,11 @@ export default async function openapiTS( immutable: options.immutable ?? false, injectFooter: [], pathParamsAsTypes: options.pathParamsAsTypes ?? false, - postTransform: - typeof options.postTransform === "function" - ? options.postTransform - : undefined, + postTransform: typeof options.postTransform === "function" ? options.postTransform : undefined, propertiesRequiredByDefault: options.propertiesRequiredByDefault ?? false, redoc, silent: options.silent ?? false, - transform: - typeof options.transform === "function" ? options.transform : undefined, + transform: typeof options.transform === "function" ? options.transform : undefined, resolve($ref) { return resolveRef(schema, $ref, { silent: options.silent ?? false }); }, @@ -96,11 +87,7 @@ export default async function openapiTS( const transformT = performance.now(); const result = transformSchema(schema, ctx); - debug( - "Completed AST transformation for entire document", - "ts", - performance.now() - transformT, - ); + debug("Completed AST transformation for entire document", "ts", performance.now() - transformT); return result; } diff --git a/packages/openapi-typescript/src/lib/redoc.ts b/packages/openapi-typescript/src/lib/redoc.ts index 7580a9fd5..4eb991375 100644 --- a/packages/openapi-typescript/src/lib/redoc.ts +++ b/packages/openapi-typescript/src/lib/redoc.ts @@ -23,12 +23,9 @@ interface ParseSchemaOptions { resolver: BaseResolver; } -export async function parseSchema( - schema: unknown, - { absoluteRef, resolver }: ParseSchemaOptions, -): Promise { +export async function parseSchema(schema: unknown, { absoluteRef, resolver }: ParseSchemaOptions): Promise { if (!schema) { - throw new Error(`Can’t parse empty schema`); + throw new Error("Can’t parse empty schema"); } if (schema instanceof URL) { const result = await resolver.resolveDocument(null, absoluteRef, true); @@ -56,11 +53,7 @@ export async function parseSchema( } if (typeof schema === "string") { // URL - if ( - schema.startsWith("http://") || - schema.startsWith("https://") || - schema.startsWith("file://") - ) { + if (schema.startsWith("http://") || schema.startsWith("https://") || schema.startsWith("file://")) { const url = new URL(schema); return parseSchema(url, { absoluteRef: url.protocol === "file:" ? fileURLToPath(url) : url.href, @@ -79,19 +72,11 @@ export async function parseSchema( } if (typeof schema === "object" && !Array.isArray(schema)) { return { - source: new Source( - absoluteRef, - JSON.stringify(schema), - "application/json", - ), + source: new Source(absoluteRef, JSON.stringify(schema), "application/json"), parsed: schema, }; } - throw new Error( - `Expected string, object, or Buffer. Got ${ - Array.isArray(schema) ? "Array" : typeof schema - }`, - ); + throw new Error(`Expected string, object, or Buffer. Got ${Array.isArray(schema) ? "Array" : typeof schema}`); } /** @@ -104,12 +89,9 @@ export async function validateAndBundle( const redocConfigT = performance.now(); debug("Loaded Redoc config", "redoc", performance.now() - redocConfigT); const redocParseT = performance.now(); - let absoluteRef = fileURLToPath( - new URL(options?.cwd ?? `file://${process.cwd()}/`), - ); + let absoluteRef = fileURLToPath(new URL(options?.cwd ?? `file://${process.cwd()}/`)); if (source instanceof URL) { - absoluteRef = - source.protocol === "file:" ? fileURLToPath(source) : source.href; + absoluteRef = source.protocol === "file:" ? fileURLToPath(source) : source.href; } const resolver = new BaseResolver(options.redoc.resolve); const document = await parseSchema(source, { @@ -119,7 +101,7 @@ export async function validateAndBundle( debug("Parsed schema", "redoc", performance.now() - redocParseT); // 1. check for OpenAPI 3 or greater - const openapiVersion = parseFloat(document.parsed.openapi); + const openapiVersion = Number.parseFloat(document.parsed.openapi); if ( document.parsed.swagger || !document.parsed.openapi || @@ -128,17 +110,10 @@ export async function validateAndBundle( openapiVersion >= 4 ) { if (document.parsed.swagger) { - throw new Error( - "Unsupported Swagger version: 2.x. Use OpenAPI 3.x instead.", - ); - } else if ( - document.parsed.openapi || - openapiVersion < 3 || - openapiVersion >= 4 - ) { - throw new Error( - `Unsupported OpenAPI version: ${document.parsed.openapi}`, - ); + throw new Error("Unsupported Swagger version: 2.x. Use OpenAPI 3.x instead."); + } + if (document.parsed.openapi || openapiVersion < 3 || openapiVersion >= 4) { + throw new Error(`Unsupported OpenAPI version: ${document.parsed.openapi}`); } throw new Error("Unsupported schema format, expected `openapi: 3.x`"); } diff --git a/packages/openapi-typescript/src/lib/ts.ts b/packages/openapi-typescript/src/lib/ts.ts index 6084744b0..812cfd4a4 100644 --- a/packages/openapi-typescript/src/lib/ts.ts +++ b/packages/openapi-typescript/src/lib/ts.ts @@ -5,30 +5,16 @@ export const JS_PROPERTY_INDEX_RE = /^[A-Za-z_$][A-Za-z_$0-9]*$/; export const JS_ENUM_INVALID_CHARS_RE = /[^A-Za-z_$0-9]+(.)?/g; export const JS_PROPERTY_INDEX_INVALID_CHARS_RE = /[^A-Za-z_$0-9]+/g; -export const BOOLEAN = ts.factory.createKeywordTypeNode( - ts.SyntaxKind.BooleanKeyword, -); +export const BOOLEAN = ts.factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword); export const FALSE = ts.factory.createLiteralTypeNode(ts.factory.createFalse()); -export const NEVER = ts.factory.createKeywordTypeNode( - ts.SyntaxKind.NeverKeyword, -); +export const NEVER = ts.factory.createKeywordTypeNode(ts.SyntaxKind.NeverKeyword); export const NULL = ts.factory.createLiteralTypeNode(ts.factory.createNull()); -export const NUMBER = ts.factory.createKeywordTypeNode( - ts.SyntaxKind.NumberKeyword, -); -export const QUESTION_TOKEN = ts.factory.createToken( - ts.SyntaxKind.QuestionToken, -); -export const STRING = ts.factory.createKeywordTypeNode( - ts.SyntaxKind.StringKeyword, -); +export const NUMBER = ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword); +export const QUESTION_TOKEN = ts.factory.createToken(ts.SyntaxKind.QuestionToken); +export const STRING = ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword); export const TRUE = ts.factory.createLiteralTypeNode(ts.factory.createTrue()); -export const UNDEFINED = ts.factory.createKeywordTypeNode( - ts.SyntaxKind.UndefinedKeyword, -); -export const UNKNOWN = ts.factory.createKeywordTypeNode( - ts.SyntaxKind.UnknownKeyword, -); +export const UNDEFINED = ts.factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword); +export const UNKNOWN = ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword); const LB_RE = /\r?\n/g; const COMMENT_RE = /\*\//g; @@ -52,15 +38,8 @@ export interface AnnotatedSchemaObject { * @see {comment} for output examples * @returns void if not comments or jsdoc format comment string */ -export function addJSDocComment( - schemaObject: AnnotatedSchemaObject, - node: ts.PropertySignature, -): void { - if ( - !schemaObject || - typeof schemaObject !== "object" || - Array.isArray(schemaObject) - ) { +export function addJSDocComment(schemaObject: AnnotatedSchemaObject, node: ts.PropertySignature): void { + if (!schemaObject || typeof schemaObject !== "object" || Array.isArray(schemaObject)) { return; } const output: string[] = []; @@ -93,9 +72,7 @@ export function addJSDocComment( continue; } const serialized = - typeof schemaObject[field] === "object" - ? JSON.stringify(schemaObject[field], null, 2) - : schemaObject[field]; + typeof schemaObject[field] === "object" ? JSON.stringify(schemaObject[field], null, 2) : schemaObject[field]; output.push(`@${field} ${String(serialized).replace(LB_RE, "\n * ")}`); } @@ -112,7 +89,7 @@ export function addJSDocComment( } else if (typeof schemaObject.type === "string") { type = schemaObject.type; } - output.push(`@enum {${type}${schemaObject.nullable ? `|null` : ""}}`); + output.push(`@enum {${type}${schemaObject.nullable ? "|null" : ""}}`); } // attach comment if it has content @@ -140,18 +117,17 @@ export function oapiRef(path: string): ts.TypeNode { if (pointer.length === 0) { throw new Error(`Error parsing $ref: ${path}. Is this a valid $ref?`); } - let t: ts.TypeReferenceNode | ts.IndexedAccessTypeNode = - ts.factory.createTypeReferenceNode( - ts.factory.createIdentifier(String(pointer[0])), - ); + let t: ts.TypeReferenceNode | ts.IndexedAccessTypeNode = ts.factory.createTypeReferenceNode( + ts.factory.createIdentifier(String(pointer[0])), + ); if (pointer.length > 1) { for (let i = 1; i < pointer.length; i++) { t = ts.factory.createIndexedAccessTypeNode( t, ts.factory.createLiteralTypeNode( - typeof pointer[i]! === "number" - ? ts.factory.createNumericLiteral(pointer[i]!) - : ts.factory.createStringLiteral(pointer[i]! as string), + typeof pointer[i] === "number" + ? ts.factory.createNumericLiteral(pointer[i]) + : ts.factory.createStringLiteral(pointer[i] as string), ), ); } @@ -179,9 +155,7 @@ export function astToString( ); // @ts-expect-error it’s OK to overwrite statements once - sourceFile.statements = ts.factory.createNodeArray( - Array.isArray(ast) ? ast : [ast], - ); + sourceFile.statements = ts.factory.createNodeArray(Array.isArray(ast) ? ast : [ast]); const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed, @@ -199,7 +173,7 @@ export function stringToAST(source: string): unknown[] { /* languageVersion */ ts.ScriptTarget.ESNext, /* setParentNodes */ undefined, /* scriptKind */ undefined, - ).statements as any; // eslint-disable-line @typescript-eslint/no-explicit-any + ).statements as any; } /** @@ -234,30 +208,21 @@ export function tsEnum( ) { let enumName = name.replace(JS_ENUM_INVALID_CHARS_RE, (c) => { const last = c[c.length - 1]; - return JS_PROPERTY_INDEX_INVALID_CHARS_RE.test(last) - ? "" - : last.toUpperCase(); + return JS_PROPERTY_INDEX_INVALID_CHARS_RE.test(last) ? "" : last.toUpperCase(); }); if (Number(name[0]) >= 0) { enumName = `Value${name}`; } enumName = `${enumName[0].toUpperCase()}${enumName.substring(1)}`; return ts.factory.createEnumDeclaration( - /* modifiers */ options - ? tsModifiers({ export: options.export ?? false }) - : undefined, + /* modifiers */ options ? tsModifiers({ export: options.export ?? false }) : undefined, /* name */ enumName, - /* members */ members.map((value, i) => - tsEnumMember(value, metadata?.[i]), - ), + /* members */ members.map((value, i) => tsEnumMember(value, metadata?.[i])), ); } /** Sanitize TS enum member expression */ -export function tsEnumMember( - value: string | number, - metadata: { name?: string; description?: string } = {}, -) { +export function tsEnumMember(value: string | number, metadata: { name?: string; description?: string } = {}) { let name = metadata.name ?? String(value); if (!JS_PROPERTY_INDEX_RE.test(name)) { if (Number(name[0]) >= 0) { @@ -268,7 +233,7 @@ export function tsEnumMember( name = name.replace(JS_PROPERTY_INDEX_INVALID_CHARS_RE, "_"); } - let member; + let member: ts.EnumMember; if (typeof value === "number") { const literal = value < 0 @@ -280,13 +245,10 @@ export function tsEnumMember( member = ts.factory.createEnumMember(name, literal); } else { - member = ts.factory.createEnumMember( - name, - ts.factory.createStringLiteral(value), - ); + member = ts.factory.createEnumMember(name, ts.factory.createStringLiteral(value)); } - if (metadata.description == undefined) { + if (metadata.description === undefined) { return member; } @@ -329,14 +291,10 @@ export function tsIsPrimitive(type: ts.TypeNode): boolean { export function tsLiteral(value: unknown): ts.TypeNode { if (typeof value === "string") { // workaround for UTF-8: https://github.com/microsoft/TypeScript/issues/36174 - return ts.factory.createIdentifier( - JSON.stringify(value), - ) as unknown as ts.TypeNode; + return ts.factory.createIdentifier(JSON.stringify(value)) as unknown as ts.TypeNode; } if (typeof value === "number") { - return ts.factory.createLiteralTypeNode( - ts.factory.createNumericLiteral(value), - ); + return ts.factory.createLiteralTypeNode(ts.factory.createNumericLiteral(value)); } if (typeof value === "boolean") { return value === true ? TRUE : FALSE; @@ -348,9 +306,7 @@ export function tsLiteral(value: unknown): ts.TypeNode { if (value.length === 0) { return ts.factory.createArrayTypeNode(NEVER); } - return ts.factory.createTupleTypeNode( - value.map((v: unknown) => tsLiteral(v)), - ); + return ts.factory.createTupleTypeNode(value.map((v: unknown) => tsLiteral(v))); } if (typeof value === "object") { const keys: ts.TypeElement[] = []; @@ -364,9 +320,7 @@ export function tsLiteral(value: unknown): ts.TypeNode { ), ); } - return keys.length - ? ts.factory.createTypeLiteralNode(keys) - : tsRecord(STRING, NEVER); + return keys.length ? ts.factory.createTypeLiteralNode(keys) : tsRecord(STRING, NEVER); } return UNKNOWN; } @@ -393,27 +347,22 @@ export function tsNullable(types: ts.TypeNode[]): ts.TypeNode { /** Create a TS Omit type */ export function tsOmit(type: ts.TypeNode, keys: string[]): ts.TypeNode { - return ts.factory.createTypeReferenceNode( - ts.factory.createIdentifier("Omit"), - [type, ts.factory.createUnionTypeNode(keys.map((k) => tsLiteral(k)))], - ); + return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("Omit"), [ + type, + ts.factory.createUnionTypeNode(keys.map((k) => tsLiteral(k))), + ]); } /** Create a TS Record type */ export function tsRecord(key: ts.TypeNode, value: ts.TypeNode) { - return ts.factory.createTypeReferenceNode( - ts.factory.createIdentifier("Record"), - [key, value], - ); + return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("Record"), [key, value]); } /** Create a valid property index */ export function tsPropertyIndex(index: string | number) { if ( (typeof index === "number" && !(index < 0)) || - (typeof index === "string" && - String(Number(index)) === index && - index[0] !== "-") + (typeof index === "string" && String(Number(index)) === index && index[0] !== "-") ) { return ts.factory.createNumericLiteral(index); } @@ -444,21 +393,13 @@ export function tsWithRequired( } // inject helper, if needed - if ( - !injectFooter.some( - (node) => - ts.isTypeAliasDeclaration(node) && - node?.name?.escapedText === "WithRequired", - ) - ) { - const helper = stringToAST( - `type WithRequired = T & { [P in K]-?: T[P] };`, - )[0] as any; // eslint-disable-line @typescript-eslint/no-explicit-any + if (!injectFooter.some((node) => ts.isTypeAliasDeclaration(node) && node?.name?.escapedText === "WithRequired")) { + const helper = stringToAST("type WithRequired = T & { [P in K]-?: T[P] };")[0] as any; injectFooter.push(helper); } - return ts.factory.createTypeReferenceNode( - ts.factory.createIdentifier("WithRequired"), - [type, tsUnion(keys.map((k) => tsLiteral(k)))], - ); + return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("WithRequired"), [ + type, + tsUnion(keys.map((k) => tsLiteral(k))), + ]); } diff --git a/packages/openapi-typescript/src/lib/utils.ts b/packages/openapi-typescript/src/lib/utils.ts index 01f4e9af2..4b764b385 100644 --- a/packages/openapi-typescript/src/lib/utils.ts +++ b/packages/openapi-typescript/src/lib/utils.ts @@ -1,17 +1,8 @@ -import { - escapePointer, - parseRef, -} from "@redocly/openapi-core/lib/ref-utils.js"; +import { escapePointer, parseRef } from "@redocly/openapi-core/lib/ref-utils.js"; import c from "ansi-colors"; import supportsColor from "supports-color"; import ts from "typescript"; -import type { - DiscriminatorObject, - OpenAPI3, - OpenAPITSOptions, - ReferenceObject, - SchemaObject, -} from "../types.js"; +import type { DiscriminatorObject, OpenAPI3, OpenAPITSOptions, ReferenceObject, SchemaObject } from "../types.js"; import { tsLiteral, tsModifiers, tsPropertyIndex } from "./ts.js"; if (!supportsColor.stdout || supportsColor.stdout.hasBasic === false) { @@ -33,14 +24,12 @@ export function createDiscriminatorProperty( { path, readonly = false }: { path: string; readonly?: boolean }, ): ts.TypeElement { // get the inferred propertyName value from the last section of the path (as the spec suggests to do) - let value = parseRef(path).pointer.pop()!; + let value = parseRef(path).pointer.pop(); // if mapping, and there’s a match, use this rather than the inferred name if (discriminator.mapping) { // Mapping value can either be a fully-qualified ref (#/components/schemas/XYZ) or a schema name (XYZ) const matchedValue = Object.entries(discriminator.mapping).find( - ([, v]) => - (!v.startsWith("#") && v === value) || - (v.startsWith("#") && parseRef(v).pointer.pop() === value), + ([, v]) => (!v.startsWith("#") && v === value) || (v.startsWith("#") && parseRef(v).pointer.pop() === value), ); if (matchedValue) { value = matchedValue[0]; // why was this designed backwards!? @@ -57,10 +46,10 @@ export function createDiscriminatorProperty( } /** Create a $ref pointer (even from other $refs) */ -export function createRef(parts: (number | string)[]): string { +export function createRef(parts: (number | string | undefined | null)[]): string { let pointer = "#"; for (const part of parts) { - if (!part) { + if (part === undefined || part === null || part === "") { continue; } const maybeRef = parseRef(String(part)).pointer; @@ -82,8 +71,7 @@ export function debug(msg: string, group?: string, time?: number) { (!group || process.env.DEBUG === "*" || process.env.DEBUG === "openapi-ts:*" || - process.env.DEBUG.toLocaleLowerCase() === - `openapi-ts:${group.toLocaleLowerCase()}`) + process.env.DEBUG.toLocaleLowerCase() === `openapi-ts:${group.toLocaleLowerCase()}`) ) { const groupColor = (group && DEBUG_GROUPS[group]) || c.whiteBright; const groupName = groupColor(`openapi-ts:${group ?? "info"}`); @@ -91,14 +79,13 @@ export function debug(msg: string, group?: string, time?: number) { if (typeof time === "number") { timeFormatted = c.green(` ${formatTime(time)} `); } - // eslint-disable-next-line no-console console.debug(` ${c.bold(groupName)}${timeFormatted}${msg}`); } } /** Print error message */ export function error(msg: string) { - console.error(c.red(` ✘ ${msg}`)); // eslint-disable-line no-console + console.error(c.red(` ✘ ${msg}`)); } /** Format a performance log in a friendly format */ @@ -106,7 +93,8 @@ export function formatTime(t: number) { if (typeof t === "number") { if (t < 1000) { return `${Math.round(10 * t) / 10}ms`; - } else if (t < 60000) { + } + if (t < 60000) { return `${Math.round(t / 100) / 10}s`; } return `${Math.round(t / 6000) / 10}m`; @@ -127,15 +115,11 @@ export function getEntries( entries.sort(([a], [b]) => a.localeCompare(b, "en-us", { numeric: true })); } if (options?.excludeDeprecated) { - entries = entries.filter( - ([, v]) => - !(v && typeof v === "object" && "deprecated" in v && v.deprecated), - ); + entries = entries.filter(([, v]) => !(v && typeof v === "object" && "deprecated" in v && v.deprecated)); } return entries; } -/* eslint-disable @typescript-eslint/no-explicit-any */ /** resolve a $ref in a schema */ export function resolveRef( schema: any, @@ -171,16 +155,13 @@ export function resolveRef( return node; } -function createDiscriminatorEnum( - values: string[], - prevSchema?: SchemaObject, -): SchemaObject { +function createDiscriminatorEnum(values: string[], prevSchema?: SchemaObject): SchemaObject { return { type: "string", enum: values, description: prevSchema?.description ? `${prevSchema.description} (enum property replaced by openapi-typescript)` - : `discriminator enum property added by openapi-typescript`, + : "discriminator enum property added by openapi-typescript", }; } @@ -209,11 +190,7 @@ function patchDiscriminatorEnum( }); return true; - } else if ( - typeof resolvedSchema === "object" && - "type" in resolvedSchema && - resolvedSchema.type === "object" - ) { + } else if (typeof resolvedSchema === "object" && "type" in resolvedSchema && resolvedSchema.type === "object") { // if the schema is an object, we can apply the discriminator enums to its properties if (!resolvedSchema.properties) { resolvedSchema.properties = {}; @@ -227,11 +204,10 @@ function patchDiscriminatorEnum( } // add/replace the discriminator enum property - resolvedSchema.properties[discriminator.propertyName] = - createDiscriminatorEnum( - values, - resolvedSchema.properties[discriminator.propertyName], - ); + resolvedSchema.properties[discriminator.propertyName] = createDiscriminatorEnum( + values, + resolvedSchema.properties[discriminator.propertyName] as SchemaObject, + ); return true; } @@ -246,16 +222,10 @@ function patchDiscriminatorEnum( return false; } -type InternalDiscriminatorMapping = Record< - string, - { inferred?: string; defined?: string[] } ->; +type InternalDiscriminatorMapping = Record; /** Return a key–value map of discriminator objects found in a schema */ -export function scanDiscriminators( - schema: OpenAPI3, - options: OpenAPITSOptions, -) { +export function scanDiscriminators(schema: OpenAPI3, options: OpenAPITSOptions) { // all discriminator objects found in the schema const objects: Record = {}; @@ -328,17 +298,11 @@ export function scanDiscriminators( // prefer defined values over automatically inferred ones // the inferred enum values from the schema might not represent the actual enum values of the discriminator, // so if we have defined values, use them instead + // biome-ignore lint/style/noNonNullAssertion: we just checked for this const mappedValues = defined ?? [inferred!]; if ( - patchDiscriminatorEnum( - schema, - mappedRef, - mappedValues, - discriminator, - ref, - options, - ) + patchDiscriminatorEnum(schema as unknown as SchemaObject, mappedRef, mappedValues, discriminator, ref, options) ) { refsHandled.push(mappedRef); } @@ -373,7 +337,7 @@ export function scanDiscriminators( if (mappedValues.length > 0) { if ( patchDiscriminatorEnum( - schema, + schema as unknown as SchemaObject, ref, mappedValues, discriminator, @@ -422,6 +386,6 @@ export function walk( /** Print warning message */ export function warn(msg: string, silent = false) { if (!silent) { - console.warn(c.yellow(` ⚠ ${msg}`)); // eslint-disable-line no-console + console.warn(c.yellow(` ⚠ ${msg}`)); } } diff --git a/packages/openapi-typescript/src/transform/components-object.ts b/packages/openapi-typescript/src/transform/components-object.ts index aa88d5e27..99bcb478a 100644 --- a/packages/openapi-typescript/src/transform/components-object.ts +++ b/packages/openapi-typescript/src/transform/components-object.ts @@ -1,18 +1,7 @@ import ts from "typescript"; -import { - NEVER, - QUESTION_TOKEN, - addJSDocComment, - tsModifiers, - tsPropertyIndex, -} from "../lib/ts.js"; +import { NEVER, QUESTION_TOKEN, addJSDocComment, tsModifiers, tsPropertyIndex } from "../lib/ts.js"; import { createRef, debug, getEntries } from "../lib/utils.js"; -import type { - ComponentsObject, - GlobalContext, - SchemaObject, - TransformNodeOptions, -} from "../types.js"; +import type { ComponentsObject, GlobalContext, SchemaObject, TransformNodeOptions } from "../types.js"; import transformHeaderObject from "./header-object.js"; import transformParameterObject from "./parameter-object.js"; import transformPathItemObject from "./path-item-object.js"; @@ -20,15 +9,9 @@ import transformRequestBodyObject from "./request-body-object.js"; import transformResponseObject from "./response-object.js"; import transformSchemaObject from "./schema-object.js"; -type ComponentTransforms = keyof Omit< - ComponentsObject, - "examples" | "securitySchemes" | "links" | "callbacks" ->; +type ComponentTransforms = keyof Omit; -const transformers: Record< - ComponentTransforms, - (node: any, options: TransformNodeOptions) => ts.TypeNode // eslint-disable-line @typescript-eslint/no-explicit-any -> = { +const transformers: Record ts.TypeNode> = { schemas: transformSchemaObject, responses: transformResponseObject, parameters: transformParameterObject, @@ -41,10 +24,7 @@ const transformers: Record< * Transform the ComponentsObject (4.8.7) * @see https://spec.openapis.org/oas/latest.html#components-object */ -export default function transformComponentsObject( - componentsObject: ComponentsObject, - ctx: GlobalContext, -): ts.TypeNode { +export default function transformComponentsObject(componentsObject: ComponentsObject, ctx: GlobalContext): ts.TypeNode { const type: ts.TypeElement[] = []; for (const key of Object.keys(transformers) as ComponentTransforms[]) { @@ -80,7 +60,7 @@ export default function transformComponentsObject( /* questionToken */ hasQuestionToken ? QUESTION_TOKEN : undefined, /* type */ subType, ); - addJSDocComment(item as unknown as any, property); // eslint-disable-line @typescript-eslint/no-explicit-any + addJSDocComment(item as unknown as any, property); items.push(property); } } @@ -89,17 +69,11 @@ export default function transformComponentsObject( /* modifiers */ undefined, /* name */ tsPropertyIndex(key), /* questionToken */ undefined, - /* type */ items.length - ? ts.factory.createTypeLiteralNode(items) - : NEVER, + /* type */ items.length ? ts.factory.createTypeLiteralNode(items) : NEVER, ), ); - debug( - `Transformed components → ${key}`, - "ts", - performance.now() - componentT, - ); + debug(`Transformed components → ${key}`, "ts", performance.now() - componentT); } return ts.factory.createTypeLiteralNode(type); diff --git a/packages/openapi-typescript/src/transform/header-object.ts b/packages/openapi-typescript/src/transform/header-object.ts index 7a9f9b226..e4d3b3e73 100644 --- a/packages/openapi-typescript/src/transform/header-object.ts +++ b/packages/openapi-typescript/src/transform/header-object.ts @@ -1,11 +1,6 @@ import { escapePointer } from "@redocly/openapi-core/lib/ref-utils.js"; import ts from "typescript"; -import { - addJSDocComment, - tsModifiers, - tsPropertyIndex, - UNKNOWN, -} from "../lib/ts.js"; +import { addJSDocComment, tsModifiers, tsPropertyIndex, UNKNOWN } from "../lib/ts.js"; import { getEntries } from "../lib/utils.js"; import type { HeaderObject, TransformNodeOptions } from "../types.js"; import transformMediaTypeObject from "./media-type-object.js"; @@ -15,20 +10,14 @@ import transformSchemaObject from "./schema-object.js"; * Transform HeaderObject nodes (4.8.21) * @see https://spec.openapis.org/oas/v3.1.0#header-object */ -export default function transformHeaderObject( - headerObject: HeaderObject, - options: TransformNodeOptions, -): ts.TypeNode { +export default function transformHeaderObject(headerObject: HeaderObject, options: TransformNodeOptions): ts.TypeNode { if (headerObject.schema) { return transformSchemaObject(headerObject.schema, options); } if (headerObject.content) { const type: ts.TypeElement[] = []; - for (const [contentType, mediaTypeObject] of getEntries( - headerObject.content, - options.ctx, - )) { + for (const [contentType, mediaTypeObject] of getEntries(headerObject.content, options.ctx)) { const nextPath = `${options.path ?? "#"}/${escapePointer(contentType)}`; const mediaType = "$ref" in mediaTypeObject diff --git a/packages/openapi-typescript/src/transform/index.ts b/packages/openapi-typescript/src/transform/index.ts index 949d3c3fb..89ba043d4 100644 --- a/packages/openapi-typescript/src/transform/index.ts +++ b/packages/openapi-typescript/src/transform/index.ts @@ -1,7 +1,4 @@ -import ts, { - type InterfaceDeclaration, - type TypeLiteralNode, -} from "typescript"; +import ts, { type InterfaceDeclaration, type TypeLiteralNode } from "typescript"; import { NEVER, STRING, tsModifiers, tsRecord } from "../lib/ts.js"; import { createRef, debug } from "../lib/utils.js"; import type { GlobalContext, OpenAPI3 } from "../types.js"; @@ -10,20 +7,13 @@ import transformPathsObject from "./paths-object.js"; import transformSchemaObject from "./schema-object.js"; import transformWebhooksObject from "./webhooks-object.js"; -type SchemaTransforms = keyof Pick< - OpenAPI3, - "paths" | "webhooks" | "components" | "$defs" ->; +type SchemaTransforms = keyof Pick; -const transformers: Record< - SchemaTransforms, - (node: any, options: GlobalContext) => ts.TypeNode // eslint-disable-line @typescript-eslint/no-explicit-any -> = { +const transformers: Record ts.TypeNode> = { paths: transformPathsObject, webhooks: transformWebhooksObject, components: transformComponentsObject, - $defs: (node, options) => - transformSchemaObject(node, { path: createRef(["$defs"]), ctx: options }), + $defs: (node, options) => transformSchemaObject(node, { path: createRef(["$defs"]), ctx: options }), }; export default function transformSchema(schema: OpenAPI3, ctx: GlobalContext) { @@ -71,10 +61,7 @@ export default function transformSchema(schema: OpenAPI3, ctx: GlobalContext) { // inject let hasOperations = false; for (const injectedType of ctx.injectFooter) { - if ( - !hasOperations && - (injectedType as InterfaceDeclaration)?.name?.escapedText === "operations" - ) { + if (!hasOperations && (injectedType as InterfaceDeclaration)?.name?.escapedText === "operations") { hasOperations = true; } type.push(injectedType); diff --git a/packages/openapi-typescript/src/transform/operation-object.ts b/packages/openapi-typescript/src/transform/operation-object.ts index c0f58bd54..16f3c25e8 100644 --- a/packages/openapi-typescript/src/transform/operation-object.ts +++ b/packages/openapi-typescript/src/transform/operation-object.ts @@ -1,18 +1,7 @@ import ts from "typescript"; -import { - NEVER, - QUESTION_TOKEN, - addJSDocComment, - oapiRef, - tsModifiers, - tsPropertyIndex, -} from "../lib/ts.js"; +import { NEVER, QUESTION_TOKEN, addJSDocComment, oapiRef, tsModifiers, tsPropertyIndex } from "../lib/ts.js"; import { createRef } from "../lib/utils.js"; -import type { - OperationObject, - RequestBodyObject, - TransformNodeOptions, -} from "../types.js"; +import type { OperationObject, RequestBodyObject, TransformNodeOptions } from "../types.js"; import { transformParametersArray } from "./parameters-array.js"; import transformRequestBodyObject from "./request-body-object.js"; import transformResponsesObject from "./responses-object.js"; @@ -28,9 +17,7 @@ export default function transformOperationObject( const type: ts.TypeElement[] = []; // parameters - type.push( - ...transformParametersArray(operationObject.parameters ?? [], options), - ); + type.push(...transformParametersArray(operationObject.parameters ?? [], options)); // requestBody if (operationObject.requestBody) { @@ -39,13 +26,11 @@ export default function transformOperationObject( ? oapiRef(operationObject.requestBody.$ref) : transformRequestBodyObject(operationObject.requestBody, { ...options, - path: createRef([options.path!, "requestBody"]), + path: createRef([options.path, "requestBody"]), }); const required = !!( "$ref" in operationObject.requestBody - ? options.ctx.resolve( - operationObject.requestBody.$ref, - ) + ? options.ctx.resolve(operationObject.requestBody.$ref) : operationObject.requestBody )?.required; const property = ts.factory.createPropertySignature( @@ -73,10 +58,7 @@ export default function transformOperationObject( /* modifiers */ tsModifiers({ readonly: options.ctx.immutable }), /* name */ tsPropertyIndex("responses"), /* questionToken */ undefined, - /* type */ transformResponsesObject( - operationObject.responses ?? {}, - options, - ), + /* type */ transformResponsesObject(operationObject.responses ?? {}, options), ), ); @@ -91,9 +73,7 @@ export function injectOperationObject( ): void { // find or create top-level operations interface let operations = options.ctx.injectFooter.find( - (node) => - ts.isInterfaceDeclaration(node) && - (node as ts.InterfaceDeclaration).name.text === "operations", + (node) => ts.isInterfaceDeclaration(node) && (node as ts.InterfaceDeclaration).name.text === "operations", ) as unknown as ts.InterfaceDeclaration; if (!operations) { operations = ts.factory.createInterfaceDeclaration( diff --git a/packages/openapi-typescript/src/transform/parameter-object.ts b/packages/openapi-typescript/src/transform/parameter-object.ts index 411c8808c..43412e8a6 100644 --- a/packages/openapi-typescript/src/transform/parameter-object.ts +++ b/packages/openapi-typescript/src/transform/parameter-object.ts @@ -11,7 +11,5 @@ export default function transformParameterObject( parameterObject: ParameterObject, options: TransformNodeOptions, ): ts.TypeNode { - return parameterObject.schema - ? transformSchemaObject(parameterObject.schema, options) - : STRING; // assume a parameter is a string by default rather than "unknown" + return parameterObject.schema ? transformSchemaObject(parameterObject.schema, options) : STRING; // assume a parameter is a string by default rather than "unknown" } diff --git a/packages/openapi-typescript/src/transform/parameters-array.ts b/packages/openapi-typescript/src/transform/parameters-array.ts index c91222653..6967b67fb 100644 --- a/packages/openapi-typescript/src/transform/parameters-array.ts +++ b/packages/openapi-typescript/src/transform/parameters-array.ts @@ -1,18 +1,7 @@ import ts from "typescript"; -import { - NEVER, - QUESTION_TOKEN, - addJSDocComment, - oapiRef, - tsModifiers, - tsPropertyIndex, -} from "../lib/ts.js"; +import { NEVER, QUESTION_TOKEN, addJSDocComment, oapiRef, tsModifiers, tsPropertyIndex } from "../lib/ts.js"; import { createRef } from "../lib/utils.js"; -import type { - ParameterObject, - ReferenceObject, - TransformNodeOptions, -} from "../types.js"; +import type { ParameterObject, ReferenceObject, TransformNodeOptions } from "../types.js"; import transformParameterObject from "./parameter-object.js"; /** @@ -26,30 +15,19 @@ export function transformParametersArray( // parameters const paramType: ts.TypeElement[] = []; - for (const paramIn of [ - "query", - "header", - "path", - "cookie", - ] as ParameterObject["in"][]) { + for (const paramIn of ["query", "header", "path", "cookie"] as ParameterObject["in"][]) { const paramLocType: ts.TypeElement[] = []; let operationParameters = parametersArray.map((param) => ({ original: param, - resolved: - "$ref" in param - ? options.ctx.resolve(param.$ref) - : param, + resolved: "$ref" in param ? options.ctx.resolve(param.$ref) : param, })); // this is the only array type in the spec, so we have to one-off sort here if (options.ctx.alphabetize) { - operationParameters.sort((a, b) => - (a.resolved?.name ?? "").localeCompare(b.resolved?.name ?? ""), - ); + operationParameters.sort((a, b) => (a.resolved?.name ?? "").localeCompare(b.resolved?.name ?? "")); } if (options.ctx.excludeDeprecated) { operationParameters = operationParameters.filter( - ({ resolved }) => - !resolved?.deprecated && !resolved?.schema?.deprecated, + ({ resolved }) => !resolved?.deprecated && !resolved?.schema?.deprecated, ); } for (const { original, resolved } of operationParameters) { @@ -65,12 +43,7 @@ export function transformParametersArray( ? oapiRef(original.$ref) : transformParameterObject(resolved as ParameterObject, { ...options, - path: createRef([ - options.path ?? "", - "parameters", - resolved.in, - resolved.name, - ]), + path: createRef([options.path, "parameters", resolved.in, resolved.name]), }); const property = ts.factory.createPropertySignature( /* modifiers */ tsModifiers({ readonly: options.ctx.immutable }), @@ -86,12 +59,8 @@ export function transformParametersArray( ts.factory.createPropertySignature( /* modifiers */ tsModifiers({ readonly: options.ctx.immutable }), /* name */ tsPropertyIndex(paramIn), - /* questionToken */ allOptional || !paramLocType.length - ? QUESTION_TOKEN - : undefined, - /* type */ paramLocType.length - ? ts.factory.createTypeLiteralNode(paramLocType) - : NEVER, + /* questionToken */ allOptional || !paramLocType.length ? QUESTION_TOKEN : undefined, + /* type */ paramLocType.length ? ts.factory.createTypeLiteralNode(paramLocType) : NEVER, ), ); } @@ -100,9 +69,7 @@ export function transformParametersArray( /* modifiers */ tsModifiers({ readonly: options.ctx.immutable }), /* name */ tsPropertyIndex("parameters"), /* questionToken */ !paramType.length ? QUESTION_TOKEN : undefined, - /* type */ paramType.length - ? ts.factory.createTypeLiteralNode(paramType) - : NEVER, + /* type */ paramType.length ? ts.factory.createTypeLiteralNode(paramType) : NEVER, ), ); diff --git a/packages/openapi-typescript/src/transform/path-item-object.ts b/packages/openapi-typescript/src/transform/path-item-object.ts index 26c811d26..e5d6e2271 100644 --- a/packages/openapi-typescript/src/transform/path-item-object.ts +++ b/packages/openapi-typescript/src/transform/path-item-object.ts @@ -1,12 +1,5 @@ import ts from "typescript"; -import { - NEVER, - QUESTION_TOKEN, - addJSDocComment, - oapiRef, - tsModifiers, - tsPropertyIndex, -} from "../lib/ts.js"; +import { NEVER, QUESTION_TOKEN, addJSDocComment, oapiRef, tsModifiers, tsPropertyIndex } from "../lib/ts.js"; import { createRef } from "../lib/utils.js"; import type { OperationObject, @@ -15,58 +8,34 @@ import type { ReferenceObject, TransformNodeOptions, } from "../types.js"; -import transformOperationObject, { - injectOperationObject, -} from "./operation-object.js"; +import transformOperationObject, { injectOperationObject } from "./operation-object.js"; import { transformParametersArray } from "./parameters-array.js"; -export type Method = - | "get" - | "put" - | "post" - | "delete" - | "options" - | "head" - | "patch" - | "trace"; +export type Method = "get" | "put" | "post" | "delete" | "options" | "head" | "patch" | "trace"; /** * Transform PathItem nodes (4.8.9) * @see https://spec.openapis.org/oas/v3.1.0#path-item-object */ -export default function transformPathItemObject( - pathItem: PathItemObject, - options: TransformNodeOptions, -): ts.TypeNode { +export default function transformPathItemObject(pathItem: PathItemObject, options: TransformNodeOptions): ts.TypeNode { const type: ts.TypeElement[] = []; // parameters type.push( ...transformParametersArray(pathItem.parameters ?? [], { ...options, - path: createRef([options.path!, "parameters"]), + path: createRef([options.path, "parameters"]), }), ); // methods - for (const method of [ - "get", - "put", - "post", - "delete", - "options", - "head", - "patch", - "trace", - ] as Method[]) { + for (const method of ["get", "put", "post", "delete", "options", "head", "patch", "trace"] as Method[]) { const operationObject = pathItem[method]; if ( !operationObject || (options.ctx.excludeDeprecated && - ("$ref" in operationObject - ? options.ctx.resolve(operationObject.$ref) - : operationObject - )?.deprecated) + ("$ref" in operationObject ? options.ctx.resolve(operationObject.$ref) : operationObject) + ?.deprecated) ) { type.push( ts.factory.createPropertySignature( @@ -80,18 +49,11 @@ export default function transformPathItemObject( } // fold top-level PathItem parameters into method-level, with the latter overriding the former - const keyedParameters: Record = - {}; + const keyedParameters: Record = {}; if (!("$ref" in operationObject)) { // important: OperationObject parameters come last, and will override any conflicts with PathItem parameters - for (const parameter of [ - ...(pathItem.parameters ?? []), - ...(operationObject.parameters ?? []), - ]) { - const name = - "$ref" in parameter - ? options.ctx.resolve(parameter.$ref)?.name - : parameter.name; + for (const parameter of [...(pathItem.parameters ?? []), ...(operationObject.parameters ?? [])]) { + const name = "$ref" in parameter ? options.ctx.resolve(parameter.$ref)?.name : parameter.name; if (name) { keyedParameters[name] = parameter; } @@ -110,13 +72,13 @@ export default function transformPathItemObject( injectOperationObject( operationId, { ...operationObject, parameters: Object.values(keyedParameters) }, - { ...options, path: createRef([options.path!, method]) }, + { ...options, path: createRef([options.path, method]) }, ); } else { operationType = ts.factory.createTypeLiteralNode( transformOperationObject( { ...operationObject, parameters: Object.values(keyedParameters) }, - { ...options, path: createRef([options.path!, method]) }, + { ...options, path: createRef([options.path, method]) }, ), ); } diff --git a/packages/openapi-typescript/src/transform/paths-object.ts b/packages/openapi-typescript/src/transform/paths-object.ts index 5104fcd75..5718a79fb 100644 --- a/packages/openapi-typescript/src/transform/paths-object.ts +++ b/packages/openapi-typescript/src/transform/paths-object.ts @@ -1,11 +1,5 @@ import ts from "typescript"; -import { - addJSDocComment, - oapiRef, - stringToAST, - tsModifiers, - tsPropertyIndex, -} from "../lib/ts.js"; +import { addJSDocComment, oapiRef, stringToAST, tsModifiers, tsPropertyIndex } from "../lib/ts.js"; import { createRef, debug, getEntries } from "../lib/utils.js"; import type { GlobalContext, @@ -23,10 +17,7 @@ const PATH_PARAM_RE = /\{[^}]+\}/g; * Transform the PathsObject node (4.8.8) * @see https://spec.openapis.org/oas/v3.1.0#operation-object */ -export default function transformPathsObject( - pathsObject: PathsObject, - ctx: GlobalContext, -): ts.TypeNode { +export default function transformPathsObject(pathsObject: PathsObject, ctx: GlobalContext): ts.TypeNode { const type: ts.TypeElement[] = []; for (const [url, pathItemObject] of getEntries(pathsObject, ctx)) { if (!pathItemObject || typeof pathItemObject !== "object") { @@ -56,17 +47,13 @@ export default function transformPathsObject( const matches = url.match(PATH_PARAM_RE); let rawPath = `\`${url}\``; if (matches) { - /* eslint-disable @typescript-eslint/no-explicit-any */ for (const match of matches) { const paramName = match.slice(1, -1); const param = pathParams[paramName]; if (!param) { rawPath = rawPath.replace(match, "${string}"); } else { - rawPath = rawPath.replace( - match, - `$\{${(param.schema as any)?.type ?? "string"}}`, - ); + rawPath = rawPath.replace(match, `$\{${(param.schema as any)?.type ?? "string"}}`); } } // note: creating a string template literal’s AST manually is hard! @@ -91,7 +78,6 @@ export default function transformPathsObject( ); continue; } - /* eslint-enable @typescript-eslint/no-explicit-any */ } } @@ -114,38 +100,21 @@ export default function transformPathsObject( function extractPathParams(pathItemObject: PathItemObject, ctx: GlobalContext) { const params: Record = {}; for (const p of pathItemObject.parameters ?? []) { - const resolved = - "$ref" in p && p.$ref - ? ctx.resolve(p.$ref) - : (p as ParameterObject); + const resolved = "$ref" in p && p.$ref ? ctx.resolve(p.$ref) : (p as ParameterObject); if (resolved && resolved.in === "path") { params[resolved.name] = resolved; } } - for (const method of [ - "get", - "put", - "post", - "delete", - "options", - "head", - "patch", - "trace", - ] as Method[]) { + for (const method of ["get", "put", "post", "delete", "options", "head", "patch", "trace"] as Method[]) { if (!(method in pathItemObject)) { continue; } const resolvedMethod = (pathItemObject[method] as ReferenceObject).$ref - ? ctx.resolve( - (pathItemObject[method] as ReferenceObject).$ref, - ) + ? ctx.resolve((pathItemObject[method] as ReferenceObject).$ref) : (pathItemObject[method] as OperationObject); if (resolvedMethod?.parameters) { for (const p of resolvedMethod.parameters) { - const resolvedParam = - "$ref" in p && p.$ref - ? ctx.resolve(p.$ref) - : (p as ParameterObject); + const resolvedParam = "$ref" in p && p.$ref ? ctx.resolve(p.$ref) : (p as ParameterObject); if (resolvedParam && resolvedParam.in === "path") { params[resolvedParam.name] = resolvedParam; } diff --git a/packages/openapi-typescript/src/transform/request-body-object.ts b/packages/openapi-typescript/src/transform/request-body-object.ts index dab0090b9..beeeef915 100644 --- a/packages/openapi-typescript/src/transform/request-body-object.ts +++ b/packages/openapi-typescript/src/transform/request-body-object.ts @@ -1,11 +1,5 @@ import ts from "typescript"; -import { - NEVER, - QUESTION_TOKEN, - addJSDocComment, - tsModifiers, - tsPropertyIndex, -} from "../lib/ts.js"; +import { NEVER, QUESTION_TOKEN, addJSDocComment, tsModifiers, tsPropertyIndex } from "../lib/ts.js"; import { createRef, getEntries } from "../lib/utils.js"; import type { RequestBodyObject, TransformNodeOptions } from "../types.js"; import transformMediaTypeObject from "./media-type-object.js"; @@ -20,11 +14,8 @@ export default function transformRequestBodyObject( options: TransformNodeOptions, ): ts.TypeNode { const type: ts.TypeElement[] = []; - for (const [contentType, mediaTypeObject] of getEntries( - requestBodyObject.content, - options.ctx, - )) { - const nextPath = createRef([options.path!, contentType]); + for (const [contentType, mediaTypeObject] of getEntries(requestBodyObject.content, options.ctx)) { + const nextPath = createRef([options.path, contentType]); const mediaType = "$ref" in mediaTypeObject ? transformSchemaObject(mediaTypeObject, { diff --git a/packages/openapi-typescript/src/transform/response-object.ts b/packages/openapi-typescript/src/transform/response-object.ts index 3afb138ef..37b6398fa 100644 --- a/packages/openapi-typescript/src/transform/response-object.ts +++ b/packages/openapi-typescript/src/transform/response-object.ts @@ -27,20 +27,14 @@ export default function transformResponseObject( // headers const headersObject: ts.TypeElement[] = []; if (responseObject.headers) { - for (const [name, headerObject] of getEntries( - responseObject.headers, - options.ctx, - )) { - const optional = - "$ref" in headerObject || headerObject.required - ? undefined - : QUESTION_TOKEN; + for (const [name, headerObject] of getEntries(responseObject.headers, options.ctx)) { + const optional = "$ref" in headerObject || headerObject.required ? undefined : QUESTION_TOKEN; const subType = "$ref" in headerObject ? oapiRef(headerObject.$ref) : transformHeaderObject(headerObject, { ...options, - path: createRef([options.path ?? "", "headers", name]), + path: createRef([options.path, "headers", name]), }); const property = ts.factory.createPropertySignature( /* modifiers */ tsModifiers({ readonly: options.ctx.immutable }), @@ -80,17 +74,14 @@ export default function transformResponseObject( // content const contentObject: ts.TypeElement[] = []; if (responseObject.content) { - for (const [contentType, mediaTypeObject] of getEntries( - responseObject.content, - options.ctx, - )) { + for (const [contentType, mediaTypeObject] of getEntries(responseObject.content, options.ctx)) { const property = ts.factory.createPropertySignature( /* modifiers */ tsModifiers({ readonly: options.ctx.immutable }), /* name */ tsPropertyIndex(contentType), /* questionToken */ undefined, /* type */ transformMediaTypeObject(mediaTypeObject, { ...options, - path: createRef([options.path ?? "", "content", contentType]), + path: createRef([options.path, "content", contentType]), }), ); contentObject.push(property); diff --git a/packages/openapi-typescript/src/transform/responses-object.ts b/packages/openapi-typescript/src/transform/responses-object.ts index 4185ace20..29c1ee39b 100644 --- a/packages/openapi-typescript/src/transform/responses-object.ts +++ b/packages/openapi-typescript/src/transform/responses-object.ts @@ -1,11 +1,5 @@ import ts from "typescript"; -import { - NEVER, - addJSDocComment, - tsModifiers, - oapiRef, - tsPropertyIndex, -} from "../lib/ts.js"; +import { NEVER, addJSDocComment, tsModifiers, oapiRef, tsPropertyIndex } from "../lib/ts.js"; import { createRef, getEntries } from "../lib/utils.js"; import type { ResponsesObject, TransformNodeOptions } from "../types.js"; import transformResponseObject from "./response-object.js"; @@ -20,16 +14,13 @@ export default function transformResponsesObject( ): ts.TypeNode { const type: ts.TypeElement[] = []; - for (const [responseCode, responseObject] of getEntries( - responsesObject, - options.ctx, - )) { + for (const [responseCode, responseObject] of getEntries(responsesObject, options.ctx)) { const responseType = "$ref" in responseObject ? oapiRef(responseObject.$ref) : transformResponseObject(responseObject, { ...options, - path: createRef([options.path ?? "", "responses", responseCode]), + path: createRef([options.path, "responses", responseCode]), }); const property = ts.factory.createPropertySignature( /* modifiers */ tsModifiers({ readonly: options.ctx.immutable }), diff --git a/packages/openapi-typescript/src/transform/schema-object.ts b/packages/openapi-typescript/src/transform/schema-object.ts index 25805cab7..fd40476ed 100644 --- a/packages/openapi-typescript/src/transform/schema-object.ts +++ b/packages/openapi-typescript/src/transform/schema-object.ts @@ -23,16 +23,8 @@ import { tsUnion, tsWithRequired, } from "../lib/ts.js"; -import { - createDiscriminatorProperty, - createRef, - getEntries, -} from "../lib/utils.js"; -import type { - ReferenceObject, - SchemaObject, - TransformNodeOptions, -} from "../types.js"; +import { createDiscriminatorProperty, createRef, getEntries } from "../lib/utils.js"; +import type { ReferenceObject, SchemaObject, TransformNodeOptions } from "../types.js"; /** * Transform SchemaObject nodes (4.8.24) @@ -73,11 +65,7 @@ export function transformSchemaObjectWithComposition( } // for any other unexpected type, throw error if (Array.isArray(schemaObject) || typeof schemaObject !== "object") { - throw new Error( - `Expected SchemaObject, received ${ - Array.isArray(schemaObject) ? "Array" : typeof schemaObject - }`, - ); + throw new Error(`Expected SchemaObject, received ${Array.isArray(schemaObject) ? "Array" : typeof schemaObject}`); } /** @@ -105,22 +93,13 @@ export function transformSchemaObjectWithComposition( !("additionalProperties" in schemaObject) ) { // hoist enum to top level if string/number enum and option is enabled - if ( - options.ctx.enum && - schemaObject.enum.every( - (v) => typeof v === "string" || typeof v === "number", - ) - ) { + if (options.ctx.enum && schemaObject.enum.every((v) => typeof v === "string" || typeof v === "number")) { let enumName = parseRef(options.path ?? "").pointer.join("/"); // allow #/components/schemas to have simpler names enumName = enumName.replace("components/schemas", ""); const metadata = schemaObject.enum.map((_, i) => ({ - name: - schemaObject["x-enum-varnames"]?.[i] ?? - schemaObject["x-enumNames"]?.[i], - description: - schemaObject["x-enum-descriptions"]?.[i] ?? - schemaObject["x-enumDescriptions"]?.[i], + name: schemaObject["x-enum-varnames"]?.[i] ?? schemaObject["x-enumNames"]?.[i], + description: schemaObject["x-enum-descriptions"]?.[i] ?? schemaObject["x-enumDescriptions"]?.[i], })); const enumType = tsEnum( enumName, @@ -153,10 +132,7 @@ export function transformSchemaObjectWithComposition( } /** Collect allOf with Omit<> for discriminators */ - function collectAllOfCompositions( - items: (SchemaObject | ReferenceObject)[], - required?: string[], - ): ts.TypeNode[] { + function collectAllOfCompositions(items: (SchemaObject | ReferenceObject)[], required?: string[]): ts.TypeNode[] { const output: ts.TypeNode[] = []; for (const item of items) { let itemType: ts.TypeNode; @@ -176,15 +152,9 @@ export function transformSchemaObjectWithComposition( !options.ctx.discriminators.refsHandled.includes(item.$ref) ) { // add WithRequired if necessary - const validRequired = (required ?? []).filter( - (key) => !!resolved.properties![key], - ); + const validRequired = (required ?? []).filter((key) => !!resolved.properties?.[key]); if (validRequired.length) { - itemType = tsWithRequired( - itemType, - validRequired, - options.ctx.injectFooter, - ); + itemType = tsWithRequired(itemType, validRequired, options.ctx.injectFooter); } } } @@ -194,15 +164,11 @@ export function transformSchemaObjectWithComposition( if (typeof item === "object" && Array.isArray(item.required)) { itemRequired.push(...item.required); } - itemType = transformSchemaObject( - { ...item, required: itemRequired }, - options, - ); + itemType = transformSchemaObject({ ...item, required: itemRequired }, options); } const discriminator = - ("$ref" in item && options.ctx.discriminators.objects[item.$ref]) || - (item as any).discriminator; // eslint-disable-line @typescript-eslint/no-explicit-any + ("$ref" in item && options.ctx.discriminators.objects[item.$ref]) || (item as any).discriminator; if (discriminator) { output.push(tsOmit(itemType, [discriminator.propertyName])); } else { @@ -217,18 +183,10 @@ export function transformSchemaObjectWithComposition( // core + allOf: intersect const coreObjectType = transformSchemaObjectCore(schemaObject, options); - const allOfType = collectAllOfCompositions( - schemaObject.allOf ?? [], - schemaObject.required, - ); + const allOfType = collectAllOfCompositions(schemaObject.allOf ?? [], schemaObject.required); if (coreObjectType || allOfType.length) { - const allOf: ts.TypeNode | undefined = allOfType.length - ? tsIntersection(allOfType) - : undefined; - finalType = tsIntersection([ - ...(coreObjectType ? [coreObjectType] : []), - ...(allOf ? [allOf] : []), - ]); + const allOf: ts.TypeNode | undefined = allOfType.length ? tsIntersection(allOfType) : undefined; + finalType = tsIntersection([...(coreObjectType ? [coreObjectType] : []), ...(allOf ? [allOf] : [])]); } // anyOf: union // (note: this may seem counterintuitive, but as TypeScript’s unions are not true XORs, they mimic behavior closer to anyOf than oneOf) @@ -249,10 +207,7 @@ export function transformSchemaObjectWithComposition( if (oneOfType.every(tsIsPrimitive)) { finalType = tsUnion([...(finalType ? [finalType] : []), ...oneOfType]); } else { - finalType = tsIntersection([ - ...(finalType ? [finalType] : []), - tsUnion(oneOfType), - ]); + finalType = tsIntersection([...(finalType ? [finalType] : []), tsUnion(oneOfType)]); } } @@ -279,10 +234,7 @@ export function transformSchemaObjectWithComposition( /** * Handle SchemaObject minus composition (anyOf/allOf/oneOf) */ -function transformSchemaObjectCore( - schemaObject: SchemaObject, - options: TransformNodeOptions, -): ts.TypeNode | undefined { +function transformSchemaObjectCore(schemaObject: SchemaObject, options: TransformNodeOptions): ts.TypeNode | undefined { if ("type" in schemaObject && schemaObject.type) { // primitives // type: null @@ -308,39 +260,25 @@ function transformSchemaObjectCore( let itemType: ts.TypeNode = UNKNOWN; // tuple type if (schemaObject.prefixItems || Array.isArray(schemaObject.items)) { - const prefixItems = - schemaObject.prefixItems ?? - (schemaObject.items as (SchemaObject | ReferenceObject)[]); - itemType = ts.factory.createTupleTypeNode( - prefixItems.map((item) => transformSchemaObject(item, options)), - ); + const prefixItems = schemaObject.prefixItems ?? (schemaObject.items as (SchemaObject | ReferenceObject)[]); + itemType = ts.factory.createTupleTypeNode(prefixItems.map((item) => transformSchemaObject(item, options))); } // standard array type else if (schemaObject.items) { - if ( - "type" in schemaObject.items && - schemaObject.items.type === "array" - ) { - itemType = ts.factory.createArrayTypeNode( - transformSchemaObject(schemaObject.items, options), - ); + if ("type" in schemaObject.items && schemaObject.items.type === "array") { + itemType = ts.factory.createArrayTypeNode(transformSchemaObject(schemaObject.items, options)); } else { itemType = transformSchemaObject(schemaObject.items, options); } } const min: number = - typeof schemaObject.minItems === "number" && schemaObject.minItems >= 0 - ? schemaObject.minItems - : 0; + typeof schemaObject.minItems === "number" && schemaObject.minItems >= 0 ? schemaObject.minItems : 0; const max: number | undefined = - typeof schemaObject.maxItems === "number" && - schemaObject.maxItems >= 0 && - min <= schemaObject.maxItems + typeof schemaObject.maxItems === "number" && schemaObject.maxItems >= 0 && min <= schemaObject.maxItems ? schemaObject.maxItems : undefined; - const estimateCodeSize = - typeof max !== "number" ? min : (max * (max + 1) - min * (min - 1)) / 2; + const estimateCodeSize = typeof max !== "number" ? min : (max * (max + 1) - min * (min - 1)) / 2; if ( options.ctx.arrayLength && (min !== 0 || max !== undefined) && @@ -365,11 +303,7 @@ function transformSchemaObjectCore( for (let i = 0; i < min; i++) { elements.push(itemType); } - elements.push( - ts.factory.createRestTypeNode( - ts.factory.createArrayTypeNode(itemType), - ), - ); + elements.push(ts.factory.createRestTypeNode(ts.factory.createArrayTypeNode(itemType))); return ts.factory.createTupleTypeNode(elements); } } @@ -386,14 +320,8 @@ function transformSchemaObjectCore( if (Array.isArray(schemaObject.oneOf)) { for (const t of schemaObject.type) { if ( - (t === "boolean" || - t === "string" || - t === "number" || - t === "integer" || - t === "null") && - schemaObject.oneOf.find( - (o) => typeof o === "object" && "type" in o && o.type === t, - ) + (t === "boolean" || t === "string" || t === "number" || t === "integer" || t === "null") && + schemaObject.oneOf.find((o) => typeof o === "object" && "type" in o && o.type === t) ) { continue; } @@ -401,7 +329,7 @@ function transformSchemaObjectCore( t === "null" || t === null ? NULL : transformSchemaObject( - { ...schemaObject, type: t, oneOf: undefined }, // don’t stack oneOf transforms + { ...schemaObject, type: t, oneOf: undefined } as SchemaObject, // don’t stack oneOf transforms options, ), ); @@ -410,7 +338,7 @@ function transformSchemaObjectCore( uniqueTypes = schemaObject.type.map((t) => t === "null" || t === null ? NULL - : transformSchemaObject({ ...schemaObject, type: t }, options), + : transformSchemaObject({ ...schemaObject, type: t } as SchemaObject, options), ); } return tsUnion(uniqueTypes); @@ -432,12 +360,12 @@ function transformSchemaObjectCore( // them (options.ctx.discriminators.refsHandled.includes(options.path!). const discriminator = !schemaObject.discriminator && - !options.ctx.discriminators.refsHandled.includes(options.path!) && - options.ctx.discriminators.objects[options.path!]; + !options.ctx.discriminators.refsHandled.includes(options.path ?? "") && + options.ctx.discriminators.objects[options.path ?? ""]; if (discriminator) { coreObjectType.unshift( createDiscriminatorProperty(discriminator, { - path: options.path!, + path: options.path ?? "", readonly: options.ctx.immutable, }), ); @@ -446,24 +374,16 @@ function transformSchemaObjectCore( } if ( - ("properties" in schemaObject && - schemaObject.properties && - Object.keys(schemaObject.properties).length) || - ("additionalProperties" in schemaObject && - schemaObject.additionalProperties) || + ("properties" in schemaObject && schemaObject.properties && Object.keys(schemaObject.properties).length) || + ("additionalProperties" in schemaObject && schemaObject.additionalProperties) || ("$defs" in schemaObject && schemaObject.$defs) ) { // properties if (Object.keys(schemaObject.properties ?? {}).length) { - for (const [k, v] of getEntries( - schemaObject.properties ?? {}, - options.ctx, - )) { + for (const [k, v] of getEntries(schemaObject.properties ?? {}, options.ctx)) { if (typeof v !== "object" || Array.isArray(v)) { throw new Error( - `${ - options.path - }: invalid property ${k}. Expected Schema Object, got ${ + `${options.path}: invalid property ${k}. Expected Schema Object, got ${ Array.isArray(v) ? "Array" : typeof v }`, ); @@ -471,19 +391,15 @@ function transformSchemaObjectCore( // handle excludeDeprecated option if (options.ctx.excludeDeprecated) { - const resolved = - "$ref" in v ? options.ctx.resolve(v.$ref) : v; + const resolved = "$ref" in v ? options.ctx.resolve(v.$ref) : v; if (resolved?.deprecated) { continue; } } let optional = schemaObject.required?.includes(k) || - (schemaObject.required === undefined && - options.ctx.propertiesRequiredByDefault) || - ("default" in v && - options.ctx.defaultNonNullable && - !options.path?.includes("parameters")) // parameters can’t be required, even with defaults + (schemaObject.required === undefined && options.ctx.propertiesRequiredByDefault) || + ("default" in v && options.ctx.defaultNonNullable && !options.path?.includes("parameters")) // parameters can’t be required, even with defaults ? undefined : QUESTION_TOKEN; let type = @@ -491,11 +407,11 @@ function transformSchemaObjectCore( ? oapiRef(v.$ref) : transformSchemaObject(v, { ...options, - path: createRef([options.path ?? "", k]), + path: createRef([options.path, k]), }); if (typeof options.ctx.transform === "function") { - const result = options.ctx.transform(v, options); + const result = options.ctx.transform(v as SchemaObject, options); if (result) { if ("schema" in result) { type = result.schema; @@ -508,8 +424,7 @@ function transformSchemaObjectCore( const property = ts.factory.createPropertySignature( /* modifiers */ tsModifiers({ - readonly: - options.ctx.immutable || ("readOnly" in v && !!v.readOnly), + readonly: options.ctx.immutable || ("readOnly" in v && !!v.readOnly), }), /* name */ tsPropertyIndex(k), /* questionToken */ optional, @@ -521,23 +436,18 @@ function transformSchemaObjectCore( } // $defs - if ( - schemaObject.$defs && - typeof schemaObject.$defs === "object" && - Object.keys(schemaObject.$defs).length - ) { + if (schemaObject.$defs && typeof schemaObject.$defs === "object" && Object.keys(schemaObject.$defs).length) { const defKeys: ts.TypeElement[] = []; for (const [k, v] of Object.entries(schemaObject.$defs)) { const property = ts.factory.createPropertySignature( /* modifiers */ tsModifiers({ - readonly: - options.ctx.immutable || ("readonly" in v && !!v.readOnly), + readonly: options.ctx.immutable || ("readonly" in v && !!v.readOnly), }), /* name */ tsPropertyIndex(k), /* questionToken */ undefined, /* type */ transformSchemaObject(v, { ...options, - path: createRef([options.path ?? "", "$defs", k]), + path: createRef([options.path, "$defs", k]), }), ); addJSDocComment(v, property); @@ -556,13 +466,9 @@ function transformSchemaObjectCore( // additionalProperties if (schemaObject.additionalProperties || options.ctx.additionalProperties) { const hasExplicitAdditionalProperties = - typeof schemaObject.additionalProperties === "object" && - Object.keys(schemaObject.additionalProperties).length; + typeof schemaObject.additionalProperties === "object" && Object.keys(schemaObject.additionalProperties).length; let addlType = hasExplicitAdditionalProperties - ? transformSchemaObject( - schemaObject.additionalProperties as SchemaObject, - options, - ) + ? transformSchemaObject(schemaObject.additionalProperties as SchemaObject, options) : UNKNOWN; // allow for `| undefined`, at least until https://github.com/microsoft/TypeScript/issues/4196 is resolved if (addlType.kind !== ts.SyntaxKind.UnknownKeyword) { @@ -588,7 +494,5 @@ function transformSchemaObjectCore( } } - return coreObjectType.length - ? ts.factory.createTypeLiteralNode(coreObjectType) - : undefined; + return coreObjectType.length ? ts.factory.createTypeLiteralNode(coreObjectType) : undefined; } diff --git a/packages/openapi-typescript/src/transform/webhooks-object.ts b/packages/openapi-typescript/src/transform/webhooks-object.ts index 1f6bbac23..28c3df644 100644 --- a/packages/openapi-typescript/src/transform/webhooks-object.ts +++ b/packages/openapi-typescript/src/transform/webhooks-object.ts @@ -4,10 +4,7 @@ import { createRef, getEntries } from "../lib/utils.js"; import type { GlobalContext, WebhooksObject } from "../types.js"; import transformPathItemObject from "./path-item-object.js"; -export default function transformWebhooksObject( - webhooksObject: WebhooksObject, - options: GlobalContext, -): ts.TypeNode { +export default function transformWebhooksObject(webhooksObject: WebhooksObject, options: GlobalContext): ts.TypeNode { const type: ts.TypeElement[] = []; for (const [name, pathItemObject] of getEntries(webhooksObject, options)) { diff --git a/packages/openapi-typescript/src/types.ts b/packages/openapi-typescript/src/types.ts index c68c2cbc9..07255bd70 100644 --- a/packages/openapi-typescript/src/types.ts +++ b/packages/openapi-typescript/src/types.ts @@ -3,7 +3,6 @@ import type { PathLike } from "node:fs"; import type ts from "typescript"; // Many types allow for true “any” for inheritance to work -/* eslint-disable @typescript-eslint/no-explicit-any */ export interface Extensable { [key: `x-${string}`]: any; @@ -453,18 +452,8 @@ export type SchemaObject = { | NullSubtype | ObjectSubtype | { - type: ( - | "string" - | "number" - | "integer" - | "array" - | "boolean" - | "null" - | "object" - )[]; + type: ("string" | "number" | "integer" | "array" | "boolean" | "null" | "object")[]; } - // eslint-disable-next-line @typescript-eslint/ban-types - | {} ); export interface TransformObject { @@ -512,11 +501,7 @@ export interface NullSubtype { export interface ObjectSubtype { type: "object" | ["object", "null"]; properties?: { [name: string]: SchemaObject | ReferenceObject }; - additionalProperties?: - | boolean - | Record - | SchemaObject - | ReferenceObject; + additionalProperties?: boolean | Record | SchemaObject | ReferenceObject; required?: string[]; allOf?: (SchemaObject | ReferenceObject)[]; anyOf?: (SchemaObject | ReferenceObject)[]; @@ -631,10 +616,7 @@ export interface OAuthFlowObject extends Extensable { * [4.8.30] Security Requirements Object * Lists the required security schemes to execute this operation. The name used for each property MUST correspond to a security scheme declared in the Security Schemes under the Components Object. */ -export type SecurityRequirementObject = Record< - keyof ComponentsObject["securitySchemes"], - string[] ->; +export type SecurityRequirementObject = Record; export interface OpenAPITSOptions { /** Treat all objects as if they have `additionalProperties: true` by default (default: false) */ @@ -652,15 +634,9 @@ export interface OpenAPITSOptions { /** Exclude deprecated fields from types? (default: false) */ excludeDeprecated?: boolean; /** Manually transform certain Schema Objects with a custom TypeScript type */ - transform?: ( - schemaObject: SchemaObject, - options: TransformNodeOptions, - ) => ts.TypeNode | TransformObject | undefined; + transform?: (schemaObject: SchemaObject, options: TransformNodeOptions) => ts.TypeNode | TransformObject | undefined; /** Modify TypeScript types built from Schema Objects */ - postTransform?: ( - type: ts.TypeNode, - options: TransformNodeOptions, - ) => ts.TypeNode | undefined; + postTransform?: (type: ts.TypeNode, options: TransformNodeOptions) => ts.TypeNode | undefined; /** Add readonly properties and readonly arrays? (default: false) */ immutable?: boolean; /** (optional) Should logging be suppressed? (necessary for STDOUT) */ diff --git a/packages/openapi-typescript/test/cjs.test.js b/packages/openapi-typescript/test/cjs.test.js index 992e287a6..a6ceaf573 100644 --- a/packages/openapi-typescript/test/cjs.test.js +++ b/packages/openapi-typescript/test/cjs.test.js @@ -1,8 +1,6 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ - // important: MUST use require()! const { fileURLToPath } = require("node:url"); -const { astToString, default: openapiTS } = require('../dist/index.cjs'); +const { astToString, default: openapiTS } = require("../dist/index.cjs"); describe("CJS bundle", () => { it("basic", async () => { @@ -11,11 +9,7 @@ describe("CJS bundle", () => { * Do not make direct changes to the file. */ -${astToString( - await openapiTS(new URL("../examples/stripe-api.yaml", import.meta.url)), -)}`; - expect(output).toMatchFileSnapshot( - fileURLToPath(new URL("../examples/stripe-api.ts", import.meta.url)), - ); +${astToString(await openapiTS(new URL("../examples/stripe-api.yaml", import.meta.url)))}`; + expect(output).toMatchFileSnapshot(fileURLToPath(new URL("../examples/stripe-api.ts", import.meta.url))); }); }); diff --git a/packages/openapi-typescript/test/cli.test.ts b/packages/openapi-typescript/test/cli.test.ts index 2f4645ec4..0d2ad551f 100644 --- a/packages/openapi-typescript/test/cli.test.ts +++ b/packages/openapi-typescript/test/cli.test.ts @@ -77,7 +77,7 @@ describe("CLI", () => { if (want instanceof URL) { expect(stdout).toMatchFileSnapshot(fileURLToPath(want)); } else { - expect(stdout).toBe(want + "\n"); + expect(stdout).toBe(`${want}\n`); } }, ci?.timeout, @@ -87,13 +87,9 @@ describe("CLI", () => { test( "stdin", async () => { - const input = fs.readFileSync( - new URL("./examples/stripe-api.yaml", root), - ); + const input = fs.readFileSync(new URL("./examples/stripe-api.yaml", root)); const { stdout } = await execa(cmd, { input, cwd }); - expect(stdout).toMatchFileSnapshot( - fileURLToPath(new URL("./examples/stripe-api.ts", root)), - ); + expect(stdout).toMatchFileSnapshot(fileURLToPath(new URL("./examples/stripe-api.ts", root))); }, TIMEOUT, ); @@ -101,11 +97,7 @@ describe("CLI", () => { describe("flags", () => { test("--help", async () => { const { stdout } = await execa(cmd, ["--help"], { cwd }); - expect(stdout).toEqual( - expect.stringMatching( - /^Usage\n\s+\$ openapi-typescript \[input\] \[options\]/, - ), - ); + expect(stdout).toEqual(expect.stringMatching(/^Usage\n\s+\$ openapi-typescript \[input\] \[options\]/)); }); test("--version", async () => { @@ -117,21 +109,16 @@ describe("CLI", () => { describe("Redocly config", () => { // TODO: why won’t this run on Windows? test.skipIf(os.platform() === "win32")("automatic config", async () => { - /* eslint-disable @typescript-eslint/no-shadow */ - // note: we have to change the cwd here for the automatic config to pick up properly const root = new URL("./fixtures/redocly/", import.meta.url); const cwd = os.platform() === "win32" ? fileURLToPath(root) : root; await execa("../../../bin/cli.js", { cwd }); for (const schema of ["a", "b", "c"]) { - expect( - fs.readFileSync(new URL(`./output/${schema}.ts`, root), "utf8"), - ).toMatchFileSnapshot( + expect(fs.readFileSync(new URL(`./output/${schema}.ts`, root), "utf8")).toMatchFileSnapshot( fileURLToPath(new URL("../../../examples/simple-example.ts", root)), ); } - /* eslint-enable @typescript-eslint/no-shadow */ }); test("--redoc config", async () => { @@ -140,13 +127,8 @@ describe("CLI", () => { }); for (const schema of ["a", "b", "c"]) { expect( - fs.readFileSync( - new URL(`./test/fixtures/redocly-flag/output/${schema}.ts`, root), - "utf8", - ), - ).toMatchFileSnapshot( - fileURLToPath(new URL("./examples/simple-example.ts", root)), - ); + fs.readFileSync(new URL(`./test/fixtures/redocly-flag/output/${schema}.ts`, root), "utf8"), + ).toMatchFileSnapshot(fileURLToPath(new URL("./examples/simple-example.ts", root))); } }); }); diff --git a/packages/openapi-typescript/test/discriminators.test.ts b/packages/openapi-typescript/test/discriminators.test.ts index 193c6bdbb..49047ca72 100644 --- a/packages/openapi-typescript/test/discriminators.test.ts +++ b/packages/openapi-typescript/test/discriminators.test.ts @@ -45,10 +45,7 @@ describe("3.1 discriminators", () => { allOf: [{ $ref: "#/components/schemas/Pet" }], }, LizardDog: { - allOf: [ - { $ref: "#/components/schemas/Dog" }, - { $ref: "#/components/schemas/Lizard" }, - ], + allOf: [{ $ref: "#/components/schemas/Dog" }, { $ref: "#/components/schemas/Lizard" }], }, AnimalSighting: { oneOf: [ @@ -640,7 +637,7 @@ export type operations = Record;`, if (want instanceof URL) { expect(result).toMatchFileSnapshot(fileURLToPath(want)); } else { - expect(result).toBe(want + "\n"); + expect(result).toBe(`${want}\n`); } }, ci?.timeout, diff --git a/packages/openapi-typescript/test/index.test.ts b/packages/openapi-typescript/test/index.test.ts index 7caaad209..1de917433 100644 --- a/packages/openapi-typescript/test/index.test.ts +++ b/packages/openapi-typescript/test/index.test.ts @@ -41,10 +41,7 @@ describe("openapiTS", () => { properties: { number: { type: "number" } }, }, AllOf: { - allOf: [ - { $ref: "#/components/schemas/HasString" }, - { $ref: "#/components/schemas/HasNumber" }, - ], + allOf: [{ $ref: "#/components/schemas/HasString" }, { $ref: "#/components/schemas/HasNumber" }], }, }, }, @@ -259,10 +256,7 @@ export type operations = Record;`, [ "$refs > YAML anchors", { - given: new URL( - "./fixtures/anchor-with-ref-test-2.yaml", - import.meta.url, - ), + given: new URL("./fixtures/anchor-with-ref-test-2.yaml", import.meta.url), want: `export interface paths { "/": { parameters: { @@ -345,9 +339,7 @@ export type operations = Record;`, }, }, }, - parameters: [ - { name: "revision", in: "query", schema: { type: "number" } }, - ], + parameters: [{ name: "revision", in: "query", schema: { type: "number" } }], }, }, components: { @@ -686,7 +678,7 @@ export type operations = Record;`, if (want instanceof URL) { expect(want).toMatchFileSnapshot(fileURLToPath(want)); } else { - expect(result).toBe(want + "\n"); + expect(result).toBe(`${want}\n`); } }, ci?.timeout, diff --git a/packages/openapi-typescript/test/invalid.test.ts b/packages/openapi-typescript/test/invalid.test.ts index b00a0b1b5..bc6b2e5d5 100644 --- a/packages/openapi-typescript/test/invalid.test.ts +++ b/packages/openapi-typescript/test/invalid.test.ts @@ -2,9 +2,7 @@ import openapiTS from "../src/index.js"; describe("Invalid schemas", () => { test("Swagger 2.0 throws", async () => { - await expect(() => - openapiTS({ swagger: "2.0" } as any), - ).rejects.toThrowError( + await expect(() => openapiTS({ swagger: "2.0" } as any)).rejects.toThrowError( "Unsupported Swagger version: 2.x. Use OpenAPI 3.x instead.", ); }); @@ -19,8 +17,6 @@ describe("Invalid schemas", () => { }); test("Other missing required fields", async () => { - await expect(() => openapiTS({} as any)).rejects.toThrowError( - "Unsupported schema format, expected `openapi: 3.x`", - ); + await expect(() => openapiTS({} as any)).rejects.toThrowError("Unsupported schema format, expected `openapi: 3.x`"); }); }); diff --git a/packages/openapi-typescript/test/lib/ts.test.ts b/packages/openapi-typescript/test/lib/ts.test.ts index f647cab9f..324fdcb42 100644 --- a/packages/openapi-typescript/test/lib/ts.test.ts +++ b/packages/openapi-typescript/test/lib/ts.test.ts @@ -16,27 +16,16 @@ import { describe("addJSDocComment", () => { test("single-line comment", () => { - const property = ts.factory.createPropertySignature( - undefined, - "comment", - undefined, - BOOLEAN, - ); + const property = ts.factory.createPropertySignature(undefined, "comment", undefined, BOOLEAN); addJSDocComment({ description: "Single-line comment" }, property); - expect(astToString(ts.factory.createTypeLiteralNode([property])).trim()) - .toBe(`{ + expect(astToString(ts.factory.createTypeLiteralNode([property])).trim()).toBe(`{ /** @description Single-line comment */ comment: boolean; }`); }); test("multi-line comment", () => { - const property = ts.factory.createPropertySignature( - undefined, - "comment", - undefined, - BOOLEAN, - ); + const property = ts.factory.createPropertySignature(undefined, "comment", undefined, BOOLEAN); addJSDocComment( { summary: "This is the summary", @@ -45,8 +34,7 @@ describe("addJSDocComment", () => { }, property, ); - expect(astToString(ts.factory.createTypeLiteralNode([property])).trim()) - .toBe(`{ + expect(astToString(ts.factory.createTypeLiteralNode([property])).trim()).toBe(`{ /** * This is the summary * @deprecated @@ -58,18 +46,9 @@ describe("addJSDocComment", () => { }); test("escapes internal comments", () => { - const property = ts.factory.createPropertySignature( - undefined, - "comment", - undefined, - BOOLEAN, - ); - addJSDocComment( - { title: "This is a comment with `/* an example comment */` within" }, - property, - ); - expect(astToString(ts.factory.createTypeLiteralNode([property])).trim()) - .toBe(`{ + const property = ts.factory.createPropertySignature(undefined, "comment", undefined, BOOLEAN); + addJSDocComment({ title: "This is a comment with `/* an example comment */` within" }, property); + expect(astToString(ts.factory.createTypeLiteralNode([property])).trim()).toBe(`{ /** This is a comment with \`/* an example comment *\\/\` within */ comment: boolean; }`); @@ -78,20 +57,17 @@ describe("addJSDocComment", () => { describe("oapiRef", () => { test("single part", () => { - expect(astToString(oapiRef("#/components")).trim()).toBe(`components`); + expect(astToString(oapiRef("#/components")).trim()).toBe("components"); }); test("multiple parts", () => { - expect(astToString(oapiRef("#/components/schemas/User")).trim()).toBe( - `components["schemas"]["User"]`, - ); + expect(astToString(oapiRef("#/components/schemas/User")).trim()).toBe(`components["schemas"]["User"]`); }); }); describe("tsEnum", () => { test("string members", () => { - expect(astToString(tsEnum("-my-color-", ["green", "red", "blue"])).trim()) - .toBe(`enum MyColor { + expect(astToString(tsEnum("-my-color-", ["green", "red", "blue"])).trim()).toBe(`enum MyColor { green = "green", red = "red", blue = "blue" @@ -113,22 +89,14 @@ describe("tsEnum", () => { }); test("name from path", () => { - expect( - astToString( - tsEnum("#/paths/url/get/parameters/query/status", [ - "active", - "inactive", - ]), - ).trim(), - ).toBe(`enum PathsUrlGetParametersQueryStatus { + expect(astToString(tsEnum("#/paths/url/get/parameters/query/status", ["active", "inactive"])).trim()).toBe(`enum PathsUrlGetParametersQueryStatus { active = "active", inactive = "inactive" }`); }); test("string members with numeric prefix", () => { - expect(astToString(tsEnum("/my/enum/", ["0a", "1b", "2c"])).trim()) - .toBe(`enum MyEnum { + expect(astToString(tsEnum("/my/enum/", ["0a", "1b", "2c"])).trim()).toBe(`enum MyEnum { Value0a = "0a", Value1b = "1b", Value2c = "2c" @@ -136,8 +104,7 @@ describe("tsEnum", () => { }); test("number members", () => { - expect(astToString(tsEnum(".Error.code.", [100, 101, 102, -100])).trim()) - .toBe(`enum ErrorCode { + expect(astToString(tsEnum(".Error.code.", [100, 101, 102, -100])).trim()).toBe(`enum ErrorCode { Value100 = 100, Value101 = 101, Value102 = 102, @@ -151,11 +118,7 @@ describe("tsEnum", () => { tsEnum( ".Error.code.", [100, 101, 102], - [ - { description: "Code 100" }, - { description: "Code 101" }, - { description: "Code 102" }, - ], + [{ description: "Code 100" }, { description: "Code 101" }, { description: "Code 102" }], ), ).trim(), ).toBe(`enum ErrorCode { @@ -174,11 +137,7 @@ describe("tsEnum", () => { tsEnum( ".Error.code.", [100, 101, 102], - [ - { name: "Unauthorized" }, - { name: "NotFound" }, - { name: "PermissionDenied" }, - ], + [{ name: "Unauthorized" }, { name: "NotFound" }, { name: "PermissionDenied" }], ), ).trim(), ).toBe(`enum ErrorCode { @@ -190,13 +149,7 @@ describe("tsEnum", () => { test("x-enum-varnames with numeric prefix", () => { expect( - astToString( - tsEnum( - ".Error.code.", - [100, 101, 102], - [{ name: "0a" }, { name: "1b" }, { name: "2c" }], - ), - ).trim(), + astToString(tsEnum(".Error.code.", [100, 101, 102], [{ name: "0a" }, { name: "1b" }, { name: "2c" }])).trim(), ).toBe(`enum ErrorCode { Value0a = 100, Value1b = 101, @@ -210,10 +163,7 @@ describe("tsEnum", () => { tsEnum( ".Error.code.", [100, 101, 102], - [ - { name: "Unauthorized", description: "User is unauthorized" }, - { name: "NotFound" }, - ], + [{ name: "Unauthorized", description: "User is unauthorized" }, { name: "NotFound" }], ), ).trim(), ).toBe(`enum ErrorCode { @@ -253,32 +203,24 @@ describe("tsEnum", () => { describe("tsPropertyIndex", () => { test("numbers -> number literals", () => { - expect(astToString(tsPropertyIndex(200)).trim()).toBe(`200`); - expect(astToString(tsPropertyIndex(200.5)).trim()).toBe(`200.5`); - expect(astToString(tsPropertyIndex(Infinity)).trim()).toBe(`Infinity`); - expect(astToString(tsPropertyIndex(NaN)).trim()).toBe(`NaN`); - expect(astToString(tsPropertyIndex(10e3)).trim()).toBe(`10000`); + expect(astToString(tsPropertyIndex(200)).trim()).toBe("200"); + expect(astToString(tsPropertyIndex(200.5)).trim()).toBe("200.5"); + expect(astToString(tsPropertyIndex(Number.POSITIVE_INFINITY)).trim()).toBe("Infinity"); + expect(astToString(tsPropertyIndex(Number.NaN)).trim()).toBe("NaN"); + expect(astToString(tsPropertyIndex(10e3)).trim()).toBe("10000"); }); test("valid strings -> identifiers", () => { - expect(astToString(tsPropertyIndex("identifier")).trim()).toBe( - `identifier`, - ); - expect(astToString(tsPropertyIndex("snake_case")).trim()).toBe( - `snake_case`, - ); - expect(astToString(tsPropertyIndex(200)).trim()).toBe(`200`); - expect(astToString(tsPropertyIndex("$id")).trim()).toBe(`$id`); + expect(astToString(tsPropertyIndex("identifier")).trim()).toBe("identifier"); + expect(astToString(tsPropertyIndex("snake_case")).trim()).toBe("snake_case"); + expect(astToString(tsPropertyIndex(200)).trim()).toBe("200"); + expect(astToString(tsPropertyIndex("$id")).trim()).toBe("$id"); expect(astToString(tsPropertyIndex("10e3")).trim()).toBe(`"10e3"`); }); test("invalid strings -> string literals", () => { - expect(astToString(tsPropertyIndex("kebab-case")).trim()).toBe( - `"kebab-case"`, - ); - expect(astToString(tsPropertyIndex("application/json")).trim()).toBe( - `"application/json"`, - ); + expect(astToString(tsPropertyIndex("kebab-case")).trim()).toBe(`"kebab-case"`); + expect(astToString(tsPropertyIndex("application/json")).trim()).toBe(`"application/json"`); expect(astToString(tsPropertyIndex("0invalid")).trim()).toBe(`"0invalid"`); expect(astToString(tsPropertyIndex("inv@lid")).trim()).toBe(`"inv@lid"`); expect(astToString(tsPropertyIndex("in.valid")).trim()).toBe(`"in.valid"`); @@ -311,14 +253,7 @@ describe("tsIsPrimitive", () => { test("object", () => { expect( tsIsPrimitive( - ts.factory.createTypeLiteralNode([ - ts.factory.createPropertySignature( - undefined, - "foo", - undefined, - STRING, - ), - ]), + ts.factory.createTypeLiteralNode([ts.factory.createPropertySignature(undefined, "foo", undefined, STRING)]), ), ).toBe(false); }); @@ -326,25 +261,21 @@ describe("tsIsPrimitive", () => { describe("tsUnion", () => { test("none", () => { - expect(astToString(tsUnion([])).trim()).toBe(`never`); + expect(astToString(tsUnion([])).trim()).toBe("never"); }); test("one", () => { - expect(astToString(tsUnion([STRING])).trim()).toBe(`string`); + expect(astToString(tsUnion([STRING])).trim()).toBe("string"); }); test("multiple (primitive)", () => { - expect( - astToString(tsUnion([STRING, STRING, NUMBER, NULL, NUMBER, NULL])).trim(), - ).toBe(`string | number | null`); + expect(astToString(tsUnion([STRING, STRING, NUMBER, NULL, NUMBER, NULL])).trim()).toBe("string | number | null"); }); test("multiple (const)", () => { - expect( - astToString( - tsUnion([NULL, tsLiteral("red"), tsLiteral(42), tsLiteral(false)]), - ).trim(), - ).toBe(`null | "red" | 42 | false`); + expect(astToString(tsUnion([NULL, tsLiteral("red"), tsLiteral(42), tsLiteral(false)])).trim()).toBe( + `null | "red" | 42 | false`, + ); }); test("multiple (object types)", () => { diff --git a/packages/openapi-typescript/test/lib/utils.test.ts b/packages/openapi-typescript/test/lib/utils.test.ts index e97babd58..2902b92b9 100644 --- a/packages/openapi-typescript/test/lib/utils.test.ts +++ b/packages/openapi-typescript/test/lib/utils.test.ts @@ -10,9 +10,7 @@ describe("getEntries", () => { describe("options", () => { test("alphabetize: true", () => { - expect( - getEntries({ z: "z", 0: 0, a: "a" }, { alphabetize: true }), - ).toEqual([ + expect(getEntries({ z: "z", 0: 0, a: "a" }, { alphabetize: true })).toEqual([ ["0", 0], ["a", "a"], ["z", "z"], @@ -41,23 +39,17 @@ describe("getEntries", () => { describe("createRef", () => { test("basic", () => { - expect(createRef(["components", "schemas", "SchemaObject"])).toBe( - "#/components/schemas/SchemaObject", - ); + expect(createRef(["components", "schemas", "SchemaObject"])).toBe("#/components/schemas/SchemaObject"); }); test("escapes", () => { - expect(createRef(["paths", "/foo/{bar}", "get", "parameters"])).toBe( - "#/paths/~1foo~1{bar}/get/parameters", - ); - expect(createRef(["components", "schemas", "~SchemaObject"])).toBe( - "#/components/schemas/~0SchemaObject", - ); + expect(createRef(["paths", "/foo/{bar}", "get", "parameters"])).toBe("#/paths/~1foo~1{bar}/get/parameters"); + expect(createRef(["components", "schemas", "~SchemaObject"])).toBe("#/components/schemas/~0SchemaObject"); }); test("handles partial paths", () => { - expect( - createRef(["#/paths/~1foo~1{bar}", "parameters", "query", "page"]), - ).toBe("#/paths/~1foo~1{bar}/parameters/query/page"); + expect(createRef(["#/paths/~1foo~1{bar}", "parameters", "query", "page"])).toBe( + "#/paths/~1foo~1{bar}/parameters/query/page", + ); }); }); diff --git a/packages/openapi-typescript/test/node-api.test.ts b/packages/openapi-typescript/test/node-api.test.ts index 5822dddae..b2cfc01cf 100644 --- a/packages/openapi-typescript/test/node-api.test.ts +++ b/packages/openapi-typescript/test/node-api.test.ts @@ -6,9 +6,7 @@ import type { TestCase } from "./test-helpers.js"; const EXAMPLES_DIR = new URL("../examples/", import.meta.url); -const DATE = ts.factory.createTypeReferenceNode( - ts.factory.createIdentifier("Date"), -); +const DATE = ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("Date")); describe("Node.js API", () => { const tests: TestCase[] = [ @@ -59,8 +57,7 @@ export type operations = Record;`, [ "input > string > URL", { - given: - "https://raw.githubusercontent.com/Redocly/redocly-cli/main/__tests__/lint/oas3.1/openapi.yaml", + given: "https://raw.githubusercontent.com/Redocly/redocly-cli/main/__tests__/lint/oas3.1/openapi.yaml", want: new URL("simple-example.ts", EXAMPLES_DIR), // options: DEFAULT_OPTIONS, }, @@ -68,9 +65,7 @@ export type operations = Record;`, [ "input > URL > remote", { - given: new URL( - "https://raw.githubusercontent.com/Redocly/redocly-cli/main/__tests__/lint/oas3.1/openapi.yaml", - ), + given: new URL("https://raw.githubusercontent.com/Redocly/redocly-cli/main/__tests__/lint/oas3.1/openapi.yaml"), want: new URL("simple-example.ts", EXAMPLES_DIR), // options: DEFAULT_OPTIONS, }, @@ -377,10 +372,7 @@ export type $defs = Record; export type operations = Record;`, options: { transform(schemaObject) { - if ( - "format" in schemaObject && - schemaObject.format === "date-time" - ) { + if ("format" in schemaObject && schemaObject.format === "date-time") { /** * Tip: use astexplorer.net to first type out the desired TypeScript, * then use the `typescript` parser and it will tell you the desired @@ -421,10 +413,7 @@ export type $defs = Record; export type operations = Record;`, options: { transform(schemaObject) { - if ( - "format" in schemaObject && - schemaObject.format === "date-time" - ) { + if ("format" in schemaObject && schemaObject.format === "date-time") { return { schema: DATE, questionToken: true, @@ -469,9 +458,7 @@ export type operations = Record;`, * then use the `typescript` parser and it will tell you the desired * AST */ - return ts.factory.createTypeReferenceNode( - ts.factory.createIdentifier("DateOrTime"), - ); + return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("DateOrTime")); } }, }, @@ -523,11 +510,7 @@ export type operations = Record;`, type: "number", enum: [1, 2, 3], "x-enumNames": ["Uno", "Dos", "Tres"], - "x-enumDescriptions": [ - "El número uno", - "El número dos", - "El número tres", - ], + "x-enumDescriptions": ["El número uno", "El número dos", "El número tres"], }, }, }, @@ -655,10 +638,7 @@ export type operations = Record;`, [ "snapshot > DigitalOcean", { - given: new URL( - "./digital-ocean-api/DigitalOcean-public.v2.yaml", - EXAMPLES_DIR, - ), + given: new URL("./digital-ocean-api/DigitalOcean-public.v2.yaml", EXAMPLES_DIR), want: new URL("./digital-ocean-api.ts", EXAMPLES_DIR), // options: DEFAULT_OPTIONS, ci: { timeout: 30000 }, @@ -672,11 +652,9 @@ export type operations = Record;`, async () => { const result = astToString(await openapiTS(given, options)); if (want instanceof URL) { - expect(`${COMMENT_HEADER}${result}`).toMatchFileSnapshot( - fileURLToPath(want), - ); + expect(`${COMMENT_HEADER}${result}`).toMatchFileSnapshot(fileURLToPath(want)); } else { - expect(result).toBe(want + "\n"); + expect(result).toBe(`${want}\n`); } }, ci?.timeout || 5000, diff --git a/packages/openapi-typescript/test/test-helpers.ts b/packages/openapi-typescript/test/test-helpers.ts index 21f2cb87c..730dd0964 100644 --- a/packages/openapi-typescript/test/test-helpers.ts +++ b/packages/openapi-typescript/test/test-helpers.ts @@ -2,8 +2,6 @@ import { createConfig } from "@redocly/openapi-core"; import { resolveRef } from "../src/lib/utils.js"; import type { GlobalContext, TransformNodeOptions } from "../src/types.js"; -/* eslint-disable @typescript-eslint/no-explicit-any */ - /** Default options for all transform* functions */ export const DEFAULT_CTX: GlobalContext = { additionalProperties: false, diff --git a/packages/openapi-typescript/test/transform/components-object.test.ts b/packages/openapi-typescript/test/transform/components-object.test.ts index 380475ca4..2c7a93c22 100644 --- a/packages/openapi-typescript/test/transform/components-object.test.ts +++ b/packages/openapi-typescript/test/transform/components-object.test.ts @@ -505,20 +505,15 @@ describe("transformComponentsObject", () => { ], ]; - for (const [ - testName, - { given, want, options = DEFAULT_OPTIONS, ci }, - ] of tests) { + for (const [testName, { given, want, options = DEFAULT_OPTIONS, ci }] of tests) { test.skipIf(ci?.skipIf)( testName, async () => { - const result = astToString( - transformComponentsObject(given, options ?? DEFAULT_OPTIONS), - ); + const result = astToString(transformComponentsObject(given, options ?? DEFAULT_OPTIONS)); if (want instanceof URL) { expect(result).toMatchFileSnapshot(fileURLToPath(want)); } else { - expect(result).toBe(want + "\n"); + expect(result).toBe(`${want}\n`); } }, ci?.timeout, diff --git a/packages/openapi-typescript/test/transform/header-object.test.ts b/packages/openapi-typescript/test/transform/header-object.test.ts index 5340a7cb7..09b62bcb6 100644 --- a/packages/openapi-typescript/test/transform/header-object.test.ts +++ b/packages/openapi-typescript/test/transform/header-object.test.ts @@ -19,22 +19,19 @@ describe("transformHeaderObject", () => { type: "string", }, }, - want: `string`, + want: "string", // options: DEFAULT_OPTIONS, }, ], ]; - for (const [ - testName, - { given, want, options = DEFAULT_OPTIONS, ci }, - ] of tests) { + for (const [testName, { given, want, options = DEFAULT_OPTIONS, ci }] of tests) { test.skipIf(ci?.skipIf)(testName, async () => { const result = astToString(transformHeaderObject(given, options)); if (want instanceof URL) { expect(result).toMatchFileSnapshot(fileURLToPath(want)); } else { - expect(result).toBe(want + "\n"); + expect(result).toBe(`${want}\n`); } }); } diff --git a/packages/openapi-typescript/test/transform/operation-object.test.ts b/packages/openapi-typescript/test/transform/operation-object.test.ts index 6a594f8ea..6cf28e61a 100644 --- a/packages/openapi-typescript/test/transform/operation-object.test.ts +++ b/packages/openapi-typescript/test/transform/operation-object.test.ts @@ -284,10 +284,7 @@ responses: { ], ]; - for (const [ - testName, - { given, want, options = DEFAULT_OPTIONS, ci }, - ] of tests) { + for (const [testName, { given, want, options = DEFAULT_OPTIONS, ci }] of tests) { test.skipIf(ci?.skipIf)( testName, async () => { @@ -295,7 +292,7 @@ responses: { if (want instanceof URL) { expect(result).toMatchFileSnapshot(fileURLToPath(want)); } else { - expect(result).toBe(want + "\n"); + expect(result).toBe(`${want}\n`); } }, ci?.timeout, diff --git a/packages/openapi-typescript/test/transform/path-item-object.test.ts b/packages/openapi-typescript/test/transform/path-item-object.test.ts index 2eda37c3b..ed0e697e3 100644 --- a/packages/openapi-typescript/test/transform/path-item-object.test.ts +++ b/packages/openapi-typescript/test/transform/path-item-object.test.ts @@ -361,10 +361,7 @@ describe("transformPathItemObject", () => { ], ]; - for (const [ - testName, - { given, want, options = DEFAULT_OPTIONS, ci }, - ] of tests) { + for (const [testName, { given, want, options = DEFAULT_OPTIONS, ci }] of tests) { test.skipIf(ci?.skipIf)( testName, async () => { @@ -372,7 +369,7 @@ describe("transformPathItemObject", () => { if (want instanceof URL) { expect(result).toMatchFileSnapshot(fileURLToPath(want)); } else { - expect(result).toBe(want + "\n"); + expect(result).toBe(`${want}\n`); } }, ci?.timeout, diff --git a/packages/openapi-typescript/test/transform/paths-object.test.ts b/packages/openapi-typescript/test/transform/paths-object.test.ts index 96e8bc0a9..6319ce026 100644 --- a/packages/openapi-typescript/test/transform/paths-object.test.ts +++ b/packages/openapi-typescript/test/transform/paths-object.test.ts @@ -22,9 +22,7 @@ describe("transformPathsObject", () => { }, ], get: { - parameters: [ - { name: "user_id", in: "path", description: "User ID." }, - ], + parameters: [{ name: "user_id", in: "path", description: "User ID." }], responses: { 200: { description: "OK", @@ -370,10 +368,7 @@ describe("transformPathsObject", () => { ], ]; - for (const [ - testName, - { given, want, options = DEFAULT_OPTIONS, ci }, - ] of tests) { + for (const [testName, { given, want, options = DEFAULT_OPTIONS, ci }] of tests) { test.skipIf(ci?.skipIf)( testName, async () => { @@ -381,7 +376,7 @@ describe("transformPathsObject", () => { if (want instanceof URL) { expect(result).toMatchFileSnapshot(fileURLToPath(want)); } else { - expect(result).toBe(want + "\n"); + expect(result).toBe(`${want}\n`); } }, ci?.timeout, diff --git a/packages/openapi-typescript/test/transform/request-body-object.test.ts b/packages/openapi-typescript/test/transform/request-body-object.test.ts index a00b6ce4f..754861187 100644 --- a/packages/openapi-typescript/test/transform/request-body-object.test.ts +++ b/packages/openapi-typescript/test/transform/request-body-object.test.ts @@ -94,10 +94,7 @@ describe("transformRequestBodyObject", () => { ], ]; - for (const [ - testName, - { given, want, options = DEFAULT_OPTIONS, ci }, - ] of tests) { + for (const [testName, { given, want, options = DEFAULT_OPTIONS, ci }] of tests) { test.skipIf(ci?.skipIf)( testName, async () => { @@ -105,7 +102,7 @@ describe("transformRequestBodyObject", () => { if (want instanceof URL) { expect(result).toMatchFileSnapshot(fileURLToPath(want)); } else { - expect(result).toBe(want + "\n"); + expect(result).toBe(`${want}\n`); } }, ci?.timeout, diff --git a/packages/openapi-typescript/test/transform/response-object.test.ts b/packages/openapi-typescript/test/transform/response-object.test.ts index 974ebc6af..f370aab08 100644 --- a/packages/openapi-typescript/test/transform/response-object.test.ts +++ b/packages/openapi-typescript/test/transform/response-object.test.ts @@ -72,10 +72,7 @@ describe("transformResponseObject", () => { ], ]; - for (const [ - testName, - { given, want, options = DEFAULT_OPTIONS, ci }, - ] of tests) { + for (const [testName, { given, want, options = DEFAULT_OPTIONS, ci }] of tests) { test.skipIf(ci?.skipIf)( testName, async () => { @@ -83,7 +80,7 @@ describe("transformResponseObject", () => { if (want instanceof URL) { expect(result).toMatchFileSnapshot(fileURLToPath(want)); } else { - expect(result).toBe(want + "\n"); + expect(result).toBe(`${want}\n`); } }, ci?.timeout, diff --git a/packages/openapi-typescript/test/transform/schema-object/array.test.ts b/packages/openapi-typescript/test/transform/schema-object/array.test.ts index a55a5a3bc..dea4783b3 100644 --- a/packages/openapi-typescript/test/transform/schema-object/array.test.ts +++ b/packages/openapi-typescript/test/transform/schema-object/array.test.ts @@ -14,7 +14,7 @@ describe("transformSchemaObject > array", () => { "basic", { given: { type: "array", items: { type: "string" } }, - want: `string[]`, + want: "string[]", // options: DEFAULT_OPTIONS, }, ], @@ -40,11 +40,7 @@ describe("transformSchemaObject > array", () => { given: { type: "array", items: { type: "number" }, - prefixItems: [ - { type: "number" }, - { type: "number" }, - { type: "number" }, - ], + prefixItems: [{ type: "number" }, { type: "number" }, { type: "number" }], }, want: `[ number, @@ -69,7 +65,7 @@ describe("transformSchemaObject > array", () => { "nullable", { given: { type: ["array", "null"], items: { type: "string" } }, - want: `string[] | null`, + want: "string[] | null", // options: DEFAULT_OPTIONS, }, ], @@ -77,7 +73,7 @@ describe("transformSchemaObject > array", () => { "nullable (deprecated syntax)", { given: { type: "array", items: { type: "string" }, nullable: true }, - want: `string[] | null`, + want: "string[] | null", // options: DEFAULT_OPTIONS, }, ], @@ -85,7 +81,7 @@ describe("transformSchemaObject > array", () => { "nullable items", { given: { type: "array", items: { type: ["string", "null"] } }, - want: `(string | null)[]`, + want: "(string | null)[]", // options: DEFAULT_OPTIONS, }, ], @@ -93,7 +89,7 @@ describe("transformSchemaObject > array", () => { "nullable items (deprecated syntax)", { given: { type: "array", items: { type: "string", nullable: true } }, - want: `(string | null)[]`, + want: "(string | null)[]", // options: DEFAULT_OPTIONS, }, ], @@ -101,7 +97,7 @@ describe("transformSchemaObject > array", () => { "options > arrayLength: true > default", { given: { type: "array", items: { type: "string" } }, - want: `string[]`, + want: "string[]", options: { ...DEFAULT_OPTIONS, ctx: { ...DEFAULT_OPTIONS.ctx, arrayLength: true }, @@ -143,7 +139,7 @@ describe("transformSchemaObject > array", () => { "options > arrayLength: true > maxItems: 20", { given: { type: "array", items: { type: "string" }, maxItems: 20 }, - want: `string[]`, + want: "string[]", options: { ...DEFAULT_OPTIONS, ctx: { ...DEFAULT_OPTIONS.ctx, arrayLength: true }, @@ -157,7 +153,7 @@ describe("transformSchemaObject > array", () => { type: "array", items: { type: "array", items: { type: "string" } }, }, - want: `string[][]`, + want: "string[][]", options: { ...DEFAULT_OPTIONS, ctx: { ...DEFAULT_OPTIONS.ctx, immutable: true }, @@ -166,10 +162,7 @@ describe("transformSchemaObject > array", () => { ], ]; - for (const [ - testName, - { given, want, options = DEFAULT_OPTIONS, ci }, - ] of tests) { + for (const [testName, { given, want, options = DEFAULT_OPTIONS, ci }] of tests) { test.skipIf(ci?.skipIf)( testName, async () => { @@ -177,7 +170,7 @@ describe("transformSchemaObject > array", () => { if (want instanceof URL) { expect(result).toMatchFileSnapshot(fileURLToPath(want)); } else { - expect(result).toBe(want + "\n"); + expect(result).toBe(`${want}\n`); } }, ci?.timeout, diff --git a/packages/openapi-typescript/test/transform/schema-object/boolean.test.ts b/packages/openapi-typescript/test/transform/schema-object/boolean.test.ts index c80f74f9f..aafc319d3 100644 --- a/packages/openapi-typescript/test/transform/schema-object/boolean.test.ts +++ b/packages/openapi-typescript/test/transform/schema-object/boolean.test.ts @@ -14,7 +14,7 @@ describe("transformSchemaObject > boolean", () => { "basic", { given: { type: "boolean" }, - want: `boolean`, + want: "boolean", // options: DEFAULT_OPTIONS, }, ], @@ -22,7 +22,7 @@ describe("transformSchemaObject > boolean", () => { "enum", { given: { type: "boolean", enum: [false] }, - want: `false`, + want: "false", // options: DEFAULT_OPTIONS, }, ], @@ -30,7 +30,7 @@ describe("transformSchemaObject > boolean", () => { "nullable", { given: { type: ["boolean", "null"] }, - want: `boolean | null`, + want: "boolean | null", // options: DEFAULT_OPTIONS, }, ], @@ -38,16 +38,13 @@ describe("transformSchemaObject > boolean", () => { "nullable (deprecated syntax)", { given: { type: "boolean", nullable: true }, - want: `boolean | null`, + want: "boolean | null", // options: DEFAULT_OPTIONS, }, ], ]; - for (const [ - testName, - { given, want, options = DEFAULT_OPTIONS, ci }, - ] of tests) { + for (const [testName, { given, want, options = DEFAULT_OPTIONS, ci }] of tests) { test.skipIf(ci?.skipIf)( testName, async () => { @@ -55,7 +52,7 @@ describe("transformSchemaObject > boolean", () => { if (want instanceof URL) { expect(result).toMatchFileSnapshot(fileURLToPath(want)); } else { - expect(result).toBe(want + "\n"); + expect(result).toBe(`${want}\n`); } }, ci?.timeout, diff --git a/packages/openapi-typescript/test/transform/schema-object/composition.test.ts b/packages/openapi-typescript/test/transform/schema-object/composition.test.ts index af8c45077..776ec3af3 100644 --- a/packages/openapi-typescript/test/transform/schema-object/composition.test.ts +++ b/packages/openapi-typescript/test/transform/schema-object/composition.test.ts @@ -16,7 +16,7 @@ describe("composition", () => { given: { type: ["string", "boolean", "number", "null"], }, - want: `string | boolean | number | null`, + want: "string | boolean | number | null", // options: DEFAULT_OPTIONS, }, ], @@ -27,7 +27,7 @@ describe("composition", () => { type: ["string", "null"], enum: [null, "blue", "green", "yellow"], }, - want: `null | "blue" | "green" | "yellow"`, + want: 'null | "blue" | "green" | "yellow"', // options: DEFAULT_OPTIONS, }, ], @@ -38,7 +38,7 @@ describe("composition", () => { type: ["string", "null"], enum: ["blue", "green", "yellow"], }, - want: `"blue" | "green" | "yellow"`, + want: '"blue" | "green" | "yellow"', // options: DEFAULT_OPTIONS, }, ], @@ -49,7 +49,7 @@ describe("composition", () => { type: ["string", "null"], enum: ["", "blue", "green", "yellow"], }, - want: `"" | "blue" | "green" | "yellow"`, + want: '"" | "blue" | "green" | "yellow"', // options: DEFAULT_OPTIONS, }, ], @@ -57,7 +57,7 @@ describe("composition", () => { "oneOf > primitives", { given: { oneOf: [{ type: "string" }, { type: "number" }] }, - want: `string | number`, + want: "string | number", // options: DEFAULT_OPTIONS, }, ], @@ -70,7 +70,7 @@ describe("composition", () => { { type: "string", const: "world" }, ], }, - want: `"hello" | "world"`, + want: '"hello" | "world"', // options: DEFAULT_OPTIONS, }, ], @@ -83,7 +83,7 @@ describe("composition", () => { { type: "number", const: 1 }, ], }, - want: `0 | 1`, + want: "0 | 1", // options: DEFAULT_OPTIONS, }, ], @@ -93,7 +93,7 @@ describe("composition", () => { given: { oneOf: [{ type: "integer" }, { type: "string" }, { type: "null" }], }, - want: `number | string | null`, + want: "number | string | null", // options: DEFAULT_OPTIONS, }, ], @@ -104,7 +104,7 @@ describe("composition", () => { oneOf: [{ type: "integer" }, { type: "string" }], nullable: true, }, - want: `(number | string) | null`, + want: "(number | string) | null", // options: DEFAULT_OPTIONS, }, ], @@ -156,7 +156,7 @@ describe("composition", () => { oneOf: [{ type: "integer" }, { type: "string" }], type: ["null", "integer", "string"], }, - want: `null | number | string`, + want: "null | number | string", // options: DEFAULT_OPTIONS, }, ], @@ -258,10 +258,7 @@ describe("composition", () => { "discriminator > oneOf", { given: { - oneOf: [ - { $ref: "#/components/schemas/Cat" }, - { $ref: "#/components/schemas/Dog" }, - ], + oneOf: [{ $ref: "#/components/schemas/Cat" }, { $ref: "#/components/schemas/Dog" }], }, want: `components["schemas"]["Cat"] | components["schemas"]["Dog"]`, options: { @@ -309,10 +306,7 @@ describe("composition", () => { properties: { name: { type: "string" }, }, - oneOf: [ - { $ref: "#/components/schemas/Cat" }, - { $ref: "#/components/schemas/Dog" }, - ], + oneOf: [{ $ref: "#/components/schemas/Cat" }, { $ref: "#/components/schemas/Dog" }], }, want: `{ name: string; @@ -620,10 +614,7 @@ describe("composition", () => { ], ]; - for (const [ - testName, - { given, want, options = DEFAULT_OPTIONS, ci }, - ] of tests) { + for (const [testName, { given, want, options = DEFAULT_OPTIONS, ci }] of tests) { test.skipIf(ci?.skipIf)( testName, async () => { @@ -631,7 +622,7 @@ describe("composition", () => { if (want instanceof URL) { expect(result).toMatchFileSnapshot(fileURLToPath(want)); } else { - expect(result).toBe(want + "\n"); + expect(result).toBe(`${want}\n`); } }, ci?.timeout, diff --git a/packages/openapi-typescript/test/transform/schema-object/empty.test.ts b/packages/openapi-typescript/test/transform/schema-object/empty.test.ts index eacca350a..54ebc1d92 100644 --- a/packages/openapi-typescript/test/transform/schema-object/empty.test.ts +++ b/packages/openapi-typescript/test/transform/schema-object/empty.test.ts @@ -14,7 +14,7 @@ describe("transformSchemaObject > empty/unknown", () => { "true", { given: true, - want: `unknown`, + want: "unknown", // options: DEFAULT_OPTIONS, }, ], @@ -22,7 +22,7 @@ describe("transformSchemaObject > empty/unknown", () => { "false", { given: false, - want: `never`, + want: "never", // options: DEFAULT_OPTIONS, }, ], @@ -30,16 +30,13 @@ describe("transformSchemaObject > empty/unknown", () => { "empty object", { given: {}, - want: `unknown`, + want: "unknown", // options: DEFAULT_OPTIONS, }, ], ]; - for (const [ - testName, - { given, want, options = DEFAULT_OPTIONS, ci }, - ] of tests) { + for (const [testName, { given, want, options = DEFAULT_OPTIONS, ci }] of tests) { test.skipIf(ci?.skipIf)( testName, async () => { @@ -47,7 +44,7 @@ describe("transformSchemaObject > empty/unknown", () => { if (want instanceof URL) { expect(result).toMatchFileSnapshot(fileURLToPath(want)); } else { - expect(result).toBe(want + "\n"); + expect(result).toBe(`${want}\n`); } }, ci?.timeout, diff --git a/packages/openapi-typescript/test/transform/schema-object/number.test.ts b/packages/openapi-typescript/test/transform/schema-object/number.test.ts index bdca28412..69cb66b81 100644 --- a/packages/openapi-typescript/test/transform/schema-object/number.test.ts +++ b/packages/openapi-typescript/test/transform/schema-object/number.test.ts @@ -14,7 +14,7 @@ describe("transformSchemaObject > number", () => { "basic", { given: { type: "number" }, - want: `number`, + want: "number", // options: DEFAULT_OPTIONS, }, ], @@ -22,7 +22,7 @@ describe("transformSchemaObject > number", () => { "enum", { given: { type: "number", enum: [50, 100, 200] }, - want: `50 | 100 | 200`, + want: "50 | 100 | 200", // options: DEFAULT_OPTIONS, }, ], @@ -30,7 +30,7 @@ describe("transformSchemaObject > number", () => { "integer", { given: { type: "integer" }, - want: `number`, + want: "number", // options: DEFAULT_OPTIONS, }, ], @@ -38,7 +38,7 @@ describe("transformSchemaObject > number", () => { "nullable", { given: { type: ["number", "null"] }, - want: `number | null`, + want: "number | null", // options: DEFAULT_OPTIONS, }, ], @@ -46,16 +46,13 @@ describe("transformSchemaObject > number", () => { "nullable (deprecated syntax)", { given: { type: "number", nullable: true }, - want: `number | null`, + want: "number | null", // options: DEFAULT_OPTIONS, }, ], ]; - for (const [ - testName, - { given, want, options = DEFAULT_OPTIONS, ci }, - ] of tests) { + for (const [testName, { given, want, options = DEFAULT_OPTIONS, ci }] of tests) { test.skipIf(ci?.skipIf)( testName, async () => { @@ -63,7 +60,7 @@ describe("transformSchemaObject > number", () => { if (want instanceof URL) { expect(result).toMatchFileSnapshot(fileURLToPath(want)); } else { - expect(result).toBe(want + "\n"); + expect(result).toBe(`${want}\n`); } }, ci?.timeout, diff --git a/packages/openapi-typescript/test/transform/schema-object/object.test.ts b/packages/openapi-typescript/test/transform/schema-object/object.test.ts index 6b1f26ff5..2fa50c557 100644 --- a/packages/openapi-typescript/test/transform/schema-object/object.test.ts +++ b/packages/openapi-typescript/test/transform/schema-object/object.test.ts @@ -32,7 +32,7 @@ describe("transformSchemaObject > object", () => { "empty", { given: { type: "object" }, - want: `Record`, + want: "Record", // options: DEFAULT_OPTIONS, }, ], @@ -199,7 +199,7 @@ describe("transformSchemaObject > object", () => { "const > number (inferred)", { given: { const: 300 }, - want: `300`, + want: "300", }, ], [ @@ -257,7 +257,7 @@ describe("transformSchemaObject > object", () => { "options > emptyObjectsUnknown: true", { given: { type: "object" }, - want: `Record`, + want: "Record", options: { ...DEFAULT_OPTIONS, ctx: { ...DEFAULT_OPTIONS.ctx, emptyObjectsUnknown: true }, @@ -284,7 +284,7 @@ describe("transformSchemaObject > object", () => { given: { type: "string", }, - want: `string`, + want: "string", options: { ...DEFAULT_OPTIONS, ctx: { ...DEFAULT_OPTIONS.ctx, immutable: true }, @@ -409,10 +409,7 @@ describe("transformSchemaObject > object", () => { ], ]; - for (const [ - testName, - { given, want, options = DEFAULT_OPTIONS, ci }, - ] of tests) { + for (const [testName, { given, want, options = DEFAULT_OPTIONS, ci }] of tests) { test.skipIf(ci?.skipIf)( testName, async () => { @@ -420,7 +417,7 @@ describe("transformSchemaObject > object", () => { if (want instanceof URL) { expect(result).toMatchFileSnapshot(fileURLToPath(want)); } else { - expect(result).toBe(want + "\n"); + expect(result).toBe(`${want}\n`); } }, ci?.timeout, diff --git a/packages/openapi-typescript/test/transform/schema-object/string.test.ts b/packages/openapi-typescript/test/transform/schema-object/string.test.ts index 025ba8682..dc35d2b10 100644 --- a/packages/openapi-typescript/test/transform/schema-object/string.test.ts +++ b/packages/openapi-typescript/test/transform/schema-object/string.test.ts @@ -14,7 +14,7 @@ describe("transformSchemaObject > string", () => { "basic", { given: { type: "string" }, - want: `string`, + want: "string", // options: DEFAULT_OPTIONS, }, ], @@ -57,8 +57,7 @@ describe("transformSchemaObject > string", () => { "enum (quotes)", { // prettier-ignore - // eslint-disable-next-line no-useless-escape - given: { type: "string", enum: ['"', "'", '\"', "`"] }, + given: { type: "string", enum: ['"', "'", '"', "`"] }, want: `"\\"" | "'" | "\\"" | "\`"`, }, ], @@ -66,7 +65,7 @@ describe("transformSchemaObject > string", () => { "nullable", { given: { type: ["string", "null"] }, - want: `string | null`, + want: "string | null", // options: DEFAULT_OPTIONS, }, ], @@ -74,16 +73,13 @@ describe("transformSchemaObject > string", () => { "nullable (deprecated syntax)", { given: { type: "string", nullable: true }, - want: `string | null`, + want: "string | null", // options: DEFAULT_OPTIONS, }, ], ]; - for (const [ - testName, - { given, want, options = DEFAULT_OPTIONS, ci }, - ] of tests) { + for (const [testName, { given, want, options = DEFAULT_OPTIONS, ci }] of tests) { test.skipIf(ci?.skipIf)( testName, async () => { @@ -91,7 +87,7 @@ describe("transformSchemaObject > string", () => { if (want instanceof URL) { expect(result).toMatchFileSnapshot(fileURLToPath(want)); } else { - expect(result).toBe(want + "\n"); + expect(result).toBe(`${want}\n`); } }, ci?.timeout, diff --git a/packages/openapi-typescript/test/transform/webhooks-object.test.ts b/packages/openapi-typescript/test/transform/webhooks-object.test.ts index 69e1513c1..b4bd946bd 100644 --- a/packages/openapi-typescript/test/transform/webhooks-object.test.ts +++ b/packages/openapi-typescript/test/transform/webhooks-object.test.ts @@ -39,8 +39,7 @@ describe("transformWebhooksObject", () => { }, responses: { 200: { - description: - "Return a 200 status to indicate that the data was received successfully", + description: "Return a 200 status to indicate that the data was received successfully", }, }, }, @@ -180,10 +179,7 @@ describe("transformWebhooksObject", () => { ], ]; - for (const [ - testName, - { given, want, options = DEFAULT_OPTIONS, ci }, - ] of tests) { + for (const [testName, { given, want, options = DEFAULT_OPTIONS, ci }] of tests) { test.skipIf(ci?.skipIf)( testName, async () => { @@ -191,7 +187,7 @@ describe("transformWebhooksObject", () => { if (want instanceof URL) { expect(result).toMatchFileSnapshot(fileURLToPath(want)); } else { - expect(result).toBe(want + "\n"); + expect(result).toBe(`${want}\n`); } }, ci?.timeout, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c1a8f1af6..f9b025605 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,39 +8,18 @@ importers: .: devDependencies: + '@biomejs/biome': + specifier: ^1.7.1 + version: 1.7.1 '@changesets/changelog-github': specifier: ^0.5.0 version: 0.5.0 '@changesets/cli': specifier: ^2.27.1 version: 2.27.1 - '@typescript-eslint/eslint-plugin': - specifier: ^7.7.1 - version: 7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/parser': - specifier: ^7.7.1 - version: 7.7.1(eslint@8.57.0)(typescript@5.4.5) del-cli: specifier: ^5.1.0 version: 5.1.0 - eslint: - specifier: ^8.57.0 - version: 8.57.0 - eslint-config-prettier: - specifier: ^9.1.0 - version: 9.1.0(eslint@8.57.0) - eslint-plugin-import: - specifier: ^2.29.1 - version: 2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0) - eslint-plugin-no-only-tests: - specifier: ^3.1.0 - version: 3.1.0 - eslint-plugin-prettier: - specifier: ^5.1.3 - version: 5.1.3(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.2.5) - eslint-plugin-vitest: - specifier: ^0.2.8 - version: 0.2.8(eslint@8.57.0)(typescript@5.4.5)(vitest@1.5.0(@types/node@20.12.7)) prettier: specifier: ^3.2.5 version: 3.2.5 @@ -244,10 +223,6 @@ importers: packages: - '@aashutoshrathi/word-wrap@1.2.6': - resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} - engines: {node: '>=0.10.0'} - '@algolia/autocomplete-core@1.9.3': resolution: {integrity: sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==} @@ -353,6 +328,59 @@ packages: resolution: {integrity: sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==} engines: {node: '>=6.9.0'} + '@biomejs/biome@1.7.1': + resolution: {integrity: sha512-wb2UNoFXcgaMdKXKT5ytsYntaogl2FSTjDt20CZynF3v7OXQUcIpTrr+be3XoOGpoZRj3Ytq9TSpmplUREXmeA==} + engines: {node: '>=14.21.3'} + hasBin: true + + '@biomejs/cli-darwin-arm64@1.7.1': + resolution: {integrity: sha512-qfLrIIB58dkgiY/1tgG6fSCBK22PZaSIf6blweZBsG6iMij05mEuJt50ne+zPnNFNUmt8t43NC/qOXT3iFHQBA==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [darwin] + + '@biomejs/cli-darwin-x64@1.7.1': + resolution: {integrity: sha512-OGeyNsEcp5VnKbF9/TBjPCTHNEOm7oHegEve07U3KZmzqfpw2Oe3i9DVW8t6vvj1TYbrwWYCld25H34kBDY7Vg==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [darwin] + + '@biomejs/cli-linux-arm64-musl@1.7.1': + resolution: {integrity: sha512-giH0/CzLOJ+wbxLxd5Shnr5xQf5fGnTRWLDe3lzjaF7IplVydNCEeZJtncB01SvyA6DAFJsvQ4LNxzAOQfEVCg==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [linux] + + '@biomejs/cli-linux-arm64@1.7.1': + resolution: {integrity: sha512-MQDf5wErj1iBvlcxCyOa0XqZYN8WJrupVgbNnqhntO3yVATg8GxduVUn1fDSaolznkDRsj7Pz3Xu1esBFwvfmg==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [linux] + + '@biomejs/cli-linux-x64-musl@1.7.1': + resolution: {integrity: sha512-ySNDtPhsLxU125IFHHAxfpoHBpkM56s4mEXeO70GZtgZay/o1h8IUPWCWf5Z7gKgc4jwgYN1U1U9xabI3hZVAg==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [linux] + + '@biomejs/cli-linux-x64@1.7.1': + resolution: {integrity: sha512-3wmCsGcC3KZ4pfTknXHfyMMlXPMhgfXVAcG5GlrR+Tq2JGiAw0EUydaLpsSBEbcG7IxH6OiUZEJZ95kAycCHBA==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [linux] + + '@biomejs/cli-win32-arm64@1.7.1': + resolution: {integrity: sha512-8hIDakEqZn0i6+388noYKdZ0ZrovTwnvMU/Qp/oJou0G7EPVdXupOe0oxiQSdRN0W7f6CS/yjPCYuVGzDG6r0g==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [win32] + + '@biomejs/cli-win32-x64@1.7.1': + resolution: {integrity: sha512-3W9k3uH6Ea6VOpAS9xkkAlS0LTfnGQjmIUCegZ8SDtK2NgJ1gO+qdEkGJb0ltahusFTN1QxJ107dM7ASA9IUEg==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [win32] + '@bundled-es-modules/cookie@2.0.0': resolution: {integrity: sha512-Or6YHg/kamKHpxULAdSqhGqnWFneIXu1NKvvfBBzKGwpVsYuFIQ5aBPHDnnoR3ghW1nvSkALd+EF9iMtY7Vjxw==} @@ -578,39 +606,10 @@ packages: cpu: [x64] os: [win32] - '@eslint-community/eslint-utils@4.4.0': - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - - '@eslint-community/regexpp@4.10.0': - resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - - '@eslint/eslintrc@2.1.4': - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - '@eslint/js@8.57.0': - resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@fastify/busboy@2.1.1': resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} engines: {node: '>=14'} - '@humanwhocodes/config-array@0.11.14': - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} - engines: {node: '>=10.10.0'} - - '@humanwhocodes/module-importer@1.0.1': - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - - '@humanwhocodes/object-schema@2.0.3': - resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} - '@inquirer/confirm@3.1.5': resolution: {integrity: sha512-6+dwZrpko5vr5EFEQmUbfBVhtu6IsnB8lQNsLHgO9S9fbfS5J6MuUj+NY0h98pPpYZXEazLR7qzypEDqVzf6aQ==} engines: {node: '>=18'} @@ -744,10 +743,6 @@ packages: '@open-draft/until@2.1.0': resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} - '@pkgr/core@0.1.1': - resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@polka/url@1.0.0-next.25': resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==} @@ -980,9 +975,6 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/json5@0.0.29': - resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - '@types/linkify-it@3.0.5': resolution: {integrity: sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw==} @@ -1034,94 +1026,6 @@ packages: '@types/wrap-ansi@3.0.0': resolution: {integrity: sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==} - '@typescript-eslint/eslint-plugin@7.7.1': - resolution: {integrity: sha512-KwfdWXJBOviaBVhxO3p5TJiLpNuh2iyXyjmWN0f1nU87pwyvfS0EmjC6ukQVYVFJd/K1+0NWGPDXiyEyQorn0Q==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - '@typescript-eslint/parser': ^7.0.0 - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/parser@7.7.1': - resolution: {integrity: sha512-vmPzBOOtz48F6JAGVS/kZYk4EkXao6iGrD838sp1w3NQQC0W8ry/q641KU4PrG7AKNAf56NOcR8GOpH8l9FPCw==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/scope-manager@6.21.0': - resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==} - engines: {node: ^16.0.0 || >=18.0.0} - - '@typescript-eslint/scope-manager@7.7.1': - resolution: {integrity: sha512-PytBif2SF+9SpEUKynYn5g1RHFddJUcyynGpztX3l/ik7KmZEv19WCMhUBkHXPU9es/VWGD3/zg3wg90+Dh2rA==} - engines: {node: ^18.18.0 || >=20.0.0} - - '@typescript-eslint/type-utils@7.7.1': - resolution: {integrity: sha512-ZksJLW3WF7o75zaBPScdW1Gbkwhd/lyeXGf1kQCxJaOeITscoSl0MjynVvCzuV5boUz/3fOI06Lz8La55mu29Q==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/types@6.21.0': - resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==} - engines: {node: ^16.0.0 || >=18.0.0} - - '@typescript-eslint/types@7.7.1': - resolution: {integrity: sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==} - engines: {node: ^18.18.0 || >=20.0.0} - - '@typescript-eslint/typescript-estree@6.21.0': - resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/typescript-estree@7.7.1': - resolution: {integrity: sha512-CXe0JHCXru8Fa36dteXqmH2YxngKJjkQLjxzoj6LYwzZ7qZvgsLSc+eqItCrqIop8Vl2UKoAi0StVWu97FQZIQ==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/utils@6.21.0': - resolution: {integrity: sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - - '@typescript-eslint/utils@7.7.1': - resolution: {integrity: sha512-QUvBxPEaBXf41ZBbaidKICgVL8Hin0p6prQDu6bbetWo39BKbWJxRsErOzMNT1rXvTll+J7ChrbmMCXM9rsvOQ==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - - '@typescript-eslint/visitor-keys@6.21.0': - resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==} - engines: {node: ^16.0.0 || >=18.0.0} - - '@typescript-eslint/visitor-keys@7.7.1': - resolution: {integrity: sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==} - engines: {node: ^18.18.0 || >=20.0.0} - - '@ungap/structured-clone@1.2.0': - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - '@vitejs/plugin-react-swc@3.6.0': resolution: {integrity: sha512-XFRbsGgpGxGzEV5i5+vRiro1bwcIaZDIdBRP16qwm+jP68ue/S8FJTBEgOeojtVDYrbSua3XFp71kC8VJE6v+g==} peerDependencies: @@ -1239,11 +1143,6 @@ packages: '@vueuse/shared@10.9.0': resolution: {integrity: sha512-Uud2IWncmAfJvRaFYzv5OHDli+FbOzxiVEQdLCKQKLyhz94PIyFC3CHcH7EDMwIn8NPtD06+PNbC/PiO0LGLtw==} - acorn-jsx@5.3.2: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn-walk@8.3.2: resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} engines: {node: '>=0.4.0'} @@ -1257,9 +1156,6 @@ packages: resolution: {integrity: sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==} engines: {node: '>=12'} - ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - algoliasearch@4.23.3: resolution: {integrity: sha512-Le/3YgNvjW9zxIQMRhUHuhiUjAlKY/zsdZpfq4dlLqg6mEm0nL6yk+7f2hDOtLpxsgE4jSzDmvHL7nXdBp5feg==} @@ -1304,26 +1200,14 @@ packages: resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} engines: {node: '>= 0.4'} - array-includes@3.1.8: - resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} - engines: {node: '>= 0.4'} - array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} - array.prototype.findlastindex@1.2.5: - resolution: {integrity: sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==} - engines: {node: '>= 0.4'} - array.prototype.flat@1.3.2: resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} engines: {node: '>= 0.4'} - array.prototype.flatmap@1.3.2: - resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} - engines: {node: '>= 0.4'} - arraybuffer.prototype.slice@1.0.3: resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} engines: {node: '>= 0.4'} @@ -1554,14 +1438,6 @@ packages: dataloader@1.4.0: resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==} - debug@3.2.7: - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - debug@4.3.4: resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} @@ -1587,9 +1463,6 @@ packages: resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} engines: {node: '>=6'} - deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - deepmerge@4.3.1: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} @@ -1645,14 +1518,6 @@ packages: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} - doctrine@2.1.0: - resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} - engines: {node: '>=0.10.0'} - - doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - dotenv@8.6.0: resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==} engines: {node: '>=10'} @@ -1714,130 +1579,24 @@ packages: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} - escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - escape-string-regexp@5.0.0: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} engines: {node: '>=12'} - eslint-config-prettier@9.1.0: - resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - - eslint-import-resolver-node@0.3.9: - resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} - - eslint-module-utils@2.8.1: - resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - - eslint-plugin-import@2.29.1: - resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - - eslint-plugin-no-only-tests@3.1.0: - resolution: {integrity: sha512-Lf4YW/bL6Un1R6A76pRZyE1dl1vr31G/ev8UzIc/geCgFWyrKil8hVjYqWVKGB/UIGmb6Slzs9T0wNezdSVegw==} - engines: {node: '>=5.0.0'} - - eslint-plugin-prettier@5.1.3: - resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - '@types/eslint': '>=8.0.0' - eslint: '>=8.0.0' - eslint-config-prettier: '*' - prettier: '>=3.0.0' - peerDependenciesMeta: - '@types/eslint': - optional: true - eslint-config-prettier: - optional: true - - eslint-plugin-vitest@0.2.8: - resolution: {integrity: sha512-q8s4tStyKtn3gXf+8nf1ZYTHhoCXKdnozZzp6u8b4ni5v68Y4vxhNh4Z8njUfNjEY8HoPBB77MazHMR23IPb+g==} - engines: {node: 14.x || >= 16} - peerDependencies: - eslint: '>=8.0.0' - vite: '*' - vitest: '*' - peerDependenciesMeta: - vite: - optional: true - - eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - hasBin: true - esm-env@1.0.0: resolution: {integrity: sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==} - espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - esprima@4.0.1: resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} engines: {node: '>=4'} hasBin: true - esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} - engines: {node: '>=0.10'} - - esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - - estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} - esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - execa@7.2.0: resolution: {integrity: sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==} engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0} @@ -1856,9 +1615,6 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-diff@1.3.0: - resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} - fast-glob@3.3.1: resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} engines: {node: '>=8.6.0'} @@ -1867,22 +1623,12 @@ packages: resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} engines: {node: '>=8.6.0'} - fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - - fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - fast-safe-stringify@2.1.1: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} fastq@1.15.0: resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} - file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} - fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} @@ -1898,13 +1644,6 @@ packages: find-yarn-workspace-root2@1.2.16: resolution: {integrity: sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==} - flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} - - flatted@3.3.1: - resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} - focus-trap@7.5.4: resolution: {integrity: sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==} @@ -1987,17 +1726,9 @@ packages: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} - glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - globals@13.24.0: - resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} - engines: {node: '>=8'} - globalthis@1.0.3: resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} engines: {node: '>= 0.4'} @@ -2025,9 +1756,6 @@ packages: grapheme-splitter@1.0.4: resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} - graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - graphql@16.8.1: resolution: {integrity: sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==} engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} @@ -2130,10 +1858,6 @@ packages: import-meta-resolve@4.0.0: resolution: {integrity: sha512-okYUR7ZQPH+efeuMJGlq4f8ubUgO50kByRPyt/Cy1Io4PSRsPjxME+YlVaCOx+NIToW7hCsZNFJyTPFFKepRSA==} - imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - indent-string@4.0.0: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} engines: {node: '>=8'} @@ -2219,10 +1943,6 @@ packages: resolution: {integrity: sha512-kyiNFFLU0Ampr6SDZitD/DwUo4Zs1nSdnygUBqsu3LooL00Qvb5j+UnvApUn/TTj1J3OuE6BTdQ5rudKmU2ZaA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - is-path-inside@4.0.0: resolution: {integrity: sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==} engines: {node: '>=12'} @@ -2293,9 +2013,6 @@ packages: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true - json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} @@ -2304,19 +2021,9 @@ packages: engines: {node: '>=10'} deprecated: Please switch to @apidevtools/json-schema-ref-parser - json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - - json5@1.0.2: - resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} - hasBin: true - jsonc-parser@3.2.1: resolution: {integrity: sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==} @@ -2326,9 +2033,6 @@ packages: jsonfile@6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} - keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - kind-of@6.0.3: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} @@ -2337,10 +2041,6 @@ packages: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} - levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} @@ -2366,9 +2066,6 @@ packages: lodash.isequal@4.5.0: resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} - lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - lodash.startcase@4.4.0: resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} @@ -2454,14 +2151,6 @@ packages: resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} engines: {node: '>=10'} - minimatch@9.0.3: - resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} - engines: {node: '>=16 || 14 >=14.17'} - - minimatch@9.0.4: - resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} - engines: {node: '>=16 || 14 >=14.17'} - minimist-options@4.1.0: resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} engines: {node: '>= 6'} @@ -2497,9 +2186,6 @@ packages: ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - msw@2.2.14: resolution: {integrity: sha512-64i8rNCa1xzDK8ZYsTrVMli05D687jty8+Th+PU5VTbJ2/4P7fkQFVyDQ6ZFT5FrNR8z2BHhbY47fKNvfHrumA==} engines: {node: '>=18'} @@ -2519,9 +2205,6 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} @@ -2578,18 +2261,6 @@ packages: resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} engines: {node: '>= 0.4'} - object.fromentries@2.0.8: - resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} - engines: {node: '>= 0.4'} - - object.groupby@1.0.3: - resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} - engines: {node: '>= 0.4'} - - object.values@1.2.0: - resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} - engines: {node: '>= 0.4'} - once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -2612,10 +2283,6 @@ packages: resolution: {integrity: sha512-ZD6dgSZi0u1QCP55g8/2yS5hNJfIpgqsSGHLxxdOjvY7eIrXzj271FJEQw33VwsZ6RCtO/NOuhxa7GBWmEudyA==} hasBin: true - optionator@0.9.3: - resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} - engines: {node: '>= 0.8.0'} - os-tmpdir@1.0.2: resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} engines: {node: '>=0.10.0'} @@ -2749,14 +2416,6 @@ packages: resolution: {integrity: sha512-MkXsENfftWSRpzCzImcp4FRsCc3y1opwB73CfCNWyzMqArju2CrlMHlqB7VexKiPEOjGMbttv1r9fSCn5S610w==} engines: {node: '>=10'} - prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - - prettier-linter-helpers@1.0.0: - resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} - engines: {node: '>=6.0.0'} - prettier@2.8.8: resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} engines: {node: '>=10.13.0'} @@ -2921,10 +2580,6 @@ packages: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - semver@7.5.4: resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} engines: {node: '>=10'} @@ -3088,10 +2743,6 @@ packages: resolution: {integrity: sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==} engines: {node: '>=12'} - strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - strip-literal@2.1.0: resolution: {integrity: sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==} @@ -3181,10 +2832,6 @@ packages: resolution: {integrity: sha512-j9KJSccHgLeRERPlhMKrCXpk2TqL2m5Z+k+OBTQhZOhIdCCd3WfqV+ylPWeipEwq17P/ekiSFWwrVQv93i3bsg==} engines: {node: '>=16'} - synckit@0.8.8: - resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==} - engines: {node: ^14.18.0 || >=16.0.0} - tabbable@6.2.0: resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} @@ -3192,9 +2839,6 @@ packages: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} engines: {node: '>=8'} - text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - tiny-glob@0.2.9: resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==} @@ -3236,15 +2880,6 @@ packages: resolution: {integrity: sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==} engines: {node: '>=12'} - ts-api-utils@1.3.0: - resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} - engines: {node: '>=16'} - peerDependencies: - typescript: '>=4.2.0' - - tsconfig-paths@3.15.0: - resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} - tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} @@ -3253,10 +2888,6 @@ packages: engines: {node: '>=8.0.0'} hasBin: true - type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - type-detect@4.0.8: resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} engines: {node: '>=4'} @@ -3265,10 +2896,6 @@ packages: resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} engines: {node: '>=10'} - type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - type-fest@0.21.3: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} @@ -3536,8 +3163,6 @@ packages: snapshots: - '@aashutoshrathi/word-wrap@1.2.6': {} - '@algolia/autocomplete-core@1.9.3(@algolia/client-search@4.23.3)(algoliasearch@4.23.3)(search-insights@2.13.0)': dependencies: '@algolia/autocomplete-plugin-algolia-insights': 1.9.3(@algolia/client-search@4.23.3)(algoliasearch@4.23.3)(search-insights@2.13.0) @@ -3685,6 +3310,41 @@ snapshots: '@babel/helper-validator-identifier': 7.22.20 to-fast-properties: 2.0.0 + '@biomejs/biome@1.7.1': + optionalDependencies: + '@biomejs/cli-darwin-arm64': 1.7.1 + '@biomejs/cli-darwin-x64': 1.7.1 + '@biomejs/cli-linux-arm64': 1.7.1 + '@biomejs/cli-linux-arm64-musl': 1.7.1 + '@biomejs/cli-linux-x64': 1.7.1 + '@biomejs/cli-linux-x64-musl': 1.7.1 + '@biomejs/cli-win32-arm64': 1.7.1 + '@biomejs/cli-win32-x64': 1.7.1 + + '@biomejs/cli-darwin-arm64@1.7.1': + optional: true + + '@biomejs/cli-darwin-x64@1.7.1': + optional: true + + '@biomejs/cli-linux-arm64-musl@1.7.1': + optional: true + + '@biomejs/cli-linux-arm64@1.7.1': + optional: true + + '@biomejs/cli-linux-x64-musl@1.7.1': + optional: true + + '@biomejs/cli-linux-x64@1.7.1': + optional: true + + '@biomejs/cli-win32-arm64@1.7.1': + optional: true + + '@biomejs/cli-win32-x64@1.7.1': + optional: true + '@bundled-es-modules/cookie@2.0.0': dependencies: cookie: 0.5.0 @@ -3952,43 +3612,8 @@ snapshots: '@esbuild/win32-x64@0.20.2': optional: true - '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': - dependencies: - eslint: 8.57.0 - eslint-visitor-keys: 3.4.3 - - '@eslint-community/regexpp@4.10.0': {} - - '@eslint/eslintrc@2.1.4': - dependencies: - ajv: 6.12.6 - debug: 4.3.4(supports-color@9.4.0) - espree: 9.6.1 - globals: 13.24.0 - ignore: 5.3.1 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - - '@eslint/js@8.57.0': {} - '@fastify/busboy@2.1.1': {} - '@humanwhocodes/config-array@0.11.14': - dependencies: - '@humanwhocodes/object-schema': 2.0.3 - debug: 4.3.4(supports-color@9.4.0) - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - - '@humanwhocodes/module-importer@1.0.1': {} - - '@humanwhocodes/object-schema@2.0.3': {} - '@inquirer/confirm@3.1.5': dependencies: '@inquirer/core': 8.0.1 @@ -4114,8 +3739,6 @@ snapshots: '@open-draft/until@2.1.0': {} - '@pkgr/core@0.1.1': {} - '@polka/url@1.0.0-next.25': {} '@redocly/ajv@8.11.0': @@ -4319,8 +3942,6 @@ snapshots: '@types/json-schema@7.0.15': {} - '@types/json5@0.0.29': {} - '@types/linkify-it@3.0.5': {} '@types/markdown-it@14.0.1': @@ -4367,135 +3988,6 @@ snapshots: '@types/wrap-ansi@3.0.0': {} - '@typescript-eslint/eslint-plugin@7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)': - dependencies: - '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.7.1(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/scope-manager': 7.7.1 - '@typescript-eslint/type-utils': 7.7.1(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.7.1(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.7.1 - debug: 4.3.4(supports-color@9.4.0) - eslint: 8.57.0 - graphemer: 1.4.0 - ignore: 5.3.1 - natural-compare: 1.4.0 - semver: 7.6.0 - ts-api-utils: 1.3.0(typescript@5.4.5) - optionalDependencies: - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5)': - dependencies: - '@typescript-eslint/scope-manager': 7.7.1 - '@typescript-eslint/types': 7.7.1 - '@typescript-eslint/typescript-estree': 7.7.1(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.7.1 - debug: 4.3.4(supports-color@9.4.0) - eslint: 8.57.0 - optionalDependencies: - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/scope-manager@6.21.0': - dependencies: - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/visitor-keys': 6.21.0 - - '@typescript-eslint/scope-manager@7.7.1': - dependencies: - '@typescript-eslint/types': 7.7.1 - '@typescript-eslint/visitor-keys': 7.7.1 - - '@typescript-eslint/type-utils@7.7.1(eslint@8.57.0)(typescript@5.4.5)': - dependencies: - '@typescript-eslint/typescript-estree': 7.7.1(typescript@5.4.5) - '@typescript-eslint/utils': 7.7.1(eslint@8.57.0)(typescript@5.4.5) - debug: 4.3.4(supports-color@9.4.0) - eslint: 8.57.0 - ts-api-utils: 1.3.0(typescript@5.4.5) - optionalDependencies: - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/types@6.21.0': {} - - '@typescript-eslint/types@7.7.1': {} - - '@typescript-eslint/typescript-estree@6.21.0(typescript@5.4.5)': - dependencies: - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.4(supports-color@9.4.0) - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.3 - semver: 7.6.0 - ts-api-utils: 1.3.0(typescript@5.4.5) - optionalDependencies: - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/typescript-estree@7.7.1(typescript@5.4.5)': - dependencies: - '@typescript-eslint/types': 7.7.1 - '@typescript-eslint/visitor-keys': 7.7.1 - debug: 4.3.4(supports-color@9.4.0) - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.4 - semver: 7.6.0 - ts-api-utils: 1.3.0(typescript@5.4.5) - optionalDependencies: - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/utils@6.21.0(eslint@8.57.0)(typescript@5.4.5)': - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.8 - '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/types': 6.21.0 - '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.4.5) - eslint: 8.57.0 - semver: 7.6.0 - transitivePeerDependencies: - - supports-color - - typescript - - '@typescript-eslint/utils@7.7.1(eslint@8.57.0)(typescript@5.4.5)': - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.8 - '@typescript-eslint/scope-manager': 7.7.1 - '@typescript-eslint/types': 7.7.1 - '@typescript-eslint/typescript-estree': 7.7.1(typescript@5.4.5) - eslint: 8.57.0 - semver: 7.6.0 - transitivePeerDependencies: - - supports-color - - typescript - - '@typescript-eslint/visitor-keys@6.21.0': - dependencies: - '@typescript-eslint/types': 6.21.0 - eslint-visitor-keys: 3.4.3 - - '@typescript-eslint/visitor-keys@7.7.1': - dependencies: - '@typescript-eslint/types': 7.7.1 - eslint-visitor-keys: 3.4.3 - - '@ungap/structured-clone@1.2.0': {} - '@vitejs/plugin-react-swc@3.6.0(@swc/helpers@0.5.5)(vite@5.2.10(@types/node@20.12.7))': dependencies: '@swc/core': 1.4.17(@swc/helpers@0.5.5) @@ -4640,10 +4132,6 @@ snapshots: - '@vue/composition-api' - vue - acorn-jsx@5.3.2(acorn@8.11.3): - dependencies: - acorn: 8.11.3 - acorn-walk@8.3.2: {} acorn@8.11.3: {} @@ -4653,13 +4141,6 @@ snapshots: clean-stack: 4.2.0 indent-string: 5.0.0 - ajv@6.12.6: - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - algoliasearch@4.23.3: dependencies: '@algolia/cache-browser-local-storage': 4.23.3 @@ -4716,26 +4197,8 @@ snapshots: call-bind: 1.0.7 is-array-buffer: 3.0.4 - array-includes@3.1.8: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - get-intrinsic: 1.2.4 - is-string: 1.0.7 - array-union@2.1.0: {} - array.prototype.findlastindex@1.2.5: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-object-atoms: 1.0.0 - es-shim-unscopables: 1.0.2 - array.prototype.flat@1.3.2: dependencies: call-bind: 1.0.7 @@ -4743,13 +4206,6 @@ snapshots: es-abstract: 1.23.3 es-shim-unscopables: 1.0.2 - array.prototype.flatmap@1.3.2: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-shim-unscopables: 1.0.2 - arraybuffer.prototype.slice@1.0.3: dependencies: array-buffer-byte-length: 1.0.1 @@ -5004,10 +4460,6 @@ snapshots: dataloader@1.4.0: {} - debug@3.2.7: - dependencies: - ms: 2.1.3 - debug@4.3.4(supports-color@9.4.0): dependencies: ms: 2.1.2 @@ -5027,8 +4479,6 @@ snapshots: dependencies: type-detect: 4.0.8 - deep-is@0.1.4: {} - deepmerge@4.3.1: {} defaults@1.0.4: @@ -5084,14 +4534,6 @@ snapshots: dependencies: path-type: 4.0.0 - doctrine@2.1.0: - dependencies: - esutils: 2.0.3 - - doctrine@3.0.0: - dependencies: - esutils: 2.0.3 - dotenv@8.6.0: {} emoji-regex@8.0.0: {} @@ -5214,157 +4656,18 @@ snapshots: escape-string-regexp@1.0.5: {} - escape-string-regexp@4.0.0: {} - escape-string-regexp@5.0.0: {} - eslint-config-prettier@9.1.0(eslint@8.57.0): - dependencies: - eslint: 8.57.0 - - eslint-import-resolver-node@0.3.9: - dependencies: - debug: 3.2.7 - is-core-module: 2.13.1 - resolve: 1.22.8 - transitivePeerDependencies: - - supports-color - - eslint-module-utils@2.8.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0): - dependencies: - debug: 3.2.7 - optionalDependencies: - '@typescript-eslint/parser': 7.7.1(eslint@8.57.0)(typescript@5.4.5) - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - transitivePeerDependencies: - - supports-color - - eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0): - dependencies: - array-includes: 3.1.8 - array.prototype.findlastindex: 1.2.5 - array.prototype.flat: 1.3.2 - array.prototype.flatmap: 1.3.2 - debug: 3.2.7 - doctrine: 2.1.0 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0) - hasown: 2.0.2 - is-core-module: 2.13.1 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.fromentries: 2.0.8 - object.groupby: 1.0.3 - object.values: 1.2.0 - semver: 6.3.1 - tsconfig-paths: 3.15.0 - optionalDependencies: - '@typescript-eslint/parser': 7.7.1(eslint@8.57.0)(typescript@5.4.5) - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - - eslint-plugin-no-only-tests@3.1.0: {} - - eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.2.5): - dependencies: - eslint: 8.57.0 - prettier: 3.2.5 - prettier-linter-helpers: 1.0.0 - synckit: 0.8.8 - optionalDependencies: - eslint-config-prettier: 9.1.0(eslint@8.57.0) - - eslint-plugin-vitest@0.2.8(eslint@8.57.0)(typescript@5.4.5)(vitest@1.5.0(@types/node@20.12.7)): - dependencies: - '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.4.5) - eslint: 8.57.0 - vitest: 1.5.0(@types/node@20.12.7)(supports-color@9.4.0) - transitivePeerDependencies: - - supports-color - - typescript - - eslint-scope@7.2.2: - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - - eslint-visitor-keys@3.4.3: {} - - eslint@8.57.0: - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@eslint-community/regexpp': 4.10.0 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.0 - '@humanwhocodes/config-array': 0.11.14 - '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.2.0 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.4(supports-color@9.4.0) - doctrine: 3.0.0 - escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.5.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - find-up: 5.0.0 - glob-parent: 6.0.2 - globals: 13.24.0 - graphemer: 1.4.0 - ignore: 5.3.1 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-yaml: 4.1.0 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.3 - strip-ansi: 6.0.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - esm-env@1.0.0: {} - espree@9.6.1: - dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) - eslint-visitor-keys: 3.4.3 - esprima@4.0.1: {} - esquery@1.5.0: - dependencies: - estraverse: 5.3.0 - - esrecurse@4.3.0: - dependencies: - estraverse: 5.3.0 - - estraverse@5.3.0: {} - estree-walker@2.0.2: {} estree-walker@3.0.3: dependencies: '@types/estree': 1.0.5 - esutils@2.0.3: {} - execa@7.2.0: dependencies: cross-spawn: 7.0.3 @@ -5399,8 +4702,6 @@ snapshots: fast-deep-equal@3.1.3: {} - fast-diff@1.3.0: {} - fast-glob@3.3.1: dependencies: '@nodelib/fs.stat': 2.0.5 @@ -5417,20 +4718,12 @@ snapshots: merge2: 1.4.1 micromatch: 4.0.5 - fast-json-stable-stringify@2.1.0: {} - - fast-levenshtein@2.0.6: {} - fast-safe-stringify@2.1.1: {} fastq@1.15.0: dependencies: reusify: 1.0.4 - file-entry-cache@6.0.1: - dependencies: - flat-cache: 3.2.0 - fill-range@7.0.1: dependencies: to-regex-range: 5.0.1 @@ -5450,14 +4743,6 @@ snapshots: micromatch: 4.0.5 pkg-dir: 4.2.0 - flat-cache@3.2.0: - dependencies: - flatted: 3.3.1 - keyv: 4.5.4 - rimraf: 3.0.2 - - flatted@3.3.1: {} - focus-trap@7.5.4: dependencies: tabbable: 6.2.0 @@ -5542,10 +4827,6 @@ snapshots: dependencies: is-glob: 4.0.3 - glob-parent@6.0.2: - dependencies: - is-glob: 4.0.3 - glob@7.2.3: dependencies: fs.realpath: 1.0.0 @@ -5555,10 +4836,6 @@ snapshots: once: 1.4.0 path-is-absolute: 1.0.1 - globals@13.24.0: - dependencies: - type-fest: 0.20.2 - globalthis@1.0.3: dependencies: define-properties: 1.2.1 @@ -5592,8 +4869,6 @@ snapshots: grapheme-splitter@1.0.4: {} - graphemer@1.4.0: {} - graphql@16.8.1: {} handlebars@4.7.8: @@ -5672,8 +4947,6 @@ snapshots: import-meta-resolve@4.0.0: {} - imurmurhash@0.1.4: {} - indent-string@4.0.0: {} indent-string@5.0.0: {} @@ -5749,8 +5022,6 @@ snapshots: is-path-cwd@3.0.0: {} - is-path-inside@3.0.3: {} - is-path-inside@4.0.0: {} is-plain-obj@1.1.0: {} @@ -5811,24 +5082,14 @@ snapshots: dependencies: argparse: 2.0.1 - json-buffer@3.0.1: {} - json-parse-even-better-errors@2.3.1: {} json-schema-ref-parser@9.0.9: dependencies: '@apidevtools/json-schema-ref-parser': 9.0.9 - json-schema-traverse@0.4.1: {} - json-schema-traverse@1.0.0: {} - json-stable-stringify-without-jsonify@1.0.1: {} - - json5@1.0.2: - dependencies: - minimist: 1.2.8 - jsonc-parser@3.2.1: {} jsonfile@4.0.0: @@ -5841,19 +5102,10 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 - keyv@4.5.4: - dependencies: - json-buffer: 3.0.1 - kind-of@6.0.3: {} kleur@4.1.5: {} - levn@0.4.1: - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - lines-and-columns@1.2.4: {} load-yaml-file@0.2.0: @@ -5880,8 +5132,6 @@ snapshots: lodash.isequal@4.5.0: {} - lodash.merge@4.6.2: {} - lodash.startcase@4.4.0: {} loose-envify@1.4.0: @@ -5973,14 +5223,6 @@ snapshots: dependencies: brace-expansion: 2.0.1 - minimatch@9.0.3: - dependencies: - brace-expansion: 2.0.1 - - minimatch@9.0.4: - dependencies: - brace-expansion: 2.0.1 - minimist-options@4.1.0: dependencies: arrify: 1.0.1 @@ -6012,8 +5254,6 @@ snapshots: ms@2.1.2: {} - ms@2.1.3: {} - msw@2.2.14(typescript@5.4.5): dependencies: '@bundled-es-modules/cookie': 2.0.0 @@ -6040,8 +5280,6 @@ snapshots: nanoid@3.3.7: {} - natural-compare@1.4.0: {} - neo-async@2.6.2: {} next@14.2.2(react-dom@18.2.0(react@18.2.0))(react@18.2.0): @@ -6104,25 +5342,6 @@ snapshots: has-symbols: 1.0.3 object-keys: 1.1.1 - object.fromentries@2.0.8: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - - object.groupby@1.0.3: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - - object.values@1.2.0: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - once@1.4.0: dependencies: wrappy: 1.0.2 @@ -6152,15 +5371,6 @@ snapshots: undici: 5.28.4 yargs-parser: 21.1.1 - optionator@0.9.3: - dependencies: - '@aashutoshrathi/word-wrap': 1.2.6 - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - os-tmpdir@1.0.2: {} outdent@0.5.0: {} @@ -6277,12 +5487,6 @@ snapshots: path-exists: 4.0.0 which-pm: 2.0.0 - prelude-ls@1.2.1: {} - - prettier-linter-helpers@1.0.0: - dependencies: - fast-diff: 1.3.0 - prettier@2.8.8: {} prettier@3.2.5: {} @@ -6465,8 +5669,6 @@ snapshots: semver@5.7.2: {} - semver@6.3.1: {} - semver@7.5.4: dependencies: lru-cache: 6.0.0 @@ -6632,8 +5834,6 @@ snapshots: dependencies: min-indent: 1.0.1 - strip-json-comments@3.1.1: {} - strip-literal@2.1.0: dependencies: js-tokens: 9.0.0 @@ -6725,17 +5925,10 @@ snapshots: magic-string: 0.30.10 periscopic: 3.1.0 - synckit@0.8.8: - dependencies: - '@pkgr/core': 0.1.1 - tslib: 2.6.2 - tabbable@6.2.0: {} term-size@2.2.1: {} - text-table@0.2.0: {} - tiny-glob@0.2.9: dependencies: globalyzer: 0.1.0 @@ -6765,17 +5958,6 @@ snapshots: trim-newlines@4.1.1: {} - ts-api-utils@1.3.0(typescript@5.4.5): - dependencies: - typescript: 5.4.5 - - tsconfig-paths@3.15.0: - dependencies: - '@types/json5': 0.0.29 - json5: 1.0.2 - minimist: 1.2.8 - strip-bom: 3.0.0 - tslib@2.6.2: {} tty-table@4.2.3: @@ -6788,16 +5970,10 @@ snapshots: wcwidth: 1.0.1 yargs: 17.7.2 - type-check@0.4.0: - dependencies: - prelude-ls: 1.2.1 - type-detect@4.0.8: {} type-fest@0.13.1: {} - type-fest@0.20.2: {} - type-fest@0.21.3: {} type-fest@0.6.0: {}