docs/internals/linters.mdx
Flipper Desktop comes with a variety of ESLint checks pre-enabled, which enable us to enforce sustainable coding practices and skip over discussions in code reviews.
This section contains an incomplete list of unusual linters we deploy, why we use them, and how to fix them (where relevant).
promise/no-nestingBefore
private pushFileToiOSDevice(
udid: string,
bundleId: string,
destination: string,
filename: string,
contents: string,
): Promise<void> {
return tmpDir({unsafeCleanup: true}).then((dir) => {
const filePath = path.resolve(dir, filename);
promisify(fs.writeFile)(filePath, contents).then(() =>
iosUtil.push(
udid,
filePath,
bundleId,
destination,
this.config.idbPath,
),
);
});
}
After
async pushFileToiOSDevice(
udid: string,
bundleId: string,
destination: string,
filename: string,
contents: string,
): Promise<void> {
const dir = await tmpDir({unsafeCleanup: true});
const filePath = path.resolve(dir, filename);
await fs.writeFile(filePath, contents);
return iosUtil.push(
udid,
filePath,
bundleId,
destination,
this.config.idbPath,
);
}
In addition to less indentation, you also maintain the promise chain here, meaning that you can handle potential errors on the call-side.
flipper/no-console-error-without-contextconsole.error("Failed to connect open iOS connection socket", e) to console.error(e).console.error call. It can be hard to find the origin of the error without context.Before
try {
// ...
} catch (e) {
console.error(e);
}
After
try {
// ...
} catch (e) {
console.error(`Failed to connect to paste host ${hostname}`, e);
}
promise/catch-or-returnthen() is applied to a promise, a catch() is applied as well. Exceptions are made if you are returning that promise. For more details, see catch-or-return.md on GitHub.Before
function request() {
// If fetch() fails, the exception will bubble to the top.
fetch("https://example.com").then(res => {
doSomethingWith(res);
});
}
After
// Option 1
function request() {
fetch("https://example.com").then(res => {
doSomethingWith(res);
}).catch((e) => {
console.error("Failed to fetch from example.com", e);
});
}
// Option 2
function request() {
// Allow the call-site to handle the error.
return fetch("https://example.com").then(res => {
doSomethingWith(res);
});
}
communist-spelling/communist-spellingconst greyColour = COLORS.GRAY; is something nobody should have to read or write.Before
const GreyedOutOverlay = initialiseComponent();
After
const GrayedOutOverlay = initializeComponent();
node/no-syncfs.existsSync() can cause frame drops for users or even long stalls.fs-extra as a dependency, which provides Promise-based alternatives for all fs functions. Most often, replacing a sync call with an async call and adding an await is all that's needed.Before
import fs from 'fs';
function ensureCertsExist() {
if (
!(
fs.existsSync(serverKey) &&
fs.existsSync(serverCert) &&
fs.existsSync(caCert)
)
) {
return generateServerCertificate();
}
}
After
import fsExtra from 'fs-extra';
async function ensureCertsExist() {
const allExist = Promise.all([
fsExtra.exists(serverKey),
fsExtra.exists(serverCert),
fsExtra.exists(caCert),
]).then((exist) => exist.every(Boolean));
if (!allExist) {
return this.generateServerCertificate();
}
}