From 290a524bcca87b995de1d9c71988f10851cfe7b8 Mon Sep 17 00:00:00 2001 From: Jason Kuhrt Date: Wed, 11 Dec 2024 12:02:58 -0500 Subject: [PATCH 01/10] refactor: use stricter typescript --- package.json | 3 ++ .../__integration-tests__/apollo-link.spec.ts | 2 +- packages/graphiql/src/YogaGraphiQL.tsx | 2 +- packages/graphiql/vite.config.ts | 2 +- .../__integration-tests__/browser.spec.ts | 2 +- .../__integration-tests__/node-http.spec.ts | 2 +- .../graphql-yoga/__tests__/batching.spec.ts | 4 +-- .../__tests__/error-masking.spec.ts | 6 ++-- .../__tests__/http-extensions.spec.ts | 2 +- .../graphql-yoga/__tests__/logging.spec.ts | 6 ++-- .../graphql-yoga/__tests__/recipes.spec.ts | 2 +- .../__tests__/request-cancellation.spec.ts | 2 +- .../graphql-yoga/__tests__/requests.spec.ts | 8 ++--- .../scripts/generate-graphiql-html.js | 26 +++++++++++----- packages/graphql-yoga/src/error.ts | 2 +- .../src/plugins/request-parser/post-json.ts | 2 +- .../plugins/request-parser/post-multipart.ts | 2 +- .../use-check-graphql-query-params.ts | 8 ++--- .../src/plugins/result-processor/accept.ts | 2 ++ .../src/plugins/result-processor/regular.ts | 3 +- .../src/plugins/result-processor/sse.ts | 2 +- packages/graphql-yoga/src/server.ts | 2 +- packages/graphql-yoga/src/utils/mask-error.ts | 4 +-- packages/nestjs-federation/src/index.ts | 18 ++++++----- packages/nestjs/src/index.ts | 9 +++--- .../__tests__/apollo-inline-trace.spec.ts | 18 +++++------ .../apollo-inline-trace.yoga-gateway.spec.ts | 30 +++++++++---------- .../plugins/apollo-inline-trace/src/index.ts | 2 +- .../plugins/apollo-usage-report/src/index.ts | 8 ++--- packages/plugins/apq/src/index.ts | 2 +- .../__tests__/validations/harness.ts | 8 ++--- .../overlapping-fields-can-be-merged.ts | 10 +++---- packages/plugins/graphql-sse/src/index.ts | 2 +- .../plugins/jwt/src/__tests__/jwt.spec.ts | 20 ++++++------- packages/plugins/jwt/src/utils.ts | 14 ++++----- .../plugins/persisted-operations/src/index.ts | 10 +++---- .../__tests__/response-cache.spec.ts | 2 +- pnpm-lock.yaml | 16 ++++++++++ tsconfig.json | 14 +++++---- 39 files changed, 157 insertions(+), 122 deletions(-) diff --git a/package.json b/package.json index dfecafc35b..b83739fb77 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "build-website": "pnpm build && cd website && pnpm build", "changeset": "changeset", "check": "pnpm -r run check", + "check:types": "tsc --pretty --noEmit", "lint": "cross-env \"ESLINT_USE_FLAT_CONFIG=false\" eslint --ext ts,js,tsx,jsx .", "postchangeset": "pnpm install --no-frozen-lockfile", "postinstall": "husky install", @@ -58,8 +59,10 @@ "@changesets/cli": "2.27.10", "@theguild/eslint-config": "0.13.2", "@theguild/prettier-config": "3.0.0", + "@tsconfig/strictest": "^2.0.5", "@types/babel__core": "7.20.5", "@types/babel__preset-env": "7.9.7", + "@types/html-minifier-terser": "^7.0.2", "@types/jest": "29.5.14", "@types/supertest": "6.0.2", "@typescript-eslint/eslint-plugin": "^8.18.0", diff --git a/packages/client/apollo-link/__integration-tests__/apollo-link.spec.ts b/packages/client/apollo-link/__integration-tests__/apollo-link.spec.ts index 3c6fadd36a..7410cf71af 100644 --- a/packages/client/apollo-link/__integration-tests__/apollo-link.spec.ts +++ b/packages/client/apollo-link/__integration-tests__/apollo-link.spec.ts @@ -95,7 +95,7 @@ describe('Yoga Apollo Link', () => { let i = 0; await new Promise(resolve => { const subscription = observable.subscribe((result: FetchResult) => { - collectedValues.push(result.data?.time); + collectedValues.push(result.data?.['time']); i++; if (i > 2) { subscription.unsubscribe(); diff --git a/packages/graphiql/src/YogaGraphiQL.tsx b/packages/graphiql/src/YogaGraphiQL.tsx index 7dd26aa2a6..aac9491176 100644 --- a/packages/graphiql/src/YogaGraphiQL.tsx +++ b/packages/graphiql/src/YogaGraphiQL.tsx @@ -133,7 +133,7 @@ export function YogaGraphiQL(props: YogaGraphiQLProps): React.ReactElement { false, ); - const [query, setQuery] = useState(params.query?.toString()); + const [query, setQuery] = useState(params['query']?.toString()); const explorer = explorerPlugin({ showAttribution: true, }); diff --git a/packages/graphiql/vite.config.ts b/packages/graphiql/vite.config.ts index 0cdc55592e..2734df141b 100644 --- a/packages/graphiql/vite.config.ts +++ b/packages/graphiql/vite.config.ts @@ -21,7 +21,7 @@ export default defineConfig({ }, define: // Having this environment variable set in development will break the dev server - process.env.BUILD === 'true' + process.env['BUILD'] === 'true' ? { 'process.env.NODE_ENV': '"production"', } diff --git a/packages/graphql-yoga/__integration-tests__/browser.spec.ts b/packages/graphql-yoga/__integration-tests__/browser.spec.ts index 60bd2abdf1..308d4e4d57 100644 --- a/packages/graphql-yoga/__integration-tests__/browser.spec.ts +++ b/packages/graphql-yoga/__integration-tests__/browser.spec.ts @@ -231,7 +231,7 @@ describe('browser', () => { await new Promise(resolve => server.listen(0, resolve)); port = (server.address() as AddressInfo).port; browser = await chromium.launch({ - headless: process.env.PLAYWRIGHT_HEADLESS !== 'false', + headless: process.env['PLAYWRIGHT_HEADLESS'] !== 'false', args: ['--incognito', '--no-sandbox', '--disable-setuid-sandbox'], }); }); diff --git a/packages/graphql-yoga/__integration-tests__/node-http.spec.ts b/packages/graphql-yoga/__integration-tests__/node-http.spec.ts index d1807899a4..8c14576157 100644 --- a/packages/graphql-yoga/__integration-tests__/node-http.spec.ts +++ b/packages/graphql-yoga/__integration-tests__/node-http.spec.ts @@ -267,7 +267,7 @@ describe('node-http', () => { expect(body).toHaveLength(3); for (const result of body) { expect(result.errors).toBeUndefined(); - expect(result.data?.isNode).toBe(true); + expect(result.data?.['isNode']).toBe(true); } } finally { await new Promise(resolve => server.close(() => resolve())); diff --git a/packages/graphql-yoga/__tests__/batching.spec.ts b/packages/graphql-yoga/__tests__/batching.spec.ts index de2bfaaf27..b6c36f851f 100644 --- a/packages/graphql-yoga/__tests__/batching.spec.ts +++ b/packages/graphql-yoga/__tests__/batching.spec.ts @@ -331,7 +331,7 @@ describe('Batching', () => { expect(contexts.length).toEqual(2); expect(contexts[0]).not.toBe(contexts[1]); - expect(contexts[0].i).toEqual(1); - expect(contexts[1].i).toEqual(2); + expect(contexts[0]!.i).toEqual(1); + expect(contexts[1]!.i).toEqual(2); }); }); diff --git a/packages/graphql-yoga/__tests__/error-masking.spec.ts b/packages/graphql-yoga/__tests__/error-masking.spec.ts index 1352343036..d4064e17b5 100644 --- a/packages/graphql-yoga/__tests__/error-masking.spec.ts +++ b/packages/graphql-yoga/__tests__/error-masking.spec.ts @@ -111,10 +111,10 @@ describe('error masking', () => { }); it('includes the original error in the extensions in dev mode (process.env.NODE_ENV=development)', async () => { - const initialEnv = process.env.NODE_ENV; + const initialEnv = process.env['NODE_ENV']; try { - process.env.NODE_ENV = 'development'; + process.env['NODE_ENV'] = 'development'; const yoga = createYoga({ schema: createTestSchema(), @@ -137,7 +137,7 @@ describe('error masking', () => { 'Error: This error will get mask if you enable maskedError.', ); } finally { - process.env.NODE_ENV = initialEnv; + process.env['NODE_ENV'] = initialEnv; } }); diff --git a/packages/graphql-yoga/__tests__/http-extensions.spec.ts b/packages/graphql-yoga/__tests__/http-extensions.spec.ts index f9c5e72dd5..3129096aa7 100644 --- a/packages/graphql-yoga/__tests__/http-extensions.spec.ts +++ b/packages/graphql-yoga/__tests__/http-extensions.spec.ts @@ -631,7 +631,7 @@ describe('Result Extensions', () => { this.name = 'CustomError'; } - toJSON() { + override toJSON() { return { message: this.message, extensions: { name: this.name, foo: 'bar' }, diff --git a/packages/graphql-yoga/__tests__/logging.spec.ts b/packages/graphql-yoga/__tests__/logging.spec.ts index e9ce9ce79f..f8ef5d6039 100644 --- a/packages/graphql-yoga/__tests__/logging.spec.ts +++ b/packages/graphql-yoga/__tests__/logging.spec.ts @@ -28,9 +28,9 @@ describe('logging', () => { expect(console.debug).not.toHaveBeenCalled(); }); it(`prints debug messages if DEBUG env var is set`, () => { - const originalValue = process.env.DEBUG; + const originalValue = process.env['DEBUG']; try { - process.env.DEBUG = '1'; + process.env['DEBUG'] = '1'; jest.spyOn(console, 'debug').mockImplementationOnce(() => {}); const logger = createLogger(); @@ -38,7 +38,7 @@ describe('logging', () => { expect(console.debug).toHaveBeenCalled(); } finally { - process.env.DEBUG = originalValue; + process.env['DEBUG'] = originalValue; } }); }); diff --git a/packages/graphql-yoga/__tests__/recipes.spec.ts b/packages/graphql-yoga/__tests__/recipes.spec.ts index 5aab2408a7..a8ae53fc57 100644 --- a/packages/graphql-yoga/__tests__/recipes.spec.ts +++ b/packages/graphql-yoga/__tests__/recipes.spec.ts @@ -12,7 +12,7 @@ describe('recipe', () => { resolvers: { Query: { id: (_, __, context: YogaInitialContext) => { - return context.params.extensions?.id; + return context.params.extensions?.['id']; }, }, }, diff --git a/packages/graphql-yoga/__tests__/request-cancellation.spec.ts b/packages/graphql-yoga/__tests__/request-cancellation.spec.ts index 3dcfbaf1d5..94a0c5300b 100644 --- a/packages/graphql-yoga/__tests__/request-cancellation.spec.ts +++ b/packages/graphql-yoga/__tests__/request-cancellation.spec.ts @@ -6,7 +6,7 @@ import { useExecutionCancellation } from '../src/plugins/use-execution-cancellat const variants: Array<[name: string, fetchAPI: undefined | FetchAPI]> = [['Ponyfill', undefined]]; -if (!process.env.LEAK_TESTS) { +if (!process.env['LEAK_TESTS']) { variants.push([ 'Native', // eslint-disable-next-line @typescript-eslint/ban-ts-comment diff --git a/packages/graphql-yoga/__tests__/requests.spec.ts b/packages/graphql-yoga/__tests__/requests.spec.ts index b0e0c9b691..5615e3aca9 100644 --- a/packages/graphql-yoga/__tests__/requests.spec.ts +++ b/packages/graphql-yoga/__tests__/requests.spec.ts @@ -534,7 +534,7 @@ describe('requests', () => { const firstResBody = await firstRes.json(); expect(firstResBody.data.greetings).toBe('Hello world!'); expect(onExecuteFn).toHaveBeenCalledTimes(1); - expect(onExecuteFn.mock.calls[0][0].args.contextValue.request).toBe(firstReq); + expect(onExecuteFn.mock.calls[0]?.[0].args.contextValue.request).toBe(firstReq); const secondReq = new Request('http://yoga/graphql', { method: 'POST', headers: { @@ -547,9 +547,9 @@ describe('requests', () => { const secondResBody = await secondRes.json(); expect(secondResBody.data.greetings).toBe('Hello world!'); expect(onExecuteFn).toHaveBeenCalledTimes(2); - expect(onExecuteFn.mock.calls[1][0].args.contextValue.request).toBe(secondReq); - expect(onExecuteFn.mock.calls[1][0].args.contextValue).not.toBe( - onExecuteFn.mock.calls[0][0].args.contextValue, + expect(onExecuteFn.mock.calls[1]?.[0].args.contextValue.request).toBe(secondReq); + expect(onExecuteFn.mock.calls[1]?.[0].args.contextValue).not.toBe( + onExecuteFn.mock.calls[0]![0].args.contextValue, ); }); }); diff --git a/packages/graphql-yoga/scripts/generate-graphiql-html.js b/packages/graphql-yoga/scripts/generate-graphiql-html.js index d8327b23ca..05b12f737b 100644 --- a/packages/graphql-yoga/scripts/generate-graphiql-html.js +++ b/packages/graphql-yoga/scripts/generate-graphiql-html.js @@ -5,16 +5,26 @@ import { minify as minifyT } from 'html-minifier-terser'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); +// TODO review if this function is still needed. +// The types suggest that minifyT is already returning a string. +// And toString does not accept an argument. +/** + * @param {string} str + */ async function minify(str) { return ( - await minifyT(str, { - minifyJS: true, - useShortDoctype: false, - removeAttributeQuotes: true, - collapseWhitespace: true, - minifyCSS: true, - }) - ).toString('utf-8'); + ( + await minifyT(str, { + minifyJS: true, + useShortDoctype: false, + removeAttributeQuotes: true, + collapseWhitespace: true, + minifyCSS: true, + }) + ) + // @ts-expect-error + .toString('utf-8') + ); } async function minifyGraphiQLHTML() { diff --git a/packages/graphql-yoga/src/error.ts b/packages/graphql-yoga/src/error.ts index 32a3be6101..ce8af8cf08 100644 --- a/packages/graphql-yoga/src/error.ts +++ b/packages/graphql-yoga/src/error.ts @@ -41,7 +41,7 @@ export function isAbortError(error: unknown): error is DOMException { return ( typeof error === 'object' && error?.constructor?.name === 'DOMException' && - (error as Record).name === 'AbortError' + (error as DOMException).name === 'AbortError' ); } diff --git a/packages/graphql-yoga/src/plugins/request-parser/post-json.ts b/packages/graphql-yoga/src/plugins/request-parser/post-json.ts index b040dd3b33..7b66838e79 100644 --- a/packages/graphql-yoga/src/plugins/request-parser/post-json.ts +++ b/packages/graphql-yoga/src/plugins/request-parser/post-json.ts @@ -23,7 +23,7 @@ export async function parsePOSTJsonRequest(request: Request): Promise param.includes('charset=')) || 'charset=utf-8'; // utf-8 is assumed when not specified; if (charset !== 'charset=utf-8') { diff --git a/packages/graphql-yoga/src/plugins/result-processor/regular.ts b/packages/graphql-yoga/src/plugins/result-processor/regular.ts index 872f7c8bc8..3246606393 100644 --- a/packages/graphql-yoga/src/plugins/result-processor/regular.ts +++ b/packages/graphql-yoga/src/plugins/result-processor/regular.ts @@ -35,7 +35,8 @@ export function processRegularResult( !Array.isArray(executionResult) && areGraphQLErrors(executionResult.errors) && executionResult.errors.some( - err => !err.extensions?.originalError || isGraphQLError(err.extensions.originalError), + err => + !err.extensions?.['originalError'] || isGraphQLError(err.extensions['originalError']), ), ); diff --git a/packages/graphql-yoga/src/plugins/result-processor/sse.ts b/packages/graphql-yoga/src/plugins/result-processor/sse.ts index cceff61d06..52d28748cb 100644 --- a/packages/graphql-yoga/src/plugins/result-processor/sse.ts +++ b/packages/graphql-yoga/src/plugins/result-processor/sse.ts @@ -11,7 +11,7 @@ export function getSSEProcessor(): ResultProcessor { let pingIntervalMs = 12_000; // for testing the pings, reduce the timeout - if (globalThis.process?.env?.NODE_ENV === 'test') { + if (globalThis.process?.env?.['NODE_ENV'] === 'test') { pingIntervalMs = 300; } diff --git a/packages/graphql-yoga/src/server.ts b/packages/graphql-yoga/src/server.ts index 184ad76b0f..82ec06779f 100644 --- a/packages/graphql-yoga/src/server.ts +++ b/packages/graphql-yoga/src/server.ts @@ -488,7 +488,7 @@ export class YogaServer< if (result == null) { const additionalContext = - context.request === request + context['request'] === request ? { params, } diff --git a/packages/graphql-yoga/src/utils/mask-error.ts b/packages/graphql-yoga/src/utils/mask-error.ts index d98dacd6f4..d252ab2f23 100644 --- a/packages/graphql-yoga/src/utils/mask-error.ts +++ b/packages/graphql-yoga/src/utils/mask-error.ts @@ -6,7 +6,7 @@ import { MaskError } from '../types.js'; export const maskError: MaskError = ( error: unknown, message: string, - isDev = globalThis.process?.env?.NODE_ENV === 'development', + isDev = globalThis.process?.env?.['NODE_ENV'] === 'development', ) => { if (isGraphQLError(error)) { if (error.originalError) { @@ -19,7 +19,7 @@ export const maskError: MaskError = ( unexpected: true, }; if (isDev) { - extensions.originalError = { + extensions['originalError'] = { message: error.originalError.message, stack: error.originalError.stack, }; diff --git a/packages/nestjs-federation/src/index.ts b/packages/nestjs-federation/src/index.ts index 97e17124df..280dd7e696 100644 --- a/packages/nestjs-federation/src/index.ts +++ b/packages/nestjs-federation/src/index.ts @@ -29,11 +29,13 @@ export class YogaFederationDriver< super(); } - async generateSchema(options: YogaFederationDriverConfig): Promise { + override async generateSchema( + options: YogaFederationDriverConfig, + ): Promise { return await this.graphqlFederationFactory.generateSchema(options); } - public async start(options: YogaFederationDriverConfig) { + public override async start(options: YogaFederationDriverConfig) { if (options.definitions?.path) { if (!options.schema) { throw new Error('Schema is required when providing definitions path'); @@ -66,7 +68,7 @@ export class YogaFederationDriver< } } - public async stop(): Promise { + public override async stop(): Promise { await this.subscriptionService?.stop(); } } @@ -96,11 +98,13 @@ export interface YogaGatewayDriverConfig extends AbstractYogaDriver { - public async generateSchema(_options: YogaGatewayDriverConfig): Promise { + public override async generateSchema( + _options: YogaGatewayDriverConfig, + ): Promise { return new GraphQLSchema({}); } - public async start(options: YogaGatewayDriverConfig) { + public override async start(options: YogaGatewayDriverConfig) { const { server: serverOpts = {}, gateway: gatewayOpts = {} } = options; const gateway: ApolloGateway = new ApolloGateway(gatewayOpts); @@ -112,12 +116,12 @@ export class YogaGatewayDriver< }); } - public async mergeDefaultOptions( + public override async mergeDefaultOptions( options: Record, ): Promise> { return { ...options, - server: await super.mergeDefaultOptions(options?.server ?? {}), + server: await super.mergeDefaultOptions(options?.['server'] ?? {}), }; } } diff --git a/packages/nestjs/src/index.ts b/packages/nestjs/src/index.ts index 6a02269bb3..54e816b9e2 100644 --- a/packages/nestjs/src/index.ts +++ b/packages/nestjs/src/index.ts @@ -85,7 +85,8 @@ export abstract class AbstractYogaDriver< // disable error masking by default maskedErrors: options.maskedErrors == null ? false : options.maskedErrors, // disable graphiql in production - graphiql: options.graphiql == null ? process.env.NODE_ENV !== 'production' : options.graphiql, + graphiql: + options.graphiql == null ? process.env['NODE_ENV'] !== 'production' : options.graphiql, }; if (platformName === 'express') { return this.registerExpress(options as YogaDriverConfig<'express'>); @@ -209,7 +210,7 @@ export abstract class AbstractYogaDriver< return mergedSchema; } - public subscriptionWithFilter( + public override subscriptionWithFilter( instanceRef: unknown, filterFn: ( payload: TPayload, @@ -238,7 +239,7 @@ export class YogaDriver< > extends AbstractYogaDriver { private subscriptionService?: GqlSubscriptionService; - public async start(options: YogaDriverConfig) { + public override async start(options: YogaDriverConfig) { if (options.definitions?.path) { if (!options.schema) { throw new Error('Schema is required when generating definitions'); @@ -386,7 +387,7 @@ export class YogaDriver< } } - public async stop() { + public override async stop() { await this.subscriptionService?.stop(); } } diff --git a/packages/plugins/apollo-inline-trace/__tests__/apollo-inline-trace.spec.ts b/packages/plugins/apollo-inline-trace/__tests__/apollo-inline-trace.spec.ts index f41017fe43..abe31bae07 100644 --- a/packages/plugins/apollo-inline-trace/__tests__/apollo-inline-trace.spec.ts +++ b/packages/plugins/apollo-inline-trace/__tests__/apollo-inline-trace.spec.ts @@ -220,8 +220,8 @@ describe('Inline Trace', () => { for (let i = 0; i < arr.length; i++) { const person = arr[i]; expect(person?.error?.length).toBe(0); - expect(person.index).toBe(i); - expectTraceNode(person.child?.[0], 'name', 'String!', 'Person'); + expect(person!.index).toBe(i); + expectTraceNode(person!.child?.[0], 'name', 'String!', 'Person'); } }); @@ -271,12 +271,12 @@ describe('Inline Trace', () => { const error = node!.error!; expect(error).toBeInstanceOf(Array); expect(error.length).toBeGreaterThan(0); - expect(typeof error[0].message).toBe('string'); - expect(typeof error[0].location).toBeDefined(); - expect(typeof error[0].location?.[0].line).toBe('number'); - expect(typeof error[0].location?.[0].column).toBe('number'); + expect(typeof error[0]!.message).toBe('string'); + expect(typeof error[0]!.location).toBeDefined(); + expect(typeof error[0]!.location?.[0]?.line).toBe('number'); + expect(typeof error[0]!.location?.[0]?.column).toBe('number'); expect(() => { - JSON.parse(error[0].json!); + JSON.parse(error[0]!.json!); }).not.toThrow(); } @@ -448,9 +448,9 @@ describe('Inline Trace', () => { expectTraceNodeError(boom); // will check for location const error = boom!.error!; - expect(error[0].message).toBe('bim'); // not 'bam' + expect(error[0]?.message).toBe('bim'); // not 'bam' - const errObj = JSON.parse(error[0].json!); + const errObj = JSON.parse(error[0]!.json!); expect(errObj.extensions).toEqual({ str: 'ing' }); }); diff --git a/packages/plugins/apollo-inline-trace/__tests__/apollo-inline-trace.yoga-gateway.spec.ts b/packages/plugins/apollo-inline-trace/__tests__/apollo-inline-trace.yoga-gateway.spec.ts index 94a585b534..8f67468bf0 100644 --- a/packages/plugins/apollo-inline-trace/__tests__/apollo-inline-trace.yoga-gateway.spec.ts +++ b/packages/plugins/apollo-inline-trace/__tests__/apollo-inline-trace.yoga-gateway.spec.ts @@ -118,19 +118,19 @@ describeIf(versionInfo.major >= 16)('Inline Trace - Yoga gateway', () => { expect(response.status).toBe(200); expect(result.errors).toMatchObject(expectedErrors); expect(result.data).toMatchObject(expectedData); - expect(result.extensions?.ftv1).toEqual(expect.any(String)); + expect(result.extensions?.['ftv1']).toEqual(expect.any(String)); - const ftv1 = result.extensions?.ftv1 as string; + const ftv1 = result.extensions?.['ftv1'] as string; const trace = Trace.decode(Buffer.from(ftv1, 'base64')); expectTrace(trace); - const nullableFail = trace.root?.child?.[0].child?.[0] as Trace.INode; + const nullableFail = trace.root?.child?.[0]?.child?.[0] as Trace.INode; expectTraceNode(nullableFail, 'nullableFail', 'TestUser1', 'TestNestedField'); expect(nullableFail.error).toHaveLength(1); - expect(JSON.parse(nullableFail.error![0].json!)).toMatchObject(expectedErrors[0]); + expect(JSON.parse(nullableFail.error![0]!.json!)).toMatchObject(expectedErrors[0]!); }); it('nullableFail - simple federated query - should return result with expected data and errors', async () => { @@ -173,19 +173,19 @@ describeIf(versionInfo.major >= 16)('Inline Trace - Yoga gateway', () => { expect(response.status).toBe(200); expect(result.errors).toMatchObject(expectedErrors); expect(result.data).toMatchObject(expectedData); - expect(result.extensions?.ftv1).toEqual(expect.any(String)); + expect(result.extensions?.['ftv1']).toEqual(expect.any(String)); - const ftv1 = result.extensions?.ftv1 as string; + const ftv1 = result.extensions?.['ftv1'] as string; const trace = Trace.decode(Buffer.from(ftv1, 'base64')); expectTrace(trace); - const nullableFail = trace.root?.child?.[0].child?.[0] as Trace.INode; + const nullableFail = trace.root?.child?.[0]?.child?.[0] as Trace.INode; expectTraceNode(nullableFail, 'nullableFail', 'TestUser1', 'TestNestedField'); expect(nullableFail.error).toHaveLength(1); - expect(JSON.parse(nullableFail.error![0].json!)).toMatchObject(expectedErrors[0]); + expect(JSON.parse(nullableFail.error![0]!.json!)).toMatchObject(expectedErrors[0]!); }); it('nonNullableFail - multi federated query - should return result with expected data and errors', async () => { @@ -236,19 +236,19 @@ describeIf(versionInfo.major >= 16)('Inline Trace - Yoga gateway', () => { expect(response.status).toBe(200); expect(result.errors).toMatchObject(expectedErrors); expect(result.data).toMatchObject(expectedData); - expect(result.extensions?.ftv1).toEqual(expect.any(String)); + expect(result.extensions?.['ftv1']).toEqual(expect.any(String)); - const ftv1 = result.extensions?.ftv1 as string; + const ftv1 = result.extensions?.['ftv1'] as string; const trace = Trace.decode(Buffer.from(ftv1, 'base64')); expectTrace(trace); - const nonNullableFail = trace.root?.child?.[0].child?.[0] as Trace.INode; + const nonNullableFail = trace.root?.child?.[0]?.child?.[0] as Trace.INode; expectTraceNode(nonNullableFail, 'nonNullableFail', 'TestUser1!', 'TestNestedField'); expect(nonNullableFail.error).toHaveLength(1); - expect(JSON.parse(nonNullableFail.error![0].json!)).toMatchObject(expectedErrors[0]); + expect(JSON.parse(nonNullableFail.error![0]!.json!)).toMatchObject(expectedErrors[0]!); }); it('nonNullableFail - simple federated query - should return result with expected data and errors', async () => { @@ -289,9 +289,9 @@ describeIf(versionInfo.major >= 16)('Inline Trace - Yoga gateway', () => { expect(response.status).toBe(200); expect(result.errors).toMatchObject(expectedErrors); expect(result.data).toMatchObject(expectedData); - expect(result.extensions?.ftv1).toEqual(expect.any(String)); + expect(result.extensions?.['ftv1']).toEqual(expect.any(String)); - const ftv1 = result.extensions?.ftv1 as string; + const ftv1 = result.extensions?.['ftv1'] as string; const trace = Trace.decode(Buffer.from(ftv1, 'base64')); expectTrace(trace); @@ -305,6 +305,6 @@ describeIf(versionInfo.major >= 16)('Inline Trace - Yoga gateway', () => { expectTraceNode(testNestedField, 'testNestedField', 'TestNestedField', 'Query'); expect(testNestedField.error).toHaveLength(1); - expect(JSON.parse(testNestedField.error![0].json!)).toMatchObject(expectedErrors[0]); + expect(JSON.parse(testNestedField.error![0]!.json!)).toMatchObject(expectedErrors[0]!); }); }); diff --git a/packages/plugins/apollo-inline-trace/src/index.ts b/packages/plugins/apollo-inline-trace/src/index.ts index 19a8584eb6..11a3eae876 100644 --- a/packages/plugins/apollo-inline-trace/src/index.ts +++ b/packages/plugins/apollo-inline-trace/src/index.ts @@ -325,7 +325,7 @@ function handleErrors( * * Reference: https://github.com/apollographql/apollo-server/blob/9389da785567a56e989430962564afc71e93bd7f/packages/apollo-server-core/src/plugin/traceTreeBuilder.ts#L133-L141 */ - if (err.extensions?.serviceName) { + if (err.extensions?.['serviceName']) { continue; } diff --git a/packages/plugins/apollo-usage-report/src/index.ts b/packages/plugins/apollo-usage-report/src/index.ts index a1cc61ad6a..d354d453e6 100644 --- a/packages/plugins/apollo-usage-report/src/index.ts +++ b/packages/plugins/apollo-usage-report/src/index.ts @@ -181,12 +181,12 @@ export function useApolloUsageReport(options: ApolloUsageReportOptions = {}): Pl } tracesPerSchema[trace.schemaId] ||= {}; - tracesPerSchema[trace.schemaId][trace.operationKey] ||= { trace: [] }; - tracesPerSchema[trace.schemaId][trace.operationKey].trace?.push(trace.trace); + tracesPerSchema[trace.schemaId]![trace.operationKey] ||= { trace: [] }; + tracesPerSchema[trace.schemaId]![trace.operationKey]!.trace?.push(trace.trace); } for (const schemaId in tracesPerSchema) { - const tracesPerQuery = tracesPerSchema[schemaId]; + const tracesPerQuery = tracesPerSchema[schemaId]!; const agentVersion = options.agentVersion || `graphql-yoga@${yoga.version}`; serverContext.waitUntil( sendTrace( @@ -273,5 +273,5 @@ function isDocumentNode(data: unknown): data is DocumentNode { const isObject = (data: unknown): data is Record => !!data && typeof data === 'object'; - return isObject(data) && data.kind === Kind.DOCUMENT; + return isObject(data) && data['kind'] === Kind.DOCUMENT; } diff --git a/packages/plugins/apq/src/index.ts b/packages/plugins/apq/src/index.ts index 46edf06aac..769809e4ee 100644 --- a/packages/plugins/apq/src/index.ts +++ b/packages/plugins/apq/src/index.ts @@ -81,7 +81,7 @@ export function useAPQ(options: APQOptions = {}): Plugin { return { async onParams({ params, setParams, fetchAPI }) { - const persistedQueryData = decodeAPQExtension(params.extensions?.persistedQuery); + const persistedQueryData = decodeAPQExtension(params.extensions?.['persistedQuery']); if (persistedQueryData === null) { return; diff --git a/packages/plugins/defer-stream/__tests__/validations/harness.ts b/packages/plugins/defer-stream/__tests__/validations/harness.ts index 0a19f2b231..5fec4b2023 100644 --- a/packages/plugins/defer-stream/__tests__/validations/harness.ts +++ b/packages/plugins/defer-stream/__tests__/validations/harness.ts @@ -22,8 +22,8 @@ function mapValue( ): Record { const result = Object.create(null); - for (const key of Object.keys(map)) { - result[key] = fn(map[key], key); + for (const [key, value] of Object.entries(map)) { + result[key] = fn(value, key); } return result; } @@ -37,8 +37,8 @@ function toJSONDeep(value: unknown): unknown { return value; } - if (typeof value.toJSON === 'function') { - return value.toJSON(); + if (typeof value['toJSON'] === 'function') { + return value['toJSON'](); } if (Array.isArray(value)) { diff --git a/packages/plugins/defer-stream/src/validations/overlapping-fields-can-be-merged.ts b/packages/plugins/defer-stream/src/validations/overlapping-fields-can-be-merged.ts index 77726c0ff3..f5825e8846 100644 --- a/packages/plugins/defer-stream/src/validations/overlapping-fields-can-be-merged.ts +++ b/packages/plugins/defer-stream/src/validations/overlapping-fields-can-be-merged.ts @@ -275,7 +275,7 @@ function findConflictsWithinSelectionSet( comparedFragmentPairs, false, fieldMap, - fragmentNames[i], + fragmentNames[i]!, ); // (C) Then compare this fragment with all other fragments found in this // selection set to collect conflicts between fragments spread together. @@ -288,8 +288,8 @@ function findConflictsWithinSelectionSet( cachedFieldsAndFragmentNames, comparedFragmentPairs, false, - fragmentNames[i], - fragmentNames[j], + fragmentNames[i]!, + fragmentNames[j]!, ); } } @@ -548,8 +548,8 @@ function collectConflictsWithin( comparedFragmentPairs, false, // within one collection is never mutually exclusive responseName, - fields[i], - fields[j], + fields[i]!, + fields[j]!, ); if (conflict) { conflicts.push(conflict); diff --git a/packages/plugins/graphql-sse/src/index.ts b/packages/plugins/graphql-sse/src/index.ts index cb23ca9c4c..7c8bd4aab6 100644 --- a/packages/plugins/graphql-sse/src/index.ts +++ b/packages/plugins/graphql-sse/src/index.ts @@ -70,7 +70,7 @@ export function useGraphQLSSE(options: GraphQLSSEPluginOptions = {}): Plugin { expect(payload.serverContext).toBeDefined(); expect(payload.url).toBeDefined(); - const t = payload.request.headers.get('Authorization'); + const authorizationHeader = payload.request.headers.get('Authorization'); + if (!authorizationHeader) return; - if (t) { - const parts = t.split(' '); + const [prefix, token] = authorizationHeader.split(' '); + if (!token) throw new Error(`Authentication header was set, but token is missing.`); - return { - token: parts[1], - prefix: parts[0], - }; - } - - return undefined; + return { + prefix, + token, + }; }, ], }); @@ -611,7 +609,7 @@ describe('jwt plugin', () => { const createTestServer = (options: JwtPluginOptions, initPlugins: Plugin[] = []) => { const yoga = createYoga({ schema, - logging: !!process.env.DEBUG, + logging: !!process.env['DEBUG'], plugins: [...initPlugins, useJWT(options)], }); diff --git a/packages/plugins/jwt/src/utils.ts b/packages/plugins/jwt/src/utils.ts index 3b8633e31a..f81feb0260 100644 --- a/packages/plugins/jwt/src/utils.ts +++ b/packages/plugins/jwt/src/utils.ts @@ -15,17 +15,15 @@ export function extractFromHeader(options: { if (!options.prefix) { const parts = header.split(' ').map(s => s.trim()); + const [prefix, token] = parts.length === 1 ? [undefined, parts[0]] : parts; - if (parts.length === 1) { - return { - prefix: undefined, - token: parts[0], - }; + if (!token) { + throw badRequestError(`Authentication header was set, but token is missing.`); } return { - prefix: parts[0], - token: parts[1], + prefix, + token, }; } @@ -40,8 +38,8 @@ export function extractFromHeader(options: { } return { - token, prefix, + token, }; }; } diff --git a/packages/plugins/persisted-operations/src/index.ts b/packages/plugins/persisted-operations/src/index.ts index 0553d7c99a..acceb2a919 100644 --- a/packages/plugins/persisted-operations/src/index.ts +++ b/packages/plugins/persisted-operations/src/index.ts @@ -30,12 +30,12 @@ export const defaultExtractPersistedOperationId: ExtractPersistedOperationId = ( if ( params.extensions != null && typeof params.extensions === 'object' && - params.extensions?.persistedQuery != null && - typeof params.extensions?.persistedQuery === 'object' && - params.extensions?.persistedQuery.version === 1 && - typeof params.extensions?.persistedQuery.sha256Hash === 'string' + params.extensions?.['persistedQuery'] != null && + typeof params.extensions?.['persistedQuery'] === 'object' && + params.extensions?.['persistedQuery']?.['version'] === 1 && + typeof params.extensions?.['persistedQuery']?.['sha256Hash'] === 'string' ) { - return params.extensions?.persistedQuery.sha256Hash; + return params.extensions?.['persistedQuery']?.['sha256Hash']; } return null; }; diff --git a/packages/plugins/response-cache/__tests__/response-cache.spec.ts b/packages/plugins/response-cache/__tests__/response-cache.spec.ts index 465381e93a..a285248703 100644 --- a/packages/plugins/response-cache/__tests__/response-cache.spec.ts +++ b/packages/plugins/response-cache/__tests__/response-cache.spec.ts @@ -1253,7 +1253,7 @@ it('gets the context in "session" and "buildResponseCacheKey"', async () => { expect(buildResponseCacheKey).toHaveBeenCalledTimes(1); expect(context).toBeDefined(); expect(session).toHaveBeenCalledWith(request, context); - expect(buildResponseCacheKey.mock.calls[0][0]).toMatchObject({ + expect(buildResponseCacheKey.mock.calls[0]?.[0]).toMatchObject({ documentString: '{__typename}', variableValues: {}, sessionId: null, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0f364fba1f..ecdce1c3dd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -52,12 +52,18 @@ importers: '@theguild/prettier-config': specifier: 3.0.0 version: 3.0.0(prettier@3.4.2) + '@tsconfig/strictest': + specifier: ^2.0.5 + version: 2.0.5 '@types/babel__core': specifier: 7.20.5 version: 7.20.5 '@types/babel__preset-env': specifier: 7.9.7 version: 7.9.7 + '@types/html-minifier-terser': + specifier: ^7.0.2 + version: 7.0.2 '@types/jest': specifier: 29.5.14 version: 29.5.14 @@ -7613,6 +7619,9 @@ packages: '@tsconfig/node16@1.0.4': resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + '@tsconfig/strictest@2.0.5': + resolution: {integrity: sha512-ec4tjL2Rr0pkZ5hww65c+EEPYwxOi4Ryv+0MtjeaSQRJyq322Q27eOQiFbuNgw2hpL4hB1/W/HBGk3VKS43osg==} + '@tufjs/canonical-json@2.0.0': resolution: {integrity: sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==} engines: {node: ^16.14.0 || >=18.0.0} @@ -7819,6 +7828,9 @@ packages: '@types/hast@3.0.4': resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + '@types/html-minifier-terser@7.0.2': + resolution: {integrity: sha512-mm2HqV22l8lFQh4r2oSsOEVea+m0qqxEmwpc9kC1p/XzmjLWrReR9D/GRs8Pex2NX/imyEH9c5IU/7tMBQCHOA==} + '@types/http-assert@1.5.6': resolution: {integrity: sha512-TTEwmtjgVbYAzZYWyeHPrrtWnfVkm8tQkP8P21uQifPgMRgjrow3XDEYqucuC8SKZJT7pUnhU/JymvjggxO9vw==} @@ -24289,6 +24301,8 @@ snapshots: '@tsconfig/node16@1.0.4': {} + '@tsconfig/strictest@2.0.5': {} + '@tufjs/canonical-json@2.0.0': {} '@tufjs/models@2.0.1': @@ -24562,6 +24576,8 @@ snapshots: dependencies: '@types/unist': 3.0.3 + '@types/html-minifier-terser@7.0.2': {} + '@types/http-assert@1.5.6': {} '@types/http-cache-semantics@4.0.4': {} diff --git a/tsconfig.json b/tsconfig.json index 4e8b1d644a..50779e0be0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,8 +1,8 @@ { + "extends": ["@tsconfig/strictest"], "compilerOptions": { "baseUrl": ".", "outDir": "dist", - "esModuleInterop": true, "allowSyntheticDefaultImports": true, "importHelpers": true, "experimentalDecorators": true, @@ -14,12 +14,8 @@ "sourceMap": false, "declaration": false, "noImplicitThis": true, - "strict": true, "alwaysStrict": true, - "noImplicitReturns": true, - "noUnusedLocals": false, "resolveJsonModule": true, - "skipLibCheck": true, "paths": { "graphql-yoga": ["packages/graphql-yoga/src/index.ts"], "@graphql-yoga/subscription": ["packages/subscription/src/index.ts"], @@ -30,7 +26,13 @@ "@graphql-yoga/urql-exchange": ["packages/client/urql-exchange/src/index.ts"], "@graphql-yoga/*": ["packages/*/src/index.ts"] }, - "jsx": "preserve" + "jsx": "preserve", + // TODO enable this, just need time to deal with the errors. + "exactOptionalPropertyTypes": false, + "isolatedModules": false, + // These are managed by ESLint + "noUnusedLocals": false, + "noUnusedParameters": false }, "include": ["packages"], "exclude": [ From 59c16b9d1915cdd7bf4c67f7707b0a19dff64561 Mon Sep 17 00:00:00 2001 From: Jason Kuhrt Date: Wed, 11 Dec 2024 12:13:32 -0500 Subject: [PATCH 02/10] ugh --- tsconfig.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index 50779e0be0..71166c0a3b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -27,10 +27,8 @@ "@graphql-yoga/*": ["packages/*/src/index.ts"] }, "jsx": "preserve", - // TODO enable this, just need time to deal with the errors. "exactOptionalPropertyTypes": false, "isolatedModules": false, - // These are managed by ESLint "noUnusedLocals": false, "noUnusedParameters": false }, From a241264c04ed0ea645b80fe825431d597a308027 Mon Sep 17 00:00:00 2001 From: Jason Kuhrt Date: Wed, 11 Dec 2024 12:15:12 -0500 Subject: [PATCH 03/10] isolated modules --- packages/graphql-yoga/src/index.ts | 5 ++++- .../fixtures/graphql/cats/cats.resolvers.ts | 2 +- packages/plugins/jwt/src/index.ts | 4 ++-- packages/plugins/prometheus/src/index.ts | 14 +++++++------- tsconfig.json | 3 +-- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/packages/graphql-yoga/src/index.ts b/packages/graphql-yoga/src/index.ts index 5c34b831af..1a56f652a7 100644 --- a/packages/graphql-yoga/src/index.ts +++ b/packages/graphql-yoga/src/index.ts @@ -39,4 +39,7 @@ export { } from '@envelop/core'; export { getSSEProcessor } from './plugins/result-processor/sse.js'; export { useExecutionCancellation } from './plugins/use-execution-cancellation.js'; -export { LandingPageRenderer, LandingPageRendererOpts } from './plugins/use-unhandled-route.js'; +export { + type LandingPageRenderer, + type LandingPageRendererOpts, +} from './plugins/use-unhandled-route.js'; diff --git a/packages/nestjs/__tests__/fixtures/graphql/cats/cats.resolvers.ts b/packages/nestjs/__tests__/fixtures/graphql/cats/cats.resolvers.ts index 132bd219e8..88459d0ff6 100644 --- a/packages/nestjs/__tests__/fixtures/graphql/cats/cats.resolvers.ts +++ b/packages/nestjs/__tests__/fixtures/graphql/cats/cats.resolvers.ts @@ -3,7 +3,7 @@ import { Args, Mutation, Query, ResolveField, Resolver, Subscription } from '@ne import { createPubSub } from '../../../utils/pubsub'; import { CatsGuard } from './cats.guard'; import { CatsService } from './cats.service'; -import { Cat } from './interfaces/cat.interface'; +import { type Cat } from './interfaces/cat.interface'; const catCreated = createPubSub<{ catCreated: Cat }>(); diff --git a/packages/plugins/jwt/src/index.ts b/packages/plugins/jwt/src/index.ts index 9b94d8ed7a..eebb3af41f 100644 --- a/packages/plugins/jwt/src/index.ts +++ b/packages/plugins/jwt/src/index.ts @@ -1,8 +1,8 @@ -export { JwtPluginOptions, ExtractTokenFunction, GetSigningKeyFunction } from './config.js'; +export type { JwtPluginOptions, ExtractTokenFunction, GetSigningKeyFunction } from './config.js'; export { extractFromCookie, extractFromHeader, createInlineSigningKeyProvider, createRemoteJwksSigningKeyProvider, } from './utils.js'; -export { useJWT, JWTExtendContextFields } from './plugin.js'; +export { useJWT, type JWTExtendContextFields } from './plugin.js'; diff --git a/packages/plugins/prometheus/src/index.ts b/packages/plugins/prometheus/src/index.ts index ee2246465a..d104ca0c24 100644 --- a/packages/plugins/prometheus/src/index.ts +++ b/packages/plugins/prometheus/src/index.ts @@ -20,19 +20,19 @@ import { } from '@envelop/prometheus'; export { - CounterAndLabels, + type CounterAndLabels, createCounter, createHistogram, createSummary, - FillLabelsFnParams, - HistogramAndLabels, - SummaryAndLabels, + type FillLabelsFnParams, + type HistogramAndLabels, + type SummaryAndLabels, getHistogramFromConfig, getCounterFromConfig, getSummaryFromConfig, - HistogramMetricOption, - CounterMetricOption, - SummaryMetricOption, + type HistogramMetricOption, + type CounterMetricOption, + type SummaryMetricOption, }; export type PrometheusTracingPluginConfig = Omit< diff --git a/tsconfig.json b/tsconfig.json index 71166c0a3b..2c0ab0981e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -27,8 +27,7 @@ "@graphql-yoga/*": ["packages/*/src/index.ts"] }, "jsx": "preserve", - "exactOptionalPropertyTypes": false, - "isolatedModules": false, + "exactOptionalPropertyTypes": true, "noUnusedLocals": false, "noUnusedParameters": false }, From c93cbee74ed84861a3d3dedfa2ef94e6bcf3c771 Mon Sep 17 00:00:00 2001 From: Jason Kuhrt Date: Wed, 11 Dec 2024 12:15:43 -0500 Subject: [PATCH 04/10] not yet --- tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index 2c0ab0981e..bcb0a77623 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -27,7 +27,7 @@ "@graphql-yoga/*": ["packages/*/src/index.ts"] }, "jsx": "preserve", - "exactOptionalPropertyTypes": true, + "exactOptionalPropertyTypes": false, "noUnusedLocals": false, "noUnusedParameters": false }, From c4c2020f95a8d69f0de8bcb3545d0dfb6f616bab Mon Sep 17 00:00:00 2001 From: Jason Kuhrt Date: Wed, 11 Dec 2024 12:17:35 -0500 Subject: [PATCH 05/10] tidy --- tsconfig.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index bcb0a77623..c414249851 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,6 +16,10 @@ "noImplicitThis": true, "alwaysStrict": true, "resolveJsonModule": true, + "jsx": "preserve", + "exactOptionalPropertyTypes": false, + "noUnusedLocals": false, + "noUnusedParameters": false, "paths": { "graphql-yoga": ["packages/graphql-yoga/src/index.ts"], "@graphql-yoga/subscription": ["packages/subscription/src/index.ts"], @@ -25,11 +29,7 @@ "@graphql-yoga/apollo-link": ["packages/client/apollo-link/src/index.ts"], "@graphql-yoga/urql-exchange": ["packages/client/urql-exchange/src/index.ts"], "@graphql-yoga/*": ["packages/*/src/index.ts"] - }, - "jsx": "preserve", - "exactOptionalPropertyTypes": false, - "noUnusedLocals": false, - "noUnusedParameters": false + } }, "include": ["packages"], "exclude": [ From 687a0374144004cc1c24d62bd5636aadc0f1a839 Mon Sep 17 00:00:00 2001 From: Jason Kuhrt Date: Wed, 11 Dec 2024 13:15:15 -0500 Subject: [PATCH 06/10] debug --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9212babf84..117008bd6a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -164,8 +164,8 @@ jobs: restore-keys: | ${{ runner.os }}-pnpm-store-graphql-v${{ matrix.graphql-version }}- - - name: Set GraphQL Version - run: node scripts/override-graphql-version.js ${{ matrix.graphql-version }} + # - name: Set GraphQL Version + # run: node scripts/override-graphql-version.js ${{ matrix.graphql-version }} - name: Install Dependencies run: pnpm i --no-frozen-lockfile # no frozen-lockfile because we change the resolutions From 076c7300c60f2a886c4d56b6f010ee6fd8117893 Mon Sep 17 00:00:00 2001 From: Jason Kuhrt Date: Wed, 11 Dec 2024 13:35:39 -0500 Subject: [PATCH 07/10] fixes for 15.x --- .github/workflows/ci.yml | 4 ++-- .../__integration-tests__/browser.spec.ts | 6 +++--- .../__tests__/http-extensions.spec.ts | 3 ++- packages/graphql-yoga/src/error.ts | 17 ++++++++++------- .../use-prevent-mutation-via-get.ts | 2 +- 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 117008bd6a..9212babf84 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -164,8 +164,8 @@ jobs: restore-keys: | ${{ runner.os }}-pnpm-store-graphql-v${{ matrix.graphql-version }}- - # - name: Set GraphQL Version - # run: node scripts/override-graphql-version.js ${{ matrix.graphql-version }} + - name: Set GraphQL Version + run: node scripts/override-graphql-version.js ${{ matrix.graphql-version }} - name: Install Dependencies run: pnpm i --no-frozen-lockfile # no frozen-lockfile because we change the resolutions diff --git a/packages/graphql-yoga/__integration-tests__/browser.spec.ts b/packages/graphql-yoga/__integration-tests__/browser.spec.ts index 308d4e4d57..e58bda8576 100644 --- a/packages/graphql-yoga/__integration-tests__/browser.spec.ts +++ b/packages/graphql-yoga/__integration-tests__/browser.spec.ts @@ -73,7 +73,7 @@ export function createTestSchema() { }, }, type: GraphQLString, - resolve: (_root, args) => args.text, + resolve: (_root, args) => args['text'], }, hello: { type: GraphQLString, @@ -111,7 +111,7 @@ export function createTestSchema() { }, type: GraphQLInt, resolve: (_root, args) => { - return args.number; + return args['number']; }, }, }), @@ -186,7 +186,7 @@ export function createTestSchema() { }, }, async *subscribe(_root, args) { - for (let count = 1; count <= args.to; count++) { + for (let count = 1; count <= args['to']; count++) { yield { count }; await setTimeout$(200); } diff --git a/packages/graphql-yoga/__tests__/http-extensions.spec.ts b/packages/graphql-yoga/__tests__/http-extensions.spec.ts index 3129096aa7..83dddd4c38 100644 --- a/packages/graphql-yoga/__tests__/http-extensions.spec.ts +++ b/packages/graphql-yoga/__tests__/http-extensions.spec.ts @@ -631,7 +631,8 @@ describe('Result Extensions', () => { this.name = 'CustomError'; } - override toJSON() { + // @ts-ignore - Only in graphql@^16 is `toJSON` a base method + /* override */ toJSON() { return { message: this.message, extensions: { name: this.name, foo: 'bar' }, diff --git a/packages/graphql-yoga/src/error.ts b/packages/graphql-yoga/src/error.ts index ce8af8cf08..01613c286e 100644 --- a/packages/graphql-yoga/src/error.ts +++ b/packages/graphql-yoga/src/error.ts @@ -135,17 +135,20 @@ export function getResponseInitByRespectingErrors( if ('errors' in result && result.errors?.length) { for (const error of result.errors) { - if (error.extensions?.http) { - if (error.extensions.http.headers) { - Object.assign(headers, error.extensions.http.headers); + if (error.extensions?.['http']) { + if (error.extensions['http'].headers) { + Object.assign(headers, error.extensions['http'].headers); } - if (isApplicationJson && error.extensions.http.spec) { + if (isApplicationJson && error.extensions['http'].spec) { continue; } - if (error.extensions.http.status && (!status || error.extensions.http.status > status)) { - status = error.extensions.http.status; + if ( + error.extensions['http'].status && + (!status || error.extensions['http'].status > status) + ) { + status = error.extensions['http'].status; } - } else if (!isOriginalGraphQLError(error) || error.extensions?.unexpected) { + } else if (!isOriginalGraphQLError(error) || error.extensions?.['unexpected']) { unexpectedErrorExists = true; } } diff --git a/packages/graphql-yoga/src/plugins/request-validation/use-prevent-mutation-via-get.ts b/packages/graphql-yoga/src/plugins/request-validation/use-prevent-mutation-via-get.ts index 07d651e670..b761fb4a7b 100644 --- a/packages/graphql-yoga/src/plugins/request-validation/use-prevent-mutation-via-get.ts +++ b/packages/graphql-yoga/src/plugins/request-validation/use-prevent-mutation-via-get.ts @@ -59,7 +59,7 @@ export function usePreventMutationViaGET(): Plugin { if (result instanceof Error) { if (result instanceof GraphQLError) { - result.extensions.http = { + result.extensions['http'] = { spec: true, status: 400, }; From 4507d5c67a7ad994a168b0c87c199162b84eae30 Mon Sep 17 00:00:00 2001 From: Jason Kuhrt Date: Wed, 11 Dec 2024 13:41:07 -0500 Subject: [PATCH 08/10] fix lint --- packages/graphql-yoga/__tests__/http-extensions.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/graphql-yoga/__tests__/http-extensions.spec.ts b/packages/graphql-yoga/__tests__/http-extensions.spec.ts index 83dddd4c38..ccfd8fc061 100644 --- a/packages/graphql-yoga/__tests__/http-extensions.spec.ts +++ b/packages/graphql-yoga/__tests__/http-extensions.spec.ts @@ -631,6 +631,7 @@ describe('Result Extensions', () => { this.name = 'CustomError'; } + // eslint-disable-next-line // @ts-ignore - Only in graphql@^16 is `toJSON` a base method /* override */ toJSON() { return { From bcf6bfdb2bea7a98942518b6a762886683686d09 Mon Sep 17 00:00:00 2001 From: Jason Kuhrt Date: Wed, 11 Dec 2024 13:43:17 -0500 Subject: [PATCH 09/10] stricter --- .../graphql-yoga/__integration-tests__/file-uploads.spec.ts | 4 ++-- packages/graphql-yoga/__tests__/requests.spec.ts | 2 +- tsconfig.json | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/graphql-yoga/__integration-tests__/file-uploads.spec.ts b/packages/graphql-yoga/__integration-tests__/file-uploads.spec.ts index 716e6b6514..cbd4e3e638 100644 --- a/packages/graphql-yoga/__integration-tests__/file-uploads.spec.ts +++ b/packages/graphql-yoga/__integration-tests__/file-uploads.spec.ts @@ -12,11 +12,11 @@ describe('file uploads', () => { schema: createSchema({ resolvers: { Mutation: { - arrayBuffer: async (root, args) => { + arrayBuffer: async (_, args) => { const buf = Buffer.from(await args.file.arrayBuffer()); return sourceFile.equals(buf); }, - stream: async (root, args) => { + stream: async (_, args) => { const chunks = []; for await (const chunk of args.file.stream()) { chunks.push(chunk); diff --git a/packages/graphql-yoga/__tests__/requests.spec.ts b/packages/graphql-yoga/__tests__/requests.spec.ts index 5615e3aca9..d9533d98db 100644 --- a/packages/graphql-yoga/__tests__/requests.spec.ts +++ b/packages/graphql-yoga/__tests__/requests.spec.ts @@ -19,7 +19,7 @@ describe('requests', () => { requestUrl: (_, __, ctx) => ctx.request.url, }, Mutation: { - echo(root, args) { + echo(_, args) { return args.str; }, }, diff --git a/tsconfig.json b/tsconfig.json index c414249851..823753c71a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,7 +19,6 @@ "jsx": "preserve", "exactOptionalPropertyTypes": false, "noUnusedLocals": false, - "noUnusedParameters": false, "paths": { "graphql-yoga": ["packages/graphql-yoga/src/index.ts"], "@graphql-yoga/subscription": ["packages/subscription/src/index.ts"], From eff57e7a365e5b4876bcd92956b70d11815d227b Mon Sep 17 00:00:00 2001 From: Jason Kuhrt Date: Wed, 11 Dec 2024 13:53:46 -0500 Subject: [PATCH 10/10] lint --- benchmark/start-server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmark/start-server.ts b/benchmark/start-server.ts index 3c733c225f..79d66616bd 100644 --- a/benchmark/start-server.ts +++ b/benchmark/start-server.ts @@ -44,7 +44,7 @@ const yogaMap: Record = { parserAndValidationCache: false, graphqlEndpoint: '/graphql-no-parse-validate-cache', }), - '/ping': (req, res) => { + '/ping': (_, res) => { res.writeHead(200); res.end(); },