diff --git a/package.json b/package.json index 4a6e012b..bed1cc67 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "prettier": "3.6.2", "temp-dir": "^3.0.0", "typescript": "^5.9.3", - "typescript-eslint": "^8.46.2", + "typescript-eslint": "^8.49.0", "vitest": "^4.0.6" }, "packageManager": "yarn@4.10.3" diff --git a/src/execute/create-temporary-directory.ts b/src/execute/create-temporary-directory.ts index 90979382..5c449b9a 100644 --- a/src/execute/create-temporary-directory.ts +++ b/src/execute/create-temporary-directory.ts @@ -1,27 +1,29 @@ -import fs from 'node:fs/promises' -import os from 'node:os' -import path from 'node:path'; -import crypto from "node:crypto"; - -export async function createTemporaryDirectory() { - const directory = path.join( - // The following quoted from https://github.com/es-tooling/module-replacements/blob/27d1acd38f19741e31d2eae561a5c8a914373fc5/docs/modules/tempy.md?plain=1#L20-L21, not sure if it's true - // MacOS and possibly some other platforms return a symlink from `os.tmpdir`. - // For some applications, this can cause problems; thus, we use `realpath`. - await fs.realpath(os.tmpdir()), - crypto.randomBytes(16).toString("hex"), - ); - - fs.mkdir(directory); - - return { - path: directory, - dispatch: () => destroyTemporaryDirectory(directory) - }; -} - -async function destroyTemporaryDirectory(directory: string) { - await fs.rm(directory, {recursive: true, force: true}) -} - -export type TemporaryDirectory = Awaited> \ No newline at end of file +import fs from "node:fs/promises"; +import os from "node:os"; +import path from "node:path"; +import crypto from "node:crypto"; + +export async function createTemporaryDirectory() { + const directory = path.join( + // The following quoted from https://github.com/es-tooling/module-replacements/blob/27d1acd38f19741e31d2eae561a5c8a914373fc5/docs/modules/tempy.md?plain=1#L20-L21, not sure if it's true + // MacOS and possibly some other platforms return a symlink from `os.tmpdir`. + // For some applications, this can cause problems; thus, we use `realpath`. + await fs.realpath(os.tmpdir()), + crypto.randomBytes(16).toString("hex"), + ); + + fs.mkdir(directory); + + return { + path: directory, + dispatch: () => destroyTemporaryDirectory(directory), + }; +} + +async function destroyTemporaryDirectory(directory: string) { + await fs.rm(directory, { recursive: true, force: true }); +} + +export type TemporaryDirectory = Awaited< + ReturnType +>; diff --git a/src/execute/index.ts b/src/execute/index.ts index 0937f38f..505241be 100644 --- a/src/execute/index.ts +++ b/src/execute/index.ts @@ -6,7 +6,7 @@ import * as configuration from "../configuration.ts"; import * as git from "../tools/git.ts"; import * as logger from "../logger.ts"; import { getProjects, getTargetRepositoryPath } from "../projects.ts"; -import {installPrettier} from './install-prettier.ts' +import { installPrettier } from "./install-prettier.ts"; export interface ExecuteResultEntry { commitHash: string; @@ -42,7 +42,7 @@ export async function execute({ }), ); - await originalPrettier.dispatch() + await originalPrettier.dispatch(); // Setup alternativeVersionPrettier await logger.log("Setting up alternativeVersionPrettier..."); @@ -54,7 +54,7 @@ export async function execute({ await runPrettier(alternativePrettier, project); }), ); - await alternativePrettier.dispatch() + await alternativePrettier.dispatch(); const diffs = await Promise.all( projects.map(getTargetRepositoryPath).map(git.diffRepository), diff --git a/src/execute/install-prettier.ts b/src/execute/install-prettier.ts index b8924492..67fc289f 100644 --- a/src/execute/install-prettier.ts +++ b/src/execute/install-prettier.ts @@ -1,67 +1,67 @@ -import path from "node:path"; -import { - PrettierVersion, - PrettierPullRequest, - sourceTypes -} from "../parse.ts"; -import * as configuration from "../configuration.ts"; -import * as brew from "../tools/brew.ts"; -import * as gh from "../tools/gh.ts"; -import * as yarn from "../tools/yarn.ts"; -import * as npm from "../tools/npm.ts"; -import * as unix from "../tools/unix.ts"; -import {createTemporaryDirectory, type TemporaryDirectory} from './create-temporary-directory.ts' - -export type InstalledPrettier = Awaited> - -export async function installPrettier( - prettierVersion: PrettierVersion, -) { - let version: string - let pullRequestDirectory: TemporaryDirectory | undefined - if (prettierVersion.type === sourceTypes.pullRequest) { - ({version, directory: pullRequestDirectory} = await getPullRequest(prettierVersion.number) ) - } else { - ({version} = prettierVersion) - } - - - const directory = await createTemporaryDirectory() - const {path: cwd} = directory - await yarn.init(['-y'], {cwd}) - await yarn.add([`prettier@${version}`],{cwd}) - - await pullRequestDirectory?.dispatch() - - return { - dispatch: () => {directory.dispatch()}, - bin: path.join(cwd, 'node_modules/prettier/bin/prettier.cjs'), - name: prettierVersion.raw - } -} - -async function existsGh() { - return !(await unix.which("gh")).includes("gh not found"); -} - -async function getPullRequest( - pullRequestNumber: PrettierPullRequest['number'], -) { - if (!(await existsGh())) { - await brew.install("gh"); - } - if (configuration.authToken !== "nothing") { - // running locally, `gh` can be already authenticated - await gh.authLoginWithToken(configuration.authToken); - } - - const directory = await createTemporaryDirectory() - - await gh.prCheckout(pullRequestNumber, directory.path); - const {stdout} = await npm.pack({cwd: directory.path}); - - return { - directory, - version: `file:${path.join(directory.path, stdout.trim())}` - }; -} +import path from "node:path"; +import { PrettierVersion, PrettierPullRequest, sourceTypes } from "../parse.ts"; +import * as configuration from "../configuration.ts"; +import * as brew from "../tools/brew.ts"; +import * as gh from "../tools/gh.ts"; +import * as yarn from "../tools/yarn.ts"; +import * as npm from "../tools/npm.ts"; +import * as unix from "../tools/unix.ts"; +import { + createTemporaryDirectory, + type TemporaryDirectory, +} from "./create-temporary-directory.ts"; + +export type InstalledPrettier = Awaited>; + +export async function installPrettier(prettierVersion: PrettierVersion) { + let version: string; + let pullRequestDirectory: TemporaryDirectory | undefined; + if (prettierVersion.type === sourceTypes.pullRequest) { + ({ version, directory: pullRequestDirectory } = await getPullRequest( + prettierVersion.number, + )); + } else { + ({ version } = prettierVersion); + } + + const directory = await createTemporaryDirectory(); + const { path: cwd } = directory; + await yarn.init(["-y"], { cwd }); + await yarn.add([`prettier@${version}`], { cwd }); + + await pullRequestDirectory?.dispatch(); + + return { + dispatch: () => { + directory.dispatch(); + }, + bin: path.join(cwd, "node_modules/prettier/bin/prettier.cjs"), + name: prettierVersion.raw, + }; +} + +async function existsGh() { + return !(await unix.which("gh")).includes("gh not found"); +} + +async function getPullRequest( + pullRequestNumber: PrettierPullRequest["number"], +) { + if (!(await existsGh())) { + await brew.install("gh"); + } + if (configuration.authToken !== "nothing") { + // running locally, `gh` can be already authenticated + await gh.authLoginWithToken(configuration.authToken); + } + + const directory = await createTemporaryDirectory(); + + await gh.prCheckout(pullRequestNumber, directory.path); + const { stdout } = await npm.pack({ cwd: directory.path }); + + return { + directory, + version: `file:${path.join(directory.path, stdout.trim())}`, + }; +} diff --git a/src/execute/run-prettier.ts b/src/execute/run-prettier.ts index 8c522873..b1453872 100644 --- a/src/execute/run-prettier.ts +++ b/src/execute/run-prettier.ts @@ -2,7 +2,7 @@ import path from "path"; import spawn from "nano-spawn"; import { type Project, getTargetRepositoryPath } from "../projects.ts"; import * as yarn from "../tools/yarn.ts"; -import {type InstalledPrettier} from './install-prettier.ts' +import { type InstalledPrettier } from "./install-prettier.ts"; export async function runPrettier( prettier: InstalledPrettier, diff --git a/src/parse.ts b/src/parse.ts index f90d0a21..a9014d5a 100644 --- a/src/parse.ts +++ b/src/parse.ts @@ -1,24 +1,21 @@ export const sourceTypes = { - pullRequest: 'pull-request', - package: 'package', + pullRequest: "pull-request", + package: "package", } as const; export interface PrettierPackage { type: typeof sourceTypes.package; - version: string, + version: string; raw?: string; } export interface PrettierPullRequest { type: typeof sourceTypes.pullRequest; - number: string, + number: string; raw?: string; } - -export type PrettierVersion = - | PrettierPackage - | PrettierPullRequest; +export type PrettierVersion = PrettierPackage | PrettierPullRequest; export type Project = { repositoryUrl: string; @@ -38,8 +35,7 @@ export function parse(source: string): Command { const tokens = tokenize(source); let alternativePrettier: PrettierVersion | undefined = undefined; - let originalPrettier: PrettierVersion = - defaultPrettierRepositorySource; + let originalPrettier: PrettierVersion = defaultPrettierRepositorySource; for (const [index, token] of tokenize(source).entries()) { const lookahead = (): Token => { @@ -99,7 +95,7 @@ export function parseRepositorySource(token: Token): PrettierVersion { throw new Error(`Unexpected token '${token.kind}', expect 'source'.`); } - const raw = token.value + const raw = token.value; // like "#3465" if (/^#\d+$/.test(raw)) { @@ -112,10 +108,10 @@ export function parseRepositorySource(token: Token): PrettierVersion { // Any source yarn accepts https://yarnpkg.com/cli/add // `sosukesuzuki/prettier#ref`, `3.0.0`, ... and so on - const packagePrefix = 'prettier@' - let version = raw + const packagePrefix = "prettier@"; + let version = raw; if (version.startsWith(packagePrefix)) { - version = version.slice(packagePrefix.length) + version = version.slice(packagePrefix.length); } return { diff --git a/src/tools/npm.ts b/src/tools/npm.ts index 013a8059..333d7438 100644 --- a/src/tools/npm.ts +++ b/src/tools/npm.ts @@ -1,5 +1,5 @@ -import spawn, {type Subprocess, type Options} from "nano-spawn"; - -export async function pack(options: Options): Promise { - return await spawn("npm", ['pack'], options); -} +import spawn, { type Subprocess, type Options } from "nano-spawn"; + +export async function pack(options: Options): Promise { + return await spawn("npm", ["pack"], options); +} diff --git a/src/tools/yarn.ts b/src/tools/yarn.ts index a8442d56..07e51e1e 100644 --- a/src/tools/yarn.ts +++ b/src/tools/yarn.ts @@ -1,13 +1,13 @@ -import spawn, {type Options} from "nano-spawn"; +import spawn, { type Options } from "nano-spawn"; export async function install(cwd: string): Promise { await spawn("yarn", [], { cwd }); } -export async function init(args: string [] ,options: Options): Promise { - await spawn("yarn", ['init',...args], options); +export async function init(args: string[], options: Options): Promise { + await spawn("yarn", ["init", ...args], options); } -export async function add(args: string [] ,options: Options): Promise { - await spawn("yarn", ['add',...args], options); +export async function add(args: string[], options: Options): Promise { + await spawn("yarn", ["add", ...args], options); } diff --git a/yarn.lock b/yarn.lock index e4b365d2..d21aa256 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1252,7 +1252,27 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:8.46.2, @typescript-eslint/eslint-plugin@npm:^8.46.2": +"@typescript-eslint/eslint-plugin@npm:8.49.0": + version: 8.49.0 + resolution: "@typescript-eslint/eslint-plugin@npm:8.49.0" + dependencies: + "@eslint-community/regexpp": "npm:^4.10.0" + "@typescript-eslint/scope-manager": "npm:8.49.0" + "@typescript-eslint/type-utils": "npm:8.49.0" + "@typescript-eslint/utils": "npm:8.49.0" + "@typescript-eslint/visitor-keys": "npm:8.49.0" + ignore: "npm:^7.0.0" + natural-compare: "npm:^1.4.0" + ts-api-utils: "npm:^2.1.0" + peerDependencies: + "@typescript-eslint/parser": ^8.49.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/f5a6ac622bebad31e6e561caa2e7364bac82e259d487e1832f90c41040c856ed360891c710098f43d3541a17703a429ef023b0f5bb573cc05ee52200096f252f + languageName: node + linkType: hard + +"@typescript-eslint/eslint-plugin@npm:^8.46.2": version: 8.46.2 resolution: "@typescript-eslint/eslint-plugin@npm:8.46.2" dependencies: @@ -1273,7 +1293,23 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/parser@npm:8.46.2, @typescript-eslint/parser@npm:^8.46.2": +"@typescript-eslint/parser@npm:8.49.0": + version: 8.49.0 + resolution: "@typescript-eslint/parser@npm:8.49.0" + dependencies: + "@typescript-eslint/scope-manager": "npm:8.49.0" + "@typescript-eslint/types": "npm:8.49.0" + "@typescript-eslint/typescript-estree": "npm:8.49.0" + "@typescript-eslint/visitor-keys": "npm:8.49.0" + debug: "npm:^4.3.4" + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/749e6244497f2b617351cce4ae520bc101c948b1c94c28e3bc4c5861eb999ada3b4be5dfad36a377a75675998a27d24c5ffba23ff2af743e2b4c4530f68b2673 + languageName: node + linkType: hard + +"@typescript-eslint/parser@npm:^8.46.2": version: 8.46.2 resolution: "@typescript-eslint/parser@npm:8.46.2" dependencies: @@ -1302,6 +1338,19 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/project-service@npm:8.49.0": + version: 8.49.0 + resolution: "@typescript-eslint/project-service@npm:8.49.0" + dependencies: + "@typescript-eslint/tsconfig-utils": "npm:^8.49.0" + "@typescript-eslint/types": "npm:^8.49.0" + debug: "npm:^4.3.4" + peerDependencies: + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/da6342fe99786c9d9c1d2fc3291ffd62afa043b42f4c7b5c1f8b3a6af266bd9af662281a0905ee70b069a811b63faf7efb63932f6bf55cb138e42309e4ced425 + languageName: node + linkType: hard + "@typescript-eslint/scope-manager@npm:8.46.2": version: 8.46.2 resolution: "@typescript-eslint/scope-manager@npm:8.46.2" @@ -1312,6 +1361,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/scope-manager@npm:8.49.0": + version: 8.49.0 + resolution: "@typescript-eslint/scope-manager@npm:8.49.0" + dependencies: + "@typescript-eslint/types": "npm:8.49.0" + "@typescript-eslint/visitor-keys": "npm:8.49.0" + checksum: 10c0/fe7a036e186e8cb933375ecc3b6ea8ce7604f1dd53d72c24d26158cbc2563527f8c1ba7a894b58bcbd079315fe950ff3c5eb5f7061658f39ff473c04d54ef701 + languageName: node + linkType: hard + "@typescript-eslint/tsconfig-utils@npm:8.46.2, @typescript-eslint/tsconfig-utils@npm:^8.46.2": version: 8.46.2 resolution: "@typescript-eslint/tsconfig-utils@npm:8.46.2" @@ -1321,6 +1380,15 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/tsconfig-utils@npm:8.49.0, @typescript-eslint/tsconfig-utils@npm:^8.49.0": + version: 8.49.0 + resolution: "@typescript-eslint/tsconfig-utils@npm:8.49.0" + peerDependencies: + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/1b255149d3f0d99b6cf5df4b62925a79f44f243748c6e877a7cf1dd0cdbff7411f2971d5e9fa85472ed76055bd1826e55c1adc99f3d82f504bd9fcd6e76f4b3a + languageName: node + linkType: hard + "@typescript-eslint/type-utils@npm:8.46.2": version: 8.46.2 resolution: "@typescript-eslint/type-utils@npm:8.46.2" @@ -1337,6 +1405,22 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/type-utils@npm:8.49.0": + version: 8.49.0 + resolution: "@typescript-eslint/type-utils@npm:8.49.0" + dependencies: + "@typescript-eslint/types": "npm:8.49.0" + "@typescript-eslint/typescript-estree": "npm:8.49.0" + "@typescript-eslint/utils": "npm:8.49.0" + debug: "npm:^4.3.4" + ts-api-utils: "npm:^2.1.0" + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/0b5bdcbd100469acc6b02642f1bface12347423fc065b57fce94eef2f059a30ada1dfada2d172531305d4a48640c51236634f25eaa9529a400447862837ff595 + languageName: node + linkType: hard + "@typescript-eslint/types@npm:8.46.2, @typescript-eslint/types@npm:^8.46.2": version: 8.46.2 resolution: "@typescript-eslint/types@npm:8.46.2" @@ -1344,6 +1428,13 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/types@npm:8.49.0, @typescript-eslint/types@npm:^8.49.0": + version: 8.49.0 + resolution: "@typescript-eslint/types@npm:8.49.0" + checksum: 10c0/75b26207b142576cf9af86406815b440c7f4bc6645fa58c58a3d781a5d80a39ba7e44d4b4df297980019a7aa1db10da5ac515191aaaf0f1ef6007996c126d8f9 + languageName: node + linkType: hard + "@typescript-eslint/typescript-estree@npm:8.46.2": version: 8.46.2 resolution: "@typescript-eslint/typescript-estree@npm:8.46.2" @@ -1364,6 +1455,25 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/typescript-estree@npm:8.49.0": + version: 8.49.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.49.0" + dependencies: + "@typescript-eslint/project-service": "npm:8.49.0" + "@typescript-eslint/tsconfig-utils": "npm:8.49.0" + "@typescript-eslint/types": "npm:8.49.0" + "@typescript-eslint/visitor-keys": "npm:8.49.0" + debug: "npm:^4.3.4" + minimatch: "npm:^9.0.4" + semver: "npm:^7.6.0" + tinyglobby: "npm:^0.2.15" + ts-api-utils: "npm:^2.1.0" + peerDependencies: + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/91d0e4ed00021085142c2845571cc91c89b700ee184eb508e8d1f97a02533c029630f00c3f0f796942b28397ec9f61502b153c81971d228893363fc546bbb341 + languageName: node + linkType: hard + "@typescript-eslint/utils@npm:8.46.2": version: 8.46.2 resolution: "@typescript-eslint/utils@npm:8.46.2" @@ -1379,6 +1489,21 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/utils@npm:8.49.0": + version: 8.49.0 + resolution: "@typescript-eslint/utils@npm:8.49.0" + dependencies: + "@eslint-community/eslint-utils": "npm:^4.7.0" + "@typescript-eslint/scope-manager": "npm:8.49.0" + "@typescript-eslint/types": "npm:8.49.0" + "@typescript-eslint/typescript-estree": "npm:8.49.0" + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/d10fe4d844dacb2f76f0a6e018455d94ba29204845d57248ae220030bda7e13e0e7b488b3ccf8ce1b5d577e1e1775cbdbbff911261a586d9bc7fdfc3cc001697 + languageName: node + linkType: hard + "@typescript-eslint/visitor-keys@npm:8.46.2": version: 8.46.2 resolution: "@typescript-eslint/visitor-keys@npm:8.46.2" @@ -1389,6 +1514,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/visitor-keys@npm:8.49.0": + version: 8.49.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.49.0" + dependencies: + "@typescript-eslint/types": "npm:8.49.0" + eslint-visitor-keys: "npm:^4.2.1" + checksum: 10c0/442c47bf8e46dda50a765cddbd524f6fef9e76acc3d11de2505ca7097054f24e53f12fe57be34b72fb56115f8f74499573a2704f3465bffdb96834083b616cf1 + languageName: node + linkType: hard + "@typescript/vfs@npm:^1.5.2": version: 1.6.2 resolution: "@typescript/vfs@npm:1.6.2" @@ -3742,7 +3877,7 @@ __metadata: semver: "npm:^7.7.3" temp-dir: "npm:^3.0.0" typescript: "npm:^5.9.3" - typescript-eslint: "npm:^8.46.2" + typescript-eslint: "npm:^8.49.0" vitest: "npm:^4.0.6" languageName: unknown linkType: soft @@ -4456,18 +4591,18 @@ __metadata: languageName: node linkType: hard -"typescript-eslint@npm:^8.46.2": - version: 8.46.2 - resolution: "typescript-eslint@npm:8.46.2" +"typescript-eslint@npm:^8.49.0": + version: 8.49.0 + resolution: "typescript-eslint@npm:8.49.0" dependencies: - "@typescript-eslint/eslint-plugin": "npm:8.46.2" - "@typescript-eslint/parser": "npm:8.46.2" - "@typescript-eslint/typescript-estree": "npm:8.46.2" - "@typescript-eslint/utils": "npm:8.46.2" + "@typescript-eslint/eslint-plugin": "npm:8.49.0" + "@typescript-eslint/parser": "npm:8.49.0" + "@typescript-eslint/typescript-estree": "npm:8.49.0" + "@typescript-eslint/utils": "npm:8.49.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/9c1bef1887ee984e63cbf4f4321f22ed232b192597400b74220aaecd42235bccc3c7786e002d283f81e1a0812a1c6d83ea5860bffa5e87d119204ecb9db0296a + checksum: 10c0/6559807ab5f0708455e22eeface154e5386506d22e4f0c5b1b2038c671ec9fb8b18f0319f6fc1f776f125902e3dc1fcfa99cc44ccf694ccac768c7034499c7e6 languageName: node linkType: hard