Skip to content

Commit 5fe340f

Browse files
committed
Use version of prettier from package.json
1 parent 68ba545 commit 5fe340f

File tree

10 files changed

+236
-43
lines changed

10 files changed

+236
-43
lines changed

.pre-commit-config.yaml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,16 @@ repos:
3636
# document contents. For example
3737
# packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/ruby/changeCondition.yml
3838
exclude: ^packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/.*/[^/]*\.yml$
39-
- repo: https://github.com/pre-commit/mirrors-prettier
40-
rev: "v2.7.1"
39+
- repo: local
4140
hooks:
4241
- id: prettier
42+
name: prettier
43+
types: [text]
44+
language: node
45+
entry: prettier --write --list-different --ignore-unknown
46+
additional_dependencies:
47+
48+
args: []
4349
- repo: https://github.com/ikamensh/flynt/
4450
rev: "0.78"
4551
hooks:

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"watch": "tsc --build --watch",
1212
"init-vscode-sandbox": "pnpm --filter=@cursorless/cursorless-vscode-core init-launch-sandbox",
1313
"meta-updater:base": "pnpm --filter=@cursorless/meta-updater build && meta-updater",
14-
"meta-updater": "pnpm run meta-updater:base && pnpm -r exec prettier --write tsconfig.json package.json",
14+
"meta-updater": "pnpm run meta-updater:base && pnpm -r exec prettier --write tsconfig.json package.json && pnpm -w exec prettier --write .pre-commit-config.yaml",
1515
"lint:meta": "pnpm run meta-updater:base --test",
1616
"lint": "pnpm run lint:meta && syncpack list-mismatches && pnpm run lint:ts",
1717
"lint:ts": "eslint packages --ext ts",
@@ -40,7 +40,8 @@
4040
},
4141
"pnpm": {
4242
"patchedDependencies": {
43-
"@docusaurus/[email protected]": "patches/@[email protected]"
43+
"@docusaurus/[email protected]": "patches/@[email protected]",
44+
4445
},
4546
"peerDependencyRules": {
4647
"ignoreMissing": [

packages/meta-updater/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
"@types/normalize-path": "^3.0.0",
1616
"normalize-path": "^3.0.0",
1717
"path-exists": "^4.0.0",
18-
"type-fest": "3.6.1"
18+
"ramda": "0.29.0",
19+
"type-fest": "3.6.1",
20+
"yaml": "2.2.1"
1921
},
2022
"main": "./out/index.js",
2123
"types": "./out/index.d.ts",
@@ -27,6 +29,7 @@
2729
}
2830
},
2931
"devDependencies": {
32+
"@types/ramda": "0.28.23",
3033
"esbuild": "^0.17.11"
3134
}
3235
}

packages/meta-updater/src/formats.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { createFormat } from "@pnpm/meta-updater";
2+
import { readFile, writeFile } from "fs/promises";
3+
import { equals } from "ramda";
4+
import yaml from "yaml";
5+
6+
export const formats = {
7+
[".yaml"]: createFormat({
8+
async read({ resolvedPath }) {
9+
return yaml.parseDocument(await readFile(resolvedPath, "utf-8")).clone();
10+
},
11+
update(actual, updater, options) {
12+
return updater(actual, options);
13+
},
14+
equal(expected, actual) {
15+
return equals(actual.toJS(), expected.toJS());
16+
},
17+
async write(expected, { resolvedPath }) {
18+
await writeFile(resolvedPath, expected.toString());
19+
},
20+
clone(content) {
21+
return content == null ? content : content.clone();
22+
},
23+
}),
24+
};
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import normalizePath from "normalize-path";
2+
import path from "path";
3+
import { Lockfile } from "@pnpm/lockfile-file";
4+
5+
export function getPackageDeps(
6+
workspaceDir: string,
7+
packageDir: string,
8+
pnpmLockfile: Lockfile,
9+
) {
10+
const pathFromRootToPackage =
11+
packageDir === workspaceDir
12+
? "."
13+
: normalizePath(path.relative(workspaceDir, packageDir));
14+
15+
/** Info about package dependencies gleaned from lock file. */
16+
const lockFilePackageInfo = pnpmLockfile.importers[pathFromRootToPackage];
17+
if (!lockFilePackageInfo) {
18+
// Raise an error here because there should always be an entry in the lockfile.
19+
throw new Error(`No importer found for ${pathFromRootToPackage}`);
20+
}
21+
22+
const deps = {
23+
...lockFilePackageInfo.dependencies,
24+
...lockFilePackageInfo.devDependencies,
25+
};
26+
return deps;
27+
}

packages/meta-updater/src/metaUpdater.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { createUpdateOptions } from "@pnpm/meta-updater";
77
import { Context } from "./Context";
88
import { updatePackageJson } from "./updatePackageJson";
99
import { updateTSConfig } from "./updateTSConfig";
10+
import { updatePreCommit } from "./updatePreCommit";
11+
import { formats } from "./formats";
1012

1113
export const updater = async (workspaceDir: string) => {
1214
const pnpmLockfile = await readWantedLockfile(workspaceDir, {
@@ -23,7 +25,11 @@ export const updater = async (workspaceDir: string) => {
2325
};
2426

2527
return createUpdateOptions({
26-
["package.json"]: updatePackageJson.bind(null, context),
27-
["tsconfig.json"]: updateTSConfig.bind(null, context),
28+
files: {
29+
["package.json"]: updatePackageJson.bind(null, context),
30+
["tsconfig.json"]: updateTSConfig.bind(null, context),
31+
[".pre-commit-config.yaml"]: updatePreCommit.bind(null, context),
32+
},
33+
formats,
2834
});
2935
};
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import type { FormatPluginFnOptions } from "@pnpm/meta-updater";
2+
import { Document, ParsedNode } from "yaml";
3+
import { Context } from "./Context";
4+
import { getPackageDeps } from "./getPackageDeps";
5+
6+
interface PreCommitConfig {
7+
repos: {
8+
hooks: {
9+
id: string;
10+
// eslint-disable-next-line @typescript-eslint/naming-convention
11+
additional_dependencies: string[];
12+
}[];
13+
}[];
14+
}
15+
16+
/**
17+
* Given a tsconfig.json, update it to match our conventions. This function is
18+
* called by the pnpm `meta-updater` plugin either to check if the tsconfig.json
19+
* is up to date or to update it, depending on flags.
20+
* @param context Contains context such as workspace dir and parsed pnpm
21+
* lockfile
22+
* @param rawInput The input tsconfig.json that should be checked / updated
23+
* @param options Extra information provided by pnpm; mostly just the directory
24+
* of the package whose tsconfig.json we are updating
25+
* @returns The updated tsconfig.json
26+
*/
27+
export async function updatePreCommit(
28+
{ workspaceDir, pnpmLockfile }: Context,
29+
rawInput: Document<ParsedNode> | null,
30+
options: FormatPluginFnOptions,
31+
): Promise<Document<ParsedNode> | null> {
32+
if (rawInput == null) {
33+
return null;
34+
}
35+
/** Directory of the package whose tsconfig.json we are updating */
36+
const packageDir = options.dir;
37+
38+
if (packageDir !== workspaceDir) {
39+
throw new Error("updatePreCommit should only be called on root");
40+
}
41+
42+
const deps = getPackageDeps(workspaceDir, packageDir, pnpmLockfile);
43+
const prettierVersion = deps["prettier"];
44+
45+
const prettierHookIndex = (rawInput.toJS() as PreCommitConfig).repos
46+
.flatMap(({ hooks }, repoIndex) =>
47+
hooks.map((hook, hookIndex) => ({ hook, repoIndex, hookIndex })),
48+
)
49+
.filter(({ hook }) => hook.id === "prettier");
50+
51+
if (prettierHookIndex.length === 0) {
52+
throw new Error("No prettier hook found");
53+
}
54+
55+
if (prettierHookIndex.length > 1) {
56+
throw new Error("Multiple prettier hooks found");
57+
}
58+
59+
const { repoIndex, hookIndex } = prettierHookIndex[0];
60+
61+
rawInput.setIn(
62+
["repos", repoIndex, "hooks", hookIndex, "additional_dependencies"],
63+
rawInput.createNode([`prettier@${prettierVersion}`]),
64+
);
65+
66+
return rawInput;
67+
}

packages/meta-updater/src/updateTSConfig.ts

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import exists from "path-exists";
55
import { TsConfigJson } from "type-fest";
66
import { toPosixPath } from "./toPosixPath";
77
import { Context } from "./Context";
8+
import { getPackageDeps } from "./getPackageDeps";
89

910
/**
1011
* Given a tsconfig.json, update it to match our conventions. This function is
@@ -41,24 +42,11 @@ export async function updateTSConfig(
4142
};
4243
}
4344

44-
const pathFromRootToPackage = normalizePath(
45-
path.relative(workspaceDir, packageDir),
46-
);
4745
const pathFromPackageToRoot = normalizePath(
4846
path.relative(packageDir, workspaceDir),
4947
);
5048

51-
/** Info about package dependencies gleaned from lock file. */
52-
const lockFilePackageInfo = pnpmLockfile.importers[pathFromRootToPackage];
53-
if (!lockFilePackageInfo) {
54-
// Raise an error here because there should always be an entry in the lockfile.
55-
throw new Error(`No importer found for ${pathFromRootToPackage}`);
56-
}
57-
58-
const deps = {
59-
...lockFilePackageInfo.dependencies,
60-
...lockFilePackageInfo.devDependencies,
61-
};
49+
const deps = getPackageDeps(workspaceDir, packageDir, pnpmLockfile);
6250

6351
/** Computed tsconfig.json references based on dependencies. */
6452
const references = [] as Array<{ path: string }>;

patches/@[email protected]

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
diff --git a/lib/index.js b/lib/index.js
2+
index d24112f5fedba5a9d7c5bd85221652a8f0bf09e1..2af95628f80926b8c4c9c774d9135a95b465959c 100644
3+
--- a/lib/index.js
4+
+++ b/lib/index.js
5+
@@ -48,7 +48,8 @@ export async function performUpdates(workspaceDir, updateParam, opts) {
6+
_writeProjectManifest: writeProjectManifest,
7+
};
8+
const actual = (await fileExists(resolvedPath)) ? await formatPlugin.read(formatHandlerOptions) : null;
9+
- const expected = await formatPlugin.update(clone(actual), updateFile, formatHandlerOptions);
10+
+ const customClone = formatPlugin.clone == null ? clone : formatPlugin.clone;
11+
+ const expected = await formatPlugin.update(customClone(actual), updateFile, formatHandlerOptions);
12+
const equal = (actual == null && expected == null) ||
13+
(actual != null && expected != null && (await formatPlugin.equal(expected, actual, formatHandlerOptions)));
14+
if (equal) {
15+
diff --git a/lib/updater/formatPlugin.d.ts b/lib/updater/formatPlugin.d.ts
16+
index 887845721b09e17b95dd0789a5db8de72c04a654..2e47ba30b25661cec37d3ab1dcca1d8908a1eb21 100644
17+
--- a/lib/updater/formatPlugin.d.ts
18+
+++ b/lib/updater/formatPlugin.d.ts
19+
@@ -12,6 +12,8 @@ export interface FormatPlugin<Content> {
20+
equal(expected: Content, actual: Content, options: FormatPluginFnOptions): PromiseOrValue<boolean>;
21+
/** Called only if write is required (`--test` isn't specified, `expected != null` and `expected` is not equal to `actual`) */
22+
write(expected: Content, options: FormatPluginFnOptions): PromiseOrValue<void>;
23+
+ /** Can be used to override the built-in clone functionality */
24+
+ clone?(content: Content): PromiseOrValue<Content>;
25+
}
26+
export interface FormatPluginFnOptions {
27+
file: string;

0 commit comments

Comments
 (0)