Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: use stricter typescript #3542

Merged
merged 10 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion benchmark/start-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const yogaMap: Record<string, RequestListener> = {
parserAndValidationCache: false,
graphqlEndpoint: '/graphql-no-parse-validate-cache',
}),
'/ping': (req, res) => {
'/ping': (_, res) => {
res.writeHead(200);
res.end();
},
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ describe('Yoga Apollo Link', () => {
let i = 0;
await new Promise<void>(resolve => {
const subscription = observable.subscribe((result: FetchResult) => {
collectedValues.push(result.data?.time);
collectedValues.push(result.data?.['time']);
i++;
if (i > 2) {
subscription.unsubscribe();
Expand Down
2 changes: 1 addition & 1 deletion packages/graphiql/src/YogaGraphiQL.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
});
Expand Down
2 changes: 1 addition & 1 deletion packages/graphiql/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"',
}
Expand Down
8 changes: 4 additions & 4 deletions packages/graphql-yoga/__integration-tests__/browser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export function createTestSchema() {
},
},
type: GraphQLString,
resolve: (_root, args) => args.text,
resolve: (_root, args) => args['text'],
},
hello: {
type: GraphQLString,
Expand Down Expand Up @@ -111,7 +111,7 @@ export function createTestSchema() {
},
type: GraphQLInt,
resolve: (_root, args) => {
return args.number;
return args['number'];
},
},
}),
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -231,7 +231,7 @@ describe('browser', () => {
await new Promise<void>(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'],
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<void>(resolve => server.close(() => resolve()));
Expand Down
4 changes: 2 additions & 2 deletions packages/graphql-yoga/__tests__/batching.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
});
6 changes: 3 additions & 3 deletions packages/graphql-yoga/__tests__/error-masking.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand All @@ -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;
}
});

Expand Down
4 changes: 3 additions & 1 deletion packages/graphql-yoga/__tests__/http-extensions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,9 @@ describe('Result Extensions', () => {
this.name = 'CustomError';
}

toJSON() {
// eslint-disable-next-line
// @ts-ignore - Only in graphql@^16 is `toJSON` a base method
/* override */ toJSON() {
return {
message: this.message,
extensions: { name: this.name, foo: 'bar' },
Expand Down
6 changes: 3 additions & 3 deletions packages/graphql-yoga/__tests__/logging.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,17 @@ 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();
logger.debug('TEST');

expect(console.debug).toHaveBeenCalled();
} finally {
process.env.DEBUG = originalValue;
process.env['DEBUG'] = originalValue;
}
});
});
Expand Down
2 changes: 1 addition & 1 deletion packages/graphql-yoga/__tests__/recipes.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ describe('recipe', () => {
resolvers: {
Query: {
id: (_, __, context: YogaInitialContext) => {
return context.params.extensions?.id;
return context.params.extensions?.['id'];
},
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 5 additions & 5 deletions packages/graphql-yoga/__tests__/requests.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe('requests', () => {
requestUrl: (_, __, ctx) => ctx.request.url,
},
Mutation: {
echo(root, args) {
echo(_, args) {
return args.str;
},
},
Expand Down Expand Up @@ -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: {
Expand All @@ -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,
);
});
});
26 changes: 18 additions & 8 deletions packages/graphql-yoga/scripts/generate-graphiql-html.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Copy link
Collaborator

@ardatan ardatan Dec 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typings might be wrong because if I remember correctly, it returns Buffer which has toString method that accepts an encoding type.

// 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() {
Expand Down
19 changes: 11 additions & 8 deletions packages/graphql-yoga/src/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function isAbortError(error: unknown): error is DOMException {
return (
typeof error === 'object' &&
error?.constructor?.name === 'DOMException' &&
(error as Record<string, unknown>).name === 'AbortError'
(error as DOMException).name === 'AbortError'
);
}

Expand Down Expand Up @@ -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;
}
}
Expand Down
5 changes: 4 additions & 1 deletion packages/graphql-yoga/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export async function parsePOSTJsonRequest(request: Request): Promise<GraphQLPar
},
};
if (err instanceof Error) {
extensions.originalError = {
extensions['originalError'] = {
name: err.name,
message: err.message,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export async function parsePOSTMultipartRequest(request: Request): Promise<Graph
}
for (const fileIndex in map) {
const file = requestBody.get(fileIndex);
const keys = map[fileIndex];
const keys = map[fileIndex]!;
for (const key of keys) {
dset(operations, key, file);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export function checkGraphQLQueryParams(

assertInvalidParams(params, extraParamNames);

if (params.query == null) {
if (params['query'] == null) {
throw createGraphQLError('Must provide query string.', {
extensions: {
http: {
Expand All @@ -73,7 +73,7 @@ export function checkGraphQLQueryParams(
});
}

const queryType = extendedTypeof(params.query);
const queryType = extendedTypeof(params['query']);
if (queryType !== 'string') {
throw createGraphQLError(`Expected "query" param to be a string, but given ${queryType}.`, {
extensions: {
Expand All @@ -87,7 +87,7 @@ export function checkGraphQLQueryParams(
});
}

const variablesParamType = extendedTypeof(params.variables);
const variablesParamType = extendedTypeof(params['variables']);
if (!['object', 'null', 'undefined'].includes(variablesParamType)) {
throw createGraphQLError(
`Expected "variables" param to be empty or an object, but given ${variablesParamType}.`,
Expand All @@ -104,7 +104,7 @@ export function checkGraphQLQueryParams(
);
}

const extensionsParamType = extendedTypeof(params.extensions);
const extensionsParamType = extendedTypeof(params['extensions']);
if (!['object', 'null', 'undefined'].includes(extensionsParamType)) {
throw createGraphQLError(
`Expected "extensions" param to be empty or an object, but given ${extensionsParamType}.`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export function usePreventMutationViaGET(): Plugin<YogaInitialContext> {

if (result instanceof Error) {
if (result instanceof GraphQLError) {
result.extensions.http = {
result.extensions['http'] = {
spec: true,
status: 400,
};
Expand Down
2 changes: 2 additions & 0 deletions packages/graphql-yoga/src/plugins/result-processor/accept.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ export function getMediaTypesForRequestInOrder(request: Request): string[] {
const mediaTypes: string[] = [];
for (const accept of accepts) {
const [mediaType, ...params] = accept.split(';');
if (mediaType === undefined) continue; // If true, malformed header.

const charset = params?.find(param => param.includes('charset=')) || 'charset=utf-8'; // utf-8 is assumed when not specified;

if (charset !== 'charset=utf-8') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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']),
),
);

Expand Down
2 changes: 1 addition & 1 deletion packages/graphql-yoga/src/plugins/result-processor/sse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
Loading
Loading