Skip to content

Commit 6bf4e65

Browse files
committed
feat(update): add option to apply breaking changes during update
1 parent d3e771f commit 6bf4e65

File tree

5 files changed

+48
-10
lines changed

5 files changed

+48
-10
lines changed

cli/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ export default function cli(): void {
2424
.option("--webapp")
2525
.action((destination, options) => cliInit(destination ?? cwd(), options));
2626

27-
program.command("update [path]").action((path, options) => cliUpdate(path ?? cwd(), options));
27+
program
28+
.command("update [path]")
29+
.option("--breaking")
30+
.action((path, options) => cliUpdate(path ?? cwd(), options));
2831

2932
program.parse(argv);
3033
}

cli/update.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,16 @@ import {bindAsyncResultFn, bindFailureFn} from "../result/result";
66
import {UpdateFailureReason, updateProject} from "../project/update";
77
import {Project} from "../project/project";
88

9-
export function cliUpdate(path: string, options: object): void {
9+
export interface UpdateOptions {
10+
readonly breaking?: boolean;
11+
}
12+
13+
export function cliUpdate(path: string, {breaking}: UpdateOptions): void {
1014
readProject(path)
1115
.then(
12-
bindAsyncResultFn<ReadProjectFailureReason, UpdateFailureReason, Project>(updateProject)
16+
bindAsyncResultFn<ReadProjectFailureReason, UpdateFailureReason, Project>(
17+
async project => updateProject({project, breaking})
18+
)
1319
)
1420
.then(
1521
bindFailureFn(reasons => {

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
"@types/recursive-readdir": "2.2.0",
5151
"@types/semver": "7.3.6",
5252
"@types/spdx-correct": "2.0.0",
53+
"@types/wordwrap": "1.0.1",
5354
"commander": "8.0.0",
5455
"empty-dir": "2.0.0",
5556
"escodegen": "2.0.0",
@@ -66,6 +67,7 @@
6667
"spdx-license-list": "6.4.0",
6768
"tslib": "2.3.0",
6869
"typescript": "4.3.5",
70+
"wordwrap": "1.0.0",
6971
"xml-formatter": "2.4.0",
7072
"yarn": "1.22.10"
7173
},

project/update.ts

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import simpleGit, {SimpleGit} from "simple-git";
22
import chain from "@softwareventures/chain";
3-
import {concat} from "@softwareventures/array";
3+
import {concat, map} from "@softwareventures/array";
4+
import wrap = require("wordwrap");
45
import {mapFn as mapAsyncFn} from "../collections/async-iterable";
56
import {FsStage, InsertResult} from "../fs-stage/fs-stage";
67
import {
@@ -30,12 +31,14 @@ export type Update = FsStageUpdate | DirectUpdate;
3031
export interface FsStageUpdate {
3132
readonly type: "fs-stage-update";
3233
readonly log: string;
34+
readonly breaking?: readonly string[];
3335
readonly apply: (stage: FsStage) => Promise<InsertResult>;
3436
}
3537

3638
export interface DirectUpdate {
3739
readonly type: "direct-update";
3840
readonly log: string;
41+
readonly breaking?: readonly string[];
3942
readonly apply: () => Promise<Result<UpdateStepFailureReason>>;
4043
}
4144

@@ -45,8 +48,13 @@ export type UpdateFailureReason = GitNotClean | CommitFailureReason | UpdateStep
4548

4649
export type UpdateStepFailureReason = YarnFixFailureReason | PrettierFixFailureReason;
4750

48-
export async function updateProject(project: Project): Promise<UpdateResult> {
49-
const git = simpleGit(project.path);
51+
export interface UpdateProjectOptions {
52+
readonly project: Project;
53+
readonly breaking?: boolean;
54+
}
55+
56+
export async function updateProject(options: UpdateProjectOptions): Promise<UpdateResult> {
57+
const git = simpleGit(options.project.path);
5058

5159
return chain([
5260
updateLintScript,
@@ -56,7 +64,7 @@ export async function updateProject(project: Project): Promise<UpdateResult> {
5664
addMissingLicense,
5765
addNewNodeVersionsToPackageJson
5866
])
59-
.map(mapAsyncFn(step(project, git)))
67+
.map(mapAsyncFn(step(options, git)))
6068
.map(combineAsyncResults).value;
6169
}
6270

@@ -70,14 +78,19 @@ export function gitNotClean(path: string): GitNotClean {
7078
}
7179

7280
function step(
73-
project: Project,
81+
{project, breaking}: UpdateProjectOptions,
7482
git: SimpleGit
7583
): (update: (project: Project) => Promise<Update | null>) => Promise<UpdateResult> {
7684
return async update =>
7785
git
7886
.status()
7987
.then(status => (status.isClean() ? success() : failure([gitNotClean(project.path)])))
8088
.then(mapAsyncResultFn(async () => update(project)))
89+
.then(
90+
mapAsyncResultFn(async update =>
91+
breaking || (update?.breaking?.length ?? 0) === 0 ? update : null
92+
)
93+
)
8194
.then(bindAsyncResultFn(async update => commitUpdate(project, git, update)));
8295
}
8396

@@ -102,7 +115,7 @@ async function commitUpdate(
102115
mapAsyncResultFn(async files =>
103116
files.length === 0
104117
? undefined
105-
: git.add(files).then(async () => git.commit(update.log))
118+
: git.add(files).then(async () => git.commit(generateCommitLog(update)))
106119
)
107120
)
108121
.then(
@@ -114,6 +127,15 @@ async function commitUpdate(
114127
);
115128
}
116129

130+
function generateCommitLog(update: Update): string {
131+
return (
132+
update.log +
133+
map(update.breaking ?? [], breaking => wrap(62)(`\n\nBREAKING CHANGE: ${breaking}`)).join(
134+
""
135+
)
136+
);
137+
}
138+
117139
async function writeUpdate(project: Project, update: Update): Promise<UpdateResult> {
118140
switch (update.type) {
119141
case "fs-stage-update":

yarn.lock

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,11 @@
701701
resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.0.tgz#fef1904e4668b6e5ecee60c52cc6a078ffa6697d"
702702
integrity sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A==
703703

704+
"@types/wordwrap@1.0.1":
705+
version "1.0.1"
706+
resolved "https://registry.yarnpkg.com/@types/wordwrap/-/wordwrap-1.0.1.tgz#6cfbe1e2ea03a30831453389e5fdec8be40fd178"
707+
integrity sha512-xe+rWyom8xn0laMWH3M7elOpWj2rDQk+3f13RAur89GKsf4FO5qmBNtXXtwepFo2XNgQI0nePdCEStoHFnNvWg==
708+
704709
"@typescript-eslint/eslint-plugin-tslint@^2.31.0 || ^3.0.0 || ^4.0.0 || ^4.21.0":
705710
version "4.28.0"
706711
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin-tslint/-/eslint-plugin-tslint-4.28.0.tgz#f555425ee8b7dc3de1f5941df51c2c6edf19e891"
@@ -6346,7 +6351,7 @@ word-wrap@^1.0.3, word-wrap@^1.2.3, word-wrap@~1.2.3:
63466351
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
63476352
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
63486353

6349-
wordwrap@^1.0.0:
6354+
wordwrap@1.0.0, wordwrap@^1.0.0:
63506355
version "1.0.0"
63516356
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
63526357
integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=

0 commit comments

Comments
 (0)