Skip to content

Commit

Permalink
[ESLint] enable promise/prefer-await-to-then for non React packages (
Browse files Browse the repository at this point in the history
…#3120)

Co-authored-by: Ted Thibodeau Jr <tthibodeau@openlinksw.com>
  • Loading branch information
dimaMachina and TallTed committed Apr 14, 2023
1 parent b901d61 commit 15c26eb
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 80 deletions.
9 changes: 9 additions & 0 deletions .changeset/tasty-glasses-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@graphiql/toolkit': patch
'graphql-language-service-server': patch
'monaco-graphql': patch
'vscode-graphql': patch
'vscode-graphql-execution': patch
---

prefer await to then
8 changes: 8 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -366,5 +366,13 @@ module.exports = {
'import/no-unresolved': ['error', { ignore: ['^node:', 'vscode'] }],
},
},
{
files: ['packages/**'],
// ignore React packages because it's ugly to have `async IIFE` inside `useEffect`
excludedFiles: ['packages/graphiql/**', 'packages/graphiql-react/**'],
rules: {
'promise/prefer-await-to-then': 'error',
},
},
],
};
54 changes: 23 additions & 31 deletions packages/graphiql-toolkit/src/async-helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,42 +52,34 @@ export function isAsyncIterable(
);
}

function asyncIterableToPromise<T>(
async function asyncIterableToPromise<T>(
input: AsyncIterable<T> | AsyncIterableIterator<T>,
): Promise<T> {
return new Promise((resolve, reject) => {
// Also support AsyncGenerator on Safari iOS.
// As mentioned in the isAsyncIterable function there is no Symbol.asyncIterator available
// so every AsyncIterable must be implemented using AsyncGenerator.
const iteratorReturn = (
'return' in input ? input : input[Symbol.asyncIterator]()
).return?.bind(input);
const iteratorNext = (
'next' in input ? input : input[Symbol.asyncIterator]()
).next.bind(input);
// Also support AsyncGenerator on Safari iOS.
// As mentioned in the isAsyncIterable function, there is no Symbol.asyncIterator available,
// so every AsyncIterable must be implemented using AsyncGenerator.
const iteratorReturn = (
'return' in input ? input : input[Symbol.asyncIterator]()
).return?.bind(input);
const iteratorNext = (
'next' in input ? input : input[Symbol.asyncIterator]()
).next.bind(input);

iteratorNext()
.then(result => {
resolve(result.value);
// ensure cleanup
void iteratorReturn?.();
})
.catch(err => {
reject(err);
});
});
const result = await iteratorNext();
// ensure cleanup
void iteratorReturn?.();
return result.value;
}

export function fetcherReturnToPromise(
export async function fetcherReturnToPromise(
fetcherResult: FetcherReturnType,
): Promise<FetcherResult> {
return Promise.resolve(fetcherResult).then(result => {
if (isAsyncIterable(result)) {
return asyncIterableToPromise(result);
}
if (isObservable(result)) {
return observableToPromise(result);
}
return result;
});
const result = await fetcherResult;
if (isAsyncIterable(result)) {
return asyncIterableToPromise(result);
}
if (isObservable(result)) {
return observableToPromise(result);
}
return result;
}
9 changes: 5 additions & 4 deletions packages/graphql-language-service-cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,21 +117,22 @@ if (command === 'server') {
});

const options: { [key: string]: any } = {};
if (argv?.port) {
if (argv.port) {
options.port = argv.port;
}
if (argv?.method) {
if (argv.method) {
options.method = argv.method;
}
if (argv?.configDir) {
if (argv.configDir) {
options.configDir = argv.configDir;
}
// eslint-disable-next-line promise/prefer-await-to-then -- don't know if I can use top level await here
startServer(options).catch(error => {
const logger = new Logger();
logger.error(String(error));
});
} else {
client(command as string, argv as { [key: string]: string });
client(command as string, argv as Record<string, string>);
}

// Exit the process when stream closes from remote end.
Expand Down
53 changes: 26 additions & 27 deletions packages/graphql-language-service-server/src/GraphQLCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -679,33 +679,32 @@ export class GraphQLCache implements GraphQLCacheInterface {
const responses: GraphQLFileInfo[] = [];
while (queue.length) {
const chunk = queue.splice(0, MAX_READS);
const promises = chunk.map(fileInfo =>
this.promiseToReadGraphQLFile(fileInfo.filePath)
.catch(error => {
// eslint-disable-next-line no-console
console.log('pro', error);
/**
* fs emits `EMFILE | ENFILE` error when there are too many
* open files - this can cause some fragment files not to be
* processed. Solve this case by implementing a queue to save
* files failed to be processed because of `EMFILE` error,
* and await on Promises created with the next batch from the
* queue.
*/
if (error.code === 'EMFILE' || error.code === 'ENFILE') {
queue.push(fileInfo);
}
})
.then((response: GraphQLFileInfo | void) => {
if (response) {
responses.push({
...response,
mtime: fileInfo.mtime,
size: fileInfo.size,
});
}
}),
);
const promises = chunk.map(async fileInfo => {
try {
const response = await this.promiseToReadGraphQLFile(
fileInfo.filePath,
);
responses.push({
...response,
mtime: fileInfo.mtime,
size: fileInfo.size,
});
} catch (error: any) {
// eslint-disable-next-line no-console
console.log('pro', error);
/**
* fs emits `EMFILE | ENFILE` error when there are too many
* open files - this can cause some fragment files not to be
* processed. Solve this case by implementing a queue to save
* files failed to be processed because of `EMFILE` error,
* and await on Promises created with the next batch from the
* queue.
*/
if (error.code === 'EMFILE' || error.code === 'ENFILE') {
queue.push(fileInfo);
}
}
});
await Promise.all(promises); // eslint-disable-line no-await-in-loop
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,10 +270,10 @@ describe('MessageProcessor', () => {
const params = { textDocument: initialDocument.textDocument, position };

// Should throw because file has been deleted from cache
return messageProcessor
.handleCompletionRequest(params)
.then(result => expect(result).toEqual(null))
.catch(() => {});
try {
const result = await messageProcessor.handleCompletionRequest(params);
expect(result).toEqual(null);
} catch {}
});

// modified to work with jest.mock() of WatchmanClient
Expand Down
7 changes: 3 additions & 4 deletions packages/graphql-language-service-server/src/startServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,22 +170,21 @@ export default async function startServer(

const { port, hostname } = options;
const socket = net
.createServer(client => {
.createServer(async client => {
client.setEncoding('utf8');
reader = new SocketMessageReader(client);
writer = new SocketMessageWriter(client);
client.on('end', () => {
socket.close();
process.exit(0);
});
return initializeHandlers({
const s = await initializeHandlers({
reader,
writer,
logger,
options: finalOptions,
}).then(s => {
s.listen();
});
s.listen();
})
.listen(port, hostname);
return;
Expand Down
2 changes: 2 additions & 0 deletions packages/monaco-graphql/src/initializeMode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export function initializeMode(
api = createMonacoGraphQLAPI(LANGUAGE_ID, config);
(<any>languages).graphql = { api };
// export to the global monaco API

// eslint-disable-next-line promise/prefer-await-to-then -- ignore to leave initializeMode sync
void getMode().then(mode => mode.setupMode(api));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,10 @@ export class GraphQLContentProvider implements TextDocumentContentProvider {
enableScripts: true,
};

this.loadProvider()
.then()
.catch(err => {
this.html = err.toString();
});
// eslint-disable-next-line promise/prefer-await-to-then -- can't use async in constructor
this.loadProvider().catch(err => {
this.html = err.toString();
});
}

validUrlFromSchema(pathOrUrl: string) {
Expand Down
12 changes: 7 additions & 5 deletions packages/vscode-graphql/src/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import { startServer } from 'graphql-language-service-server';
// The npm scripts are configured to only build this once before
// watching the extension, so please restart the extension debugger for changes!

const start = () => {
startServer({ method: 'node' }).catch(err => {
async function start() {
try {
await startServer({ method: 'node' });
} catch (err) {
// eslint-disable-next-line no-console
console.error(err);
});
};
}
}

start();
void start();

0 comments on commit 15c26eb

Please sign in to comment.