Skip to content

Commit cc76626

Browse files
committed
feat(prettier): apply prettier code style to modified files after each update
1 parent 6750d80 commit cc76626

File tree

3 files changed

+84
-1
lines changed

3 files changed

+84
-1
lines changed

cli/update.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export function cliUpdate(path: string, options: object): void {
2121
case "git-not-clean":
2222
return `Git working copy not clean: ${reason.path}`;
2323
case "yarn-fix-failed":
24+
case "prettier-fix-failed":
2425
return `Failed to apply code style rules: ${reason.path}`;
2526
}
2627
})

prettier/fix.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import {resolve} from "path";
2+
import {mapFn} from "@softwareventures/array";
3+
import {ProjectSource} from "../project/project";
4+
import {readProjectJson} from "../project/read-json";
5+
import {combineAsyncResults, mapFailureFn, Result, success} from "../result/result";
6+
import {yarn} from "../yarn/yarn";
7+
8+
export type PrettierFixResult = Result<PrettierFixFailureReason>;
9+
10+
export interface PrettierFixFailureReason {
11+
readonly type: "prettier-fix-failed";
12+
readonly path: string;
13+
}
14+
15+
export async function prettierFixFiles(
16+
project: ProjectSource,
17+
relativePaths: readonly string[]
18+
): Promise<PrettierFixResult> {
19+
return Promise.resolve(relativePaths)
20+
.then(
21+
mapFn(async path =>
22+
yarn(project.path, "prettier", "--write", path).then(
23+
mapFailureFn(
24+
(): PrettierFixFailureReason => ({
25+
type: "prettier-fix-failed",
26+
path: resolve(project.path, path)
27+
})
28+
)
29+
)
30+
)
31+
)
32+
.then(combineAsyncResults);
33+
}
34+
35+
export async function prettierFixFilesIfAvailable(
36+
project: ProjectSource,
37+
relativePaths: readonly string[]
38+
): Promise<PrettierFixResult> {
39+
return isPrettierAvailable(project).then(async available =>
40+
available ? prettierFixFiles(project, relativePaths) : success()
41+
);
42+
}
43+
44+
export async function isPrettierAvailable(project: ProjectSource): Promise<boolean> {
45+
return readProjectJson(project, "package.json")
46+
.catch(reason => {
47+
if (reason instanceof SyntaxError || reason.code === "ENOENT") {
48+
return false;
49+
} else {
50+
throw reason;
51+
}
52+
})
53+
.then(
54+
packageJson =>
55+
packageJsonDependsOnPrettier(packageJson) && yarnPrettierCanRun(packageJson)
56+
);
57+
}
58+
59+
function packageJsonDependsOnPrettier(packageJson: any): boolean {
60+
return (
61+
typeof packageJson === "object" &&
62+
((typeof packageJson?.dependencies === "object" &&
63+
typeof packageJson?.dependencies?.prettier === "string") ||
64+
(typeof packageJson?.devDependencies === "object" &&
65+
typeof packageJson?.devDependencies?.prettier === "string"))
66+
);
67+
}
68+
69+
function yarnPrettierCanRun(packageJson: any): boolean {
70+
return (
71+
typeof packageJson === "object" &&
72+
(typeof packageJson?.scripts !== "object" ||
73+
packageJson?.scripts?.prettier == null ||
74+
String(packageJson?.scripts?.prettier).trim() === "prettier")
75+
);
76+
}

project/update.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {excludeNull, mapFn} from "../collections/async-iterable";
1919
import {addMissingLicense} from "../license/add-missing-license";
2020
import {YarnFixFailureReason} from "../yarn/fix";
2121
import {applyCodeStyle} from "../yarn/apply-code-style";
22+
import {PrettierFixFailureReason, prettierFixFilesIfAvailable} from "../prettier/fix";
2223
import {Project} from "./project";
2324

2425
export type Update = FsStageUpdate | DirectUpdate;
@@ -39,7 +40,7 @@ export type UpdateResult = Result<UpdateFailureReason>;
3940

4041
export type UpdateFailureReason = GitNotClean | CommitFailureReason | UpdateStepFailureReason;
4142

42-
export type UpdateStepFailureReason = YarnFixFailureReason;
43+
export type UpdateStepFailureReason = YarnFixFailureReason | PrettierFixFailureReason;
4344

4445
export async function updateProject(project: Project): Promise<UpdateResult> {
4546
const git = simpleGit(project.path);
@@ -80,6 +81,11 @@ function step(project: Project, git: SimpleGit): (update: Update) => Promise<Upd
8081
)
8182
.then(mapAsyncResultFn(async () => git.status()))
8283
.then(mapResultFn(status => concat([status.modified, status.not_added])))
84+
.then(
85+
bindAsyncResultFn(async files =>
86+
prettierFixFilesIfAvailable(project, files).then(mapResultFn(() => files))
87+
)
88+
)
8389
.then(
8490
mapAsyncResultFn(async files =>
8591
files.length === 0

0 commit comments

Comments
 (0)