From 81e6dadc8d54f421e135ab4192f69557ab8dbb1b Mon Sep 17 00:00:00 2001 From: Sora Morimoto Date: Tue, 23 Apr 2024 12:24:54 +0900 Subject: [PATCH] Fix lint errors Signed-off-by: Sora Morimoto --- src/index.ts | 80 ++++++++++++++++----------------- src/parseCompilerLog.ts | 30 ++++++------- test/index.test.ts | 18 ++++---- test/parseCompilerLog.test.ts | 84 +++++++++++++++++------------------ tsup.config.ts | 6 +-- vitest.config.ts | 2 +- 6 files changed, 110 insertions(+), 110 deletions(-) diff --git a/src/index.ts b/src/index.ts index cce0ef7..f6eb381 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,14 +1,14 @@ -import * as path from 'path'; -import { existsSync } from 'fs'; -import * as fs from 'fs/promises'; -import { Plugin } from 'vite'; -import { execaCommand } from 'execa'; -import { npmRunPathEnv } from 'npm-run-path'; -import * as stream from 'stream'; -import chalk from 'chalk'; -import parseCompilerLog from './parseCompilerLog.js'; - -const logPrefix = chalk.cyan('[@jihchi/vite-plugin-rescript]'); +import { existsSync } from "node:fs"; +import * as fs from "node:fs/promises"; +import * as path from "node:path"; +import type * as stream from "node:stream"; +import chalk from "chalk"; +import { execaCommand } from "execa"; +import { npmRunPathEnv } from "npm-run-path"; +import type { Plugin } from "vite"; +import parseCompilerLog from "./parseCompilerLog.js"; + +const logPrefix = chalk.cyan("[@jihchi/vite-plugin-rescript]"); type ReScriptProcess = { shutdown: () => void; @@ -16,11 +16,11 @@ type ReScriptProcess = { async function launchReScript( watch: boolean, - silent: boolean + silent: boolean, ): Promise { const cmd = watch - ? 'rescript build -with-deps -w' - : 'rescript build -with-deps'; + ? "rescript build -with-deps -w" + : "rescript build -with-deps"; const result = execaCommand(cmd, { env: npmRunPathEnv(), @@ -38,14 +38,14 @@ async function launchReScript( // eslint-disable-next-line no-console console.log(logPrefix, output); } - if (watch && output.includes('>>>> Finish compiling')) { + if (watch && output.includes(">>>> Finish compiling")) { compileOnce(true); } } const { stdout, stderr } = result; - stdout && stdout.on('data', dataListener); - stderr && stderr.on('data', dataListener); + stdout?.on("data", dataListener); + stderr?.on("data", dataListener); if (watch) { await new Promise((resolve) => { @@ -78,14 +78,14 @@ export default function createReScriptPlugin(config?: Config): Plugin { let childProcessReScript: undefined | ReScriptProcess; // Retrieve config - const output = config?.loader?.output ?? './lib/es6'; - const suffix = config?.loader?.suffix ?? '.bs.js'; - const suffixRegex = new RegExp(`${suffix.replace('.', '\\.')}$`); + const output = config?.loader?.output ?? "./lib/es6"; + const suffix = config?.loader?.suffix ?? ".bs.js"; + const suffixRegex = new RegExp(`${suffix.replace(".", "\\.")}$`); const silent = config?.silent ?? false; return { - name: '@jihchi/vite-plugin-rescript', - enforce: 'pre', + name: "@jihchi/vite-plugin-rescript", + enforce: "pre", async configResolved(resolvedConfig) { root = resolvedConfig.root; @@ -93,16 +93,16 @@ export default function createReScriptPlugin(config?: Config): Plugin { // exclude "vite preview [--mode ]" const isOnlyDevServerLaunching = - command === 'serve' && !inlineConfig.hasOwnProperty('preview'); + command === "serve" && !Object.hasOwn(inlineConfig, "preview"); - const isBuildForProduction = command === 'build'; + const isBuildForProduction = command === "build"; const needReScript = isOnlyDevServerLaunching || isBuildForProduction; // The watch command can only be run by one process at the same time. - const isLocked = existsSync(path.resolve('./.bsb.lock')); + const isLocked = existsSync(path.resolve("./.bsb.lock")); - const watch = !isLocked && (command === 'serve' || Boolean(build.watch)); + const watch = !isLocked && (command === "serve" || Boolean(build.watch)); if (needReScript) { childProcessReScript = await launchReScript(watch, silent); @@ -113,32 +113,32 @@ export default function createReScriptPlugin(config?: Config): Plugin { // If the build watcher is enabled (adding watch config would automatically enable it), // exclude rescript files since recompilation should be based on the generated JS files. watch: userConfig.build?.watch - ? { exclude: ['**/*.res', '**/*.resi'] } + ? { exclude: ["**/*.res", "**/*.resi"] } : null, }, server: { watch: { // Ignore rescript files when watching since they may occasionally trigger hot update - ignored: ['**/*.res', '**/*.resi'], + ignored: ["**/*.res", "**/*.resi"], }, }, }), configureServer(server) { // Manually find and parse log file after server start since // initial compilation does not trigger handleHotUpdate. - fs.readFile(path.resolve('./lib/bs/.compiler.log'), 'utf8').then( + fs.readFile(path.resolve("./lib/bs/.compiler.log"), "utf8").then( (data) => { const log = data.toString(); const err = parseCompilerLog(log); - if (err) server.hot.send({ type: 'error', err }); - } + if (err) server.hot.send({ type: "error", err }); + }, ); }, // Hook that resolves `.bs.js` imports to their `.res` counterpart async resolveId(source, importer, options) { - if (source.endsWith('.res')) usingLoader = true; + if (source.endsWith(".res")) usingLoader = true; if (options.isEntry || !importer) return null; - if (!importer.endsWith('.res')) return null; + if (!importer.endsWith(".res")) return null; if (!source.endsWith(suffix)) return null; if (path.isAbsolute(source)) return null; @@ -154,7 +154,7 @@ export default function createReScriptPlugin(config?: Config): Plugin { } // Only replace the last occurrence - const resFile = source.replace(suffixRegex, '.res'); + const resFile = source.replace(suffixRegex, ".res"); const id = path.join(dirname, resFile); // Enable other plugins to resolve the file @@ -174,7 +174,7 @@ export default function createReScriptPlugin(config?: Config): Plugin { }, // Hook that loads the generated `.bs.js` file from `lib/es6` for ReScript files async load(id) { - if (!id.endsWith('.res')) return null; + if (!id.endsWith(".res")) return null; // Find the path to the generated js file const relativePath = path.relative(root, id); @@ -186,7 +186,7 @@ export default function createReScriptPlugin(config?: Config): Plugin { this.addWatchFile(filePath); // Read the file content and return the code - return { code: await fs.readFile(filePath, 'utf8') }; + return { code: await fs.readFile(filePath, "utf8") }; }, async handleHotUpdate({ file, read, server }) { // HMR is not automatically triggered when using the ReScript file loader. @@ -195,15 +195,15 @@ export default function createReScriptPlugin(config?: Config): Plugin { if (usingLoader && file.endsWith(suffix)) { const lib = path.resolve(output); const relativePath = path.relative(lib, file); - if (relativePath.startsWith('..')) return; - const resFile = relativePath.replace(suffixRegex, '.res'); + if (relativePath.startsWith("..")) return; + const resFile = relativePath.replace(suffixRegex, ".res"); const id = path.join(root, resFile); const moduleNode = server.moduleGraph.getModuleById(id); if (moduleNode) return [moduleNode]; - } else if (file.endsWith('.compiler.log')) { + } else if (file.endsWith(".compiler.log")) { const log = await read(); const err = parseCompilerLog(log); - if (err) server.hot.send({ type: 'error', err }); + if (err) server.hot.send({ type: "error", err }); } return; diff --git a/src/parseCompilerLog.ts b/src/parseCompilerLog.ts index 5b7b8cb..6f74470 100644 --- a/src/parseCompilerLog.ts +++ b/src/parseCompilerLog.ts @@ -1,13 +1,13 @@ -import { ErrorPayload } from 'vite'; -import { EOL } from 'os'; +import { EOL } from "node:os"; +import type { ErrorPayload } from "vite"; -const ruler = '—'.repeat(80); +const ruler = "—".repeat(80); // https://github.com/rescript-lang/rescript-vscode/blob/7ab2d231f91fee2f93cbf6cae1b38f94c06a58c1/server/src/utils.ts#L288 const fileAndRangeRegex = /(.+):(\d+):(\d+)(-(\d+)(:(\d+))?)?$/; // https://github.com/rescript-lang/rescript-vscode/blob/7ab2d231f91fee2f93cbf6cae1b38f94c06a58c1/server/src/utils.ts#L433 -const codeRegex = /^ +([0-9]+| +|\.) (│|┆)/; +const codeRegex = /^ {2,}([0-9]+| +|\.) (│|┆)/; // Compiler can treat warnings as hard errors based on `warnings` object in bsconfig.json const warningErrorRegex = /Warning number \d+ \(configured as error\)/; @@ -15,7 +15,7 @@ const warningErrorRegex = /Warning number \d+ \(configured as error\)/; // Returns true if the line indicates the start of an error block function isErrorLine(line: string | undefined) { if (line?.startsWith(" We've found a bug for you!")) return true; - if (line?.startsWith(' Syntax error!')) return true; + if (line?.startsWith(" Syntax error!")) return true; if (line && warningErrorRegex.test(line)) return true; return false; } @@ -26,13 +26,13 @@ function isErrorLine(line: string | undefined) { * @returns Error object to send to the client or null. */ export default function parseCompilerLog( - log: string -): ErrorPayload['err'] | null { + log: string, +): ErrorPayload["err"] | null { // Split by line endings and remove empty lines const lines = log.split(EOL).filter(Boolean); // Optimization; only parse log when compiler is done - if (lines[lines.length - 1]?.startsWith('#Done(')) { + if (lines[lines.length - 1]?.startsWith("#Done(")) { let foundError = false; let path: string | undefined; let startLine = 0; @@ -68,10 +68,10 @@ export default function parseCompilerLog( i += 1; } else if (!foundError) { // Only run below checks once an error has been found - } else if (line?.startsWith(' Warning number ')) { + } else if (line?.startsWith(" Warning number ")) { // Reached the end of the error break; - } else if (line?.startsWith('#Done(')) { + } else if (line?.startsWith("#Done(")) { // Reached the end of the log file break; } else { @@ -81,7 +81,7 @@ export default function parseCompilerLog( // Replace strange vertical bars with regular ones in order to match // the code frame regex defined in the vite overlay file: // https://github.com/vitejs/vite/blob/96591bf9989529de839ba89958755eafe4c445ae/packages/vite/src/client/overlay.ts#L116 - let codeFrameLine = line?.replace('┆', '|').replace('│', '|'); + let codeFrameLine = line?.replace("┆", "|").replace("│", "|"); // Since the red color indicator is lost when parsing the log file, // this adds a pointer (`>`) to the line where the error starts. @@ -92,7 +92,7 @@ export default function parseCompilerLog( if (codeFrameLine) { frame.push(codeFrameLine); } - } else if (line?.startsWith(' ')) { + } else if (line?.startsWith(" ")) { // It has to be a message by now messages.push(line.trim()); } @@ -101,9 +101,9 @@ export default function parseCompilerLog( if (foundError) { return { - message: messages.join('\n'), - frame: `${frame.join('\n')}`, - stack: '', + message: messages.join("\n"), + frame: `${frame.join("\n")}`, + stack: "", id: path, }; } diff --git a/test/index.test.ts b/test/index.test.ts index 60474f6..2efa248 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -1,20 +1,20 @@ -import { describe, expect, it } from 'vitest'; -import Plugin from '../src/index.js'; +import { describe, expect, it } from "vitest"; +import Plugin from "../src/index.js"; -describe('@jihchi/vite-plugin-rescript', () => { - it('works', () => { +describe("@jihchi/vite-plugin-rescript", () => { + it("works", () => { const actual = Plugin(); - expect(actual).toHaveProperty('name', '@jihchi/vite-plugin-rescript'); - expect(actual).toHaveProperty('configResolved'); + expect(actual).toHaveProperty("name", "@jihchi/vite-plugin-rescript"); + expect(actual).toHaveProperty("configResolved"); expect(actual.configResolved).toBeInstanceOf(Function); }); - it('invokes closeBundle hook without crashing', async () => { + it("invokes closeBundle hook without crashing", async () => { const actual = Plugin(); - expect(actual).toHaveProperty('closeBundle'); + expect(actual).toHaveProperty("closeBundle"); await expect( // @ts-expect-error - actual.closeBundle() + actual.closeBundle(), ).resolves.toEqual(undefined); }); }); diff --git a/test/parseCompilerLog.test.ts b/test/parseCompilerLog.test.ts index 988bd23..24d2a55 100644 --- a/test/parseCompilerLog.test.ts +++ b/test/parseCompilerLog.test.ts @@ -1,9 +1,9 @@ -import { EOL } from 'os'; -import { describe, expect, it } from 'vitest'; -import parseCompilerLog from '../src/parseCompilerLog.js'; +import { EOL } from "node:os"; +import { describe, expect, it } from "vitest"; +import parseCompilerLog from "../src/parseCompilerLog.js"; -const start = '#Start(1638790229265)'; -const done = '#Done(1638790229437)'; +const start = "#Start(1638790229265)"; +const done = "#Done(1638790229437)"; const warning = ` Warning number 27 @@ -106,101 +106,101 @@ function expectParseCompilerLog(...sections: string[]) { return expect(parseCompilerLog(sections.join(EOL).replace(/\n/g, EOL))); } -describe('@jihchi/vite-plugin-rescript/overlay', () => { - it('returns null for empty string', () => { - expectParseCompilerLog('').toBe(null); +describe("@jihchi/vite-plugin-rescript/overlay", () => { + it("returns null for empty string", () => { + expectParseCompilerLog("").toBe(null); }); - it('returns null when compiler has just started', () => { + it("returns null when compiler has just started", () => { expectParseCompilerLog(start).toBe(null); }); - it('returns null when compiler is not yet done', () => { + it("returns null when compiler is not yet done", () => { expectParseCompilerLog(start, error).toBe(null); }); - it('returns null when compiler log contains no errors', () => { + it("returns null when compiler log contains no errors", () => { expectParseCompilerLog(start, done).toBe(null); }); - it('returns null when compiler log contains only warning', () => { + it("returns null when compiler log contains only warning", () => { expectParseCompilerLog(start, warning, done).toBe(null); }); - it('returns error when compiler log contains error', () => { + it("returns error when compiler log contains error", () => { expectParseCompilerLog(start, error, done).toEqual({ message: "The value whoops can't be found", - stack: '', - id: '/path/to/file.res:3:3-8', + stack: "", + id: "/path/to/file.res:3:3-8", frame: errorFrame, }); }); - it('returns error when compiler log contains syntax error', () => { + it("returns error when compiler log contains syntax error", () => { expectParseCompilerLog(start, syntaxError, done).toEqual({ - message: 'Did you forget a `]` here?', - stack: '', - id: '/path/to/file.res:3:20', + message: "Did you forget a `]` here?", + stack: "", + id: "/path/to/file.res:3:20", frame: syntaxErrorFrame, }); }); - it('returns error when compiler log contains warning configured as error', () => { + it("returns error when compiler log contains warning configured as error", () => { expectParseCompilerLog(start, warningError, done).toEqual({ - message: 'unused variable status.', - stack: '', - id: '/path/to/file.res:2:13-18', + message: "unused variable status.", + stack: "", + id: "/path/to/file.res:2:13-18", frame: warningErrorFrame, }); }); - it('returns error without frame pointer when path has no location', () => { + it("returns error without frame pointer when path has no location", () => { expectParseCompilerLog(start, ppxError, done).toEqual({ - message: 'Something went wrong...', - stack: '', - id: '/path/to/file.res', + message: "Something went wrong...", + stack: "", + id: "/path/to/file.res", frame: ppxErrorFrame, }); }); - it('returns error when compiler log contains error and warning', () => { + it("returns error when compiler log contains error and warning", () => { expectParseCompilerLog(start, error, warning, done).toEqual({ message: "The value whoops can't be found", - stack: '', - id: '/path/to/file.res:3:3-8', + stack: "", + id: "/path/to/file.res:3:3-8", frame: errorFrame, }); }); - it('returns error when compiler log contains error with odd vertical bars', () => { + it("returns error when compiler log contains error with odd vertical bars", () => { expectParseCompilerLog( start, - error.replace('│', '┆'), + error.replace("│", "┆"), warning, - done + done, ).toEqual({ message: "The value whoops can't be found", - stack: '', - id: '/path/to/file.res:3:3-8', + stack: "", + id: "/path/to/file.res:3:3-8", frame: errorFrame, }); }); - it('returns only the first error', () => { + it("returns only the first error", () => { expectParseCompilerLog(start, error, syntaxError, done).toEqual({ message: "The value whoops can't be found", - stack: '', - id: '/path/to/file.res:3:3-8', + stack: "", + id: "/path/to/file.res:3:3-8", frame: errorFrame, }); }); - it('returns error with multiple messages', () => { - const hint = ' Did you mean whooops?'; + it("returns error with multiple messages", () => { + const hint = " Did you mean whooops?"; expectParseCompilerLog(start, error, hint, done).toEqual({ message: "The value whoops can't be found\nDid you mean whooops?", - stack: '', - id: '/path/to/file.res:3:3-8', + stack: "", + id: "/path/to/file.res:3:3-8", frame: errorFrame, }); }); diff --git a/tsup.config.ts b/tsup.config.ts index 9f5437c..4a11a49 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -1,8 +1,8 @@ -import { defineConfig } from 'tsup'; +import { defineConfig } from "tsup"; export default defineConfig({ - entry: ['src/index.ts'], - format: ['cjs', 'esm'], + entry: ["src/index.ts"], + format: ["cjs", "esm"], clean: true, dts: true, }); diff --git a/vitest.config.ts b/vitest.config.ts index e2131ea..428c8d6 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -1,5 +1,5 @@ /// -import { defineConfig } from 'vite'; +import { defineConfig } from "vite"; export default defineConfig({ test: {},