@servicetitan/startup 24.0.3 → 24.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands/build.d.ts +1 -0
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/build.js +3 -0
- package/dist/cli/commands/build.js.map +1 -1
- package/dist/cli/commands/bundle-package.d.ts +1 -0
- package/dist/cli/commands/bundle-package.d.ts.map +1 -1
- package/dist/cli/commands/bundle-package.js +3 -0
- package/dist/cli/commands/bundle-package.js.map +1 -1
- package/dist/cli/commands/eslint.d.ts +1 -0
- package/dist/cli/commands/eslint.d.ts.map +1 -1
- package/dist/cli/commands/eslint.js +3 -0
- package/dist/cli/commands/eslint.js.map +1 -1
- package/dist/cli/commands/get-command.d.ts +6 -0
- package/dist/cli/commands/get-command.d.ts.map +1 -0
- package/dist/cli/commands/get-command.js +50 -0
- package/dist/cli/commands/get-command.js.map +1 -0
- package/dist/cli/commands/get-user-commands.d.ts +7 -0
- package/dist/cli/commands/get-user-commands.d.ts.map +1 -0
- package/dist/cli/commands/get-user-commands.js +17 -0
- package/dist/cli/commands/get-user-commands.js.map +1 -0
- package/dist/cli/commands/index.d.ts +3 -3
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +3 -0
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/init.d.ts +2 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +5 -2
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/install.d.ts +1 -0
- package/dist/cli/commands/install.d.ts.map +1 -1
- package/dist/cli/commands/install.js +3 -0
- package/dist/cli/commands/install.js.map +1 -1
- package/dist/cli/commands/kendo-ui-license.d.ts +1 -0
- package/dist/cli/commands/kendo-ui-license.d.ts.map +1 -1
- package/dist/cli/commands/kendo-ui-license.js +3 -0
- package/dist/cli/commands/kendo-ui-license.js.map +1 -1
- package/dist/cli/commands/lint.d.ts +1 -0
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/commands/lint.js +3 -0
- package/dist/cli/commands/lint.js.map +1 -1
- package/dist/cli/commands/mfe-publish.d.ts +7 -2
- package/dist/cli/commands/mfe-publish.d.ts.map +1 -1
- package/dist/cli/commands/mfe-publish.js +25 -11
- package/dist/cli/commands/mfe-publish.js.map +1 -1
- package/dist/cli/commands/prepare-package.d.ts +1 -0
- package/dist/cli/commands/prepare-package.d.ts.map +1 -1
- package/dist/cli/commands/prepare-package.js +3 -0
- package/dist/cli/commands/prepare-package.js.map +1 -1
- package/dist/cli/commands/start.d.ts +1 -0
- package/dist/cli/commands/start.d.ts.map +1 -1
- package/dist/cli/commands/start.js +3 -0
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/commands/styles-check.d.ts +1 -0
- package/dist/cli/commands/styles-check.d.ts.map +1 -1
- package/dist/cli/commands/styles-check.js +3 -0
- package/dist/cli/commands/styles-check.js.map +1 -1
- package/dist/cli/commands/tests.d.ts +1 -0
- package/dist/cli/commands/tests.d.ts.map +1 -1
- package/dist/cli/commands/tests.js +3 -0
- package/dist/cli/commands/tests.js.map +1 -1
- package/dist/cli/commands/types.d.ts +5 -0
- package/dist/cli/commands/types.d.ts.map +1 -0
- package/dist/cli/commands/types.js +3 -0
- package/dist/cli/commands/types.js.map +1 -0
- package/dist/cli/index.js +24 -37
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/utils/lerna-exec.d.ts +1 -0
- package/dist/cli/utils/lerna-exec.d.ts.map +1 -1
- package/dist/cli/utils/lerna-exec.js +3 -0
- package/dist/cli/utils/lerna-exec.js.map +1 -1
- package/dist/utils/get-packages.d.ts.map +1 -1
- package/dist/utils/get-packages.js +29 -12
- package/dist/utils/get-packages.js.map +1 -1
- package/dist/utils/maybe-create-git-folder.d.ts +10 -0
- package/dist/utils/maybe-create-git-folder.d.ts.map +1 -0
- package/dist/utils/maybe-create-git-folder.js +25 -0
- package/dist/utils/maybe-create-git-folder.js.map +1 -0
- package/package.json +12 -12
- package/src/cli/commands/__tests__/get-command.test.ts +17 -0
- package/src/cli/commands/__tests__/get-user-commands.test.ts +24 -0
- package/src/cli/commands/__tests__/init.test.ts +4 -4
- package/src/cli/commands/__tests__/install.test.ts +4 -0
- package/src/cli/commands/__tests__/mfe-publish.test.ts +11 -0
- package/src/cli/commands/build.ts +4 -0
- package/src/cli/commands/bundle-package.ts +4 -0
- package/src/cli/commands/eslint.ts +4 -0
- package/src/cli/commands/get-command.ts +50 -0
- package/src/cli/commands/get-user-commands.ts +19 -0
- package/src/cli/commands/index.ts +3 -4
- package/src/cli/commands/init.ts +7 -3
- package/src/cli/commands/install.ts +4 -0
- package/src/cli/commands/kendo-ui-license.ts +4 -0
- package/src/cli/commands/lint.ts +4 -0
- package/src/cli/commands/mfe-publish.ts +31 -12
- package/src/cli/commands/prepare-package.ts +4 -0
- package/src/cli/commands/start.ts +4 -0
- package/src/cli/commands/styles-check.ts +4 -0
- package/src/cli/commands/tests.ts +4 -0
- package/src/cli/commands/types.ts +4 -0
- package/src/cli/index.ts +27 -59
- package/src/cli/utils/__tests__/lerna-exec.test.ts +2 -0
- package/src/cli/utils/lerna-exec.ts +4 -0
- package/src/utils/__tests__/get-packages.test.ts +67 -20
- package/src/utils/__tests__/maybe-create-git-folder.test.ts +41 -0
- package/src/utils/get-packages.ts +34 -17
- package/src/utils/maybe-create-git-folder.ts +18 -0
- package/template-react18/packages/application/package.json +1 -1
- package/template-react18/packages/feature-a/package.json +1 -1
- package/template-react18/packages/feature-b/package.json +1 -1
- package/template-react18/packages/feature-c/package.json +1 -1
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { CommandName } from '../../utils';
|
|
2
|
+
|
|
3
|
+
import { Build } from './build';
|
|
4
|
+
import { BundlePackage } from './bundle-package';
|
|
5
|
+
import { ESLintCommand } from './eslint';
|
|
6
|
+
import { Init } from './init';
|
|
7
|
+
import { Install } from './install';
|
|
8
|
+
import { KendoUILicense } from './kendo-ui-license';
|
|
9
|
+
import { Lint } from './lint';
|
|
10
|
+
import { MFEPackageClean, MFEPackagePublish, MFEPublish } from './mfe-publish';
|
|
11
|
+
import { PreparePackage } from './prepare-package';
|
|
12
|
+
import { Start } from './start';
|
|
13
|
+
import { StylesCheck } from './styles-check';
|
|
14
|
+
import { Tests } from './tests';
|
|
15
|
+
import { Command } from './types';
|
|
16
|
+
|
|
17
|
+
type Newable<T> = new (...args: any[]) => T;
|
|
18
|
+
|
|
19
|
+
export function getCommand(name: CommandName): Newable<Command> | undefined {
|
|
20
|
+
switch (name) {
|
|
21
|
+
case CommandName.build:
|
|
22
|
+
return Build;
|
|
23
|
+
case CommandName['bundle-package']:
|
|
24
|
+
return BundlePackage;
|
|
25
|
+
case CommandName.eslint:
|
|
26
|
+
return ESLintCommand;
|
|
27
|
+
case CommandName.init:
|
|
28
|
+
return Init;
|
|
29
|
+
case CommandName.install:
|
|
30
|
+
return Install;
|
|
31
|
+
case CommandName['kendo-ui-license']:
|
|
32
|
+
return KendoUILicense;
|
|
33
|
+
case CommandName.lint:
|
|
34
|
+
return Lint;
|
|
35
|
+
case CommandName['mfe-package-clean']:
|
|
36
|
+
return MFEPackageClean;
|
|
37
|
+
case CommandName['mfe-package-publish']:
|
|
38
|
+
return MFEPackagePublish;
|
|
39
|
+
case CommandName['mfe-publish']:
|
|
40
|
+
return MFEPublish;
|
|
41
|
+
case CommandName['prepare-package']:
|
|
42
|
+
return PreparePackage;
|
|
43
|
+
case CommandName.start:
|
|
44
|
+
return Start;
|
|
45
|
+
case CommandName['styles-check']:
|
|
46
|
+
return StylesCheck;
|
|
47
|
+
case CommandName.test:
|
|
48
|
+
return Tests;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { CommandName } from '../../utils';
|
|
2
|
+
|
|
3
|
+
import { getCommand } from './get-command';
|
|
4
|
+
|
|
5
|
+
interface UserCommand {
|
|
6
|
+
name: string;
|
|
7
|
+
description: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function getUserCommands() {
|
|
11
|
+
return Object.values(CommandName)
|
|
12
|
+
.sort((a, b) => a.localeCompare(b))
|
|
13
|
+
.map(name => {
|
|
14
|
+
const Command = getCommand(name)!;
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
16
|
+
return { name, description: new Command({ _: [] }).description() };
|
|
17
|
+
})
|
|
18
|
+
.filter(({ description }) => !!description) as UserCommand[];
|
|
19
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export * from './build';
|
|
2
2
|
export * from './bundle-package';
|
|
3
3
|
export * from './eslint';
|
|
4
|
+
export * from './get-command';
|
|
5
|
+
export * from './get-user-commands';
|
|
4
6
|
export * from './init';
|
|
5
7
|
export * from './install';
|
|
6
8
|
export * from './kendo-ui-license';
|
|
@@ -10,7 +12,4 @@ export * from './start';
|
|
|
10
12
|
export * from './tests';
|
|
11
13
|
export * from './styles-check';
|
|
12
14
|
export * from './mfe-publish';
|
|
13
|
-
|
|
14
|
-
export interface Command {
|
|
15
|
-
execute(): Promise<void>;
|
|
16
|
-
}
|
|
15
|
+
export * from './types';
|
package/src/cli/commands/init.ts
CHANGED
|
@@ -7,13 +7,17 @@ import { log, logErrors } from '../../utils';
|
|
|
7
7
|
import { Command } from './';
|
|
8
8
|
|
|
9
9
|
interface Args {
|
|
10
|
-
|
|
10
|
+
react17?: boolean;
|
|
11
11
|
output?: string;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export class Init implements Command {
|
|
15
15
|
constructor(private args: Args) {}
|
|
16
16
|
|
|
17
|
+
description() {
|
|
18
|
+
return 'generate empty project';
|
|
19
|
+
}
|
|
20
|
+
|
|
17
21
|
@logErrors
|
|
18
22
|
async execute() {
|
|
19
23
|
const destination = path.resolve(this.args.output ?? '.');
|
|
@@ -25,11 +29,11 @@ export class Init implements Command {
|
|
|
25
29
|
|
|
26
30
|
await copyFiles('template', destination);
|
|
27
31
|
|
|
28
|
-
if (this.args.
|
|
32
|
+
if (!this.args.react17) {
|
|
29
33
|
await copyFiles('template-react18', destination);
|
|
30
34
|
}
|
|
31
35
|
|
|
32
|
-
log.info(`copied${this.args.
|
|
36
|
+
log.info(`copied${this.args.react17 ? ' React 17' : ''} template to ${destination}`);
|
|
33
37
|
}
|
|
34
38
|
}
|
|
35
39
|
|
|
@@ -4,6 +4,10 @@ import { log, logErrors, getStartupVersion } from '../../utils';
|
|
|
4
4
|
import { Command } from '.';
|
|
5
5
|
|
|
6
6
|
export class Install implements Command {
|
|
7
|
+
description() {
|
|
8
|
+
return 'install project dependencies';
|
|
9
|
+
}
|
|
10
|
+
|
|
7
11
|
@logErrors
|
|
8
12
|
async execute() {
|
|
9
13
|
const installCommand = process.env.CI ? 'ci' : 'i';
|
|
@@ -30,6 +30,10 @@ const LICENSE = Buffer.from(ENCODED_LICENSE, 'base64').toString('ascii');
|
|
|
30
30
|
const LICENSING_PACKAGE = '@progress/kendo-licensing';
|
|
31
31
|
|
|
32
32
|
export class KendoUILicense implements Command {
|
|
33
|
+
description() {
|
|
34
|
+
return 'install KendoReact license key';
|
|
35
|
+
}
|
|
36
|
+
|
|
33
37
|
async execute() {
|
|
34
38
|
if (!isModuleInstalled(LICENSING_PACKAGE)) {
|
|
35
39
|
return;
|
package/src/cli/commands/lint.ts
CHANGED
|
@@ -23,13 +23,14 @@ import { getDefaultBuildVersion } from '../utils/publish';
|
|
|
23
23
|
import { Command } from '.';
|
|
24
24
|
|
|
25
25
|
interface ArgsPackagePublish {
|
|
26
|
+
branch?: string;
|
|
26
27
|
build?: string;
|
|
28
|
+
concurrency?: number;
|
|
27
29
|
dry?: boolean;
|
|
28
30
|
force?: boolean;
|
|
29
|
-
branch?: string;
|
|
30
|
-
tag?: string | false;
|
|
31
31
|
noTag?: string;
|
|
32
32
|
registry?: string;
|
|
33
|
+
tag?: string | false;
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
interface ArgsPackageClean {
|
|
@@ -44,6 +45,10 @@ interface Args extends ArgsPackagePublish, ArgsPackageClean {
|
|
|
44
45
|
export class MFEPublish implements Command {
|
|
45
46
|
constructor(private args: Args) {}
|
|
46
47
|
|
|
48
|
+
description() {
|
|
49
|
+
return 'publish or unpublish MFE packages';
|
|
50
|
+
}
|
|
51
|
+
|
|
47
52
|
@logErrors
|
|
48
53
|
async execute() {
|
|
49
54
|
let packages = splitPackagesByType(getPackages())[PackageType.Webpack] ?? [];
|
|
@@ -67,25 +72,35 @@ export class MFEPublish implements Command {
|
|
|
67
72
|
|
|
68
73
|
await lernaExec({
|
|
69
74
|
'cmd': `startup mfe-package-${this.args.clean ? 'clean' : 'publish'}`,
|
|
75
|
+
'concurrency': this.args.concurrency ?? 1,
|
|
70
76
|
'scope': packages.map(({ name }) => name),
|
|
71
77
|
'stream': true,
|
|
72
|
-
'--':
|
|
73
|
-
...[this.args.build ? `--build ${this.args.build}` : undefined],
|
|
74
|
-
...[this.args.branch ? `--branch ${this.args.branch}` : undefined],
|
|
75
|
-
...[this.args.tag ? `--tag ${this.args.tag}` : undefined],
|
|
76
|
-
...[this.args.tag === false ? `--no-tag` : undefined],
|
|
77
|
-
...[this.args.dry ? '--dry' : undefined],
|
|
78
|
-
...[this.args.force ? '--force' : undefined],
|
|
79
|
-
...[this.args.count ? `--count ${this.args.count}` : undefined],
|
|
80
|
-
...[this.args.registry ? `--registry ${this.args.registry}` : undefined],
|
|
81
|
-
].filter(item => !!item) as string[],
|
|
78
|
+
'--': this.getPublishOptions(),
|
|
82
79
|
});
|
|
83
80
|
}
|
|
81
|
+
|
|
82
|
+
getPublishOptions() {
|
|
83
|
+
const { build, branch, count, dry, force, registry, tag } = this.args;
|
|
84
|
+
return [
|
|
85
|
+
...[branch && `--branch ${branch}`],
|
|
86
|
+
...[build && `--build ${build}`],
|
|
87
|
+
...[count && `--count ${count}`],
|
|
88
|
+
...[dry && '--dry'],
|
|
89
|
+
...[force && '--force'],
|
|
90
|
+
...[registry && `--registry ${registry}`],
|
|
91
|
+
...[tag && `--tag ${tag}`],
|
|
92
|
+
...[tag === false && `--no-tag`],
|
|
93
|
+
].filter(item => !!item) as string[];
|
|
94
|
+
}
|
|
84
95
|
}
|
|
85
96
|
|
|
86
97
|
export class MFEPackagePublish implements Command {
|
|
87
98
|
constructor(private args: ArgsPackagePublish) {}
|
|
88
99
|
|
|
100
|
+
description() {
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
|
|
89
104
|
@logErrors
|
|
90
105
|
async execute() {
|
|
91
106
|
if (!isWebComponent()) {
|
|
@@ -190,6 +205,10 @@ export class MFEPackagePublish implements Command {
|
|
|
190
205
|
export class MFEPackageClean implements Command {
|
|
191
206
|
constructor(private args: ArgsPackageClean) {}
|
|
192
207
|
|
|
208
|
+
description() {
|
|
209
|
+
return undefined;
|
|
210
|
+
}
|
|
211
|
+
|
|
193
212
|
@logErrors
|
|
194
213
|
async execute() {
|
|
195
214
|
if (!isWebComponent()) {
|
|
@@ -121,6 +121,10 @@ function checkStylesWebComponent(files: FileInfo[]) {
|
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
export class StylesCheck implements Command {
|
|
124
|
+
description() {
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
|
|
124
128
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
125
129
|
async execute() {
|
|
126
130
|
if (isLegacy()) {
|
package/src/cli/index.ts
CHANGED
|
@@ -1,69 +1,23 @@
|
|
|
1
1
|
import execa from 'execa';
|
|
2
2
|
import { argv, Arguments } from 'yargs';
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
Build,
|
|
7
|
-
BundlePackage,
|
|
8
|
-
Command,
|
|
9
|
-
ESLintCommand,
|
|
10
|
-
Init,
|
|
11
|
-
Install,
|
|
12
|
-
KendoUILicense,
|
|
13
|
-
Lint,
|
|
14
|
-
MFEPackageClean,
|
|
15
|
-
MFEPackagePublish,
|
|
16
|
-
MFEPublish,
|
|
17
|
-
PreparePackage,
|
|
18
|
-
Start,
|
|
19
|
-
StylesCheck,
|
|
20
|
-
Tests,
|
|
21
|
-
} from './commands';
|
|
3
|
+
import { CommandName, getStartupVersion, log } from '../utils';
|
|
4
|
+
import { getCommand, getUserCommands } from './commands';
|
|
22
5
|
import { setNodeOptions } from './utils';
|
|
23
6
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
case CommandName.build:
|
|
31
|
-
return Build;
|
|
32
|
-
case CommandName['bundle-package']:
|
|
33
|
-
return BundlePackage;
|
|
34
|
-
case CommandName.eslint:
|
|
35
|
-
return ESLintCommand;
|
|
36
|
-
case CommandName.init:
|
|
37
|
-
return Init;
|
|
38
|
-
case CommandName.install:
|
|
39
|
-
return Install;
|
|
40
|
-
case CommandName['kendo-ui-license']:
|
|
41
|
-
return KendoUILicense;
|
|
42
|
-
case CommandName.lint:
|
|
43
|
-
return Lint;
|
|
44
|
-
case CommandName['mfe-package-clean']:
|
|
45
|
-
return MFEPackageClean;
|
|
46
|
-
case CommandName['mfe-package-publish']:
|
|
47
|
-
return MFEPackagePublish;
|
|
48
|
-
case CommandName['mfe-publish']:
|
|
49
|
-
return MFEPublish;
|
|
50
|
-
case CommandName['prepare-package']:
|
|
51
|
-
return PreparePackage;
|
|
52
|
-
case CommandName.start:
|
|
53
|
-
return Start;
|
|
54
|
-
case CommandName['styles-check']:
|
|
55
|
-
return StylesCheck;
|
|
56
|
-
case CommandName.test:
|
|
57
|
-
return Tests;
|
|
58
|
-
default:
|
|
59
|
-
log.error(`${name}: command not found!`);
|
|
60
|
-
process.exit(127);
|
|
61
|
-
}
|
|
7
|
+
const argvSync = argv as Arguments;
|
|
8
|
+
const name = argvSync._[0]?.toString() as CommandName;
|
|
9
|
+
if (!name) {
|
|
10
|
+
log.info(`startup cli v${getStartupVersion()}`);
|
|
11
|
+
usage();
|
|
12
|
+
process.exit(0);
|
|
62
13
|
}
|
|
63
14
|
|
|
64
|
-
const argvSync = argv as Arguments;
|
|
65
|
-
const name = argvSync._[0].toString() as CommandName;
|
|
66
15
|
const Command = getCommand(name);
|
|
16
|
+
if (!Command) {
|
|
17
|
+
log.error(`Unknown command: "${name}"`);
|
|
18
|
+
usage();
|
|
19
|
+
process.exit(127);
|
|
20
|
+
}
|
|
67
21
|
|
|
68
22
|
if (setNodeOptions(name)) {
|
|
69
23
|
// Run command in child process with amended NODE_OPTIONS
|
|
@@ -77,3 +31,17 @@ if (setNodeOptions(name)) {
|
|
|
77
31
|
process.exit(1);
|
|
78
32
|
});
|
|
79
33
|
}
|
|
34
|
+
|
|
35
|
+
function usage() {
|
|
36
|
+
write('\nUsage:\n');
|
|
37
|
+
|
|
38
|
+
const commands = getUserCommands().filter(({ name }) => !!name);
|
|
39
|
+
const maxNameLength = commands.reduce((result, { name }) => Math.max(result, name.length), 0);
|
|
40
|
+
commands.forEach(({ name, description }) => {
|
|
41
|
+
write(`startup ${name.padEnd(maxNameLength, ' ')} ${description}`);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function write(text: string) {
|
|
46
|
+
return console.info(text); // eslint-disable-line no-console
|
|
47
|
+
}
|
|
@@ -31,6 +31,8 @@ describe(`${lernaExec.name}`, () => {
|
|
|
31
31
|
{ arg: { parallel: true }, option: '--parallel' },
|
|
32
32
|
{ arg: { stream: true }, option: '--stream' },
|
|
33
33
|
{ arg: { bail: false }, option: '--no-bail' },
|
|
34
|
+
{ arg: { concurrency: 1 }, option: '--concurrency=1' },
|
|
35
|
+
{ arg: { concurrency: 0 }, option: '--concurrency=0' },
|
|
34
36
|
] as { arg: Partial<typeof args>; option: string }[])('with $arg', ({ arg, option }) => {
|
|
35
37
|
beforeEach(() => Object.assign(args, arg));
|
|
36
38
|
|
|
@@ -4,6 +4,7 @@ import { log } from '../../utils';
|
|
|
4
4
|
interface Args {
|
|
5
5
|
'bail'?: boolean;
|
|
6
6
|
'cmd': string;
|
|
7
|
+
'concurrency'?: number;
|
|
7
8
|
'scope'?: string[];
|
|
8
9
|
'stream'?: boolean;
|
|
9
10
|
'parallel'?: boolean;
|
|
@@ -33,5 +34,8 @@ function getOptions(args: Args) {
|
|
|
33
34
|
if (args.stream) {
|
|
34
35
|
result.push('--stream');
|
|
35
36
|
}
|
|
37
|
+
if (typeof args.concurrency === 'number') {
|
|
38
|
+
result.push(`--concurrency=${args.concurrency}`);
|
|
39
|
+
}
|
|
36
40
|
return result;
|
|
37
41
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import execa from 'execa';
|
|
2
2
|
import { isBundle, isLegacy } from '../get-configuration';
|
|
3
|
+
import { log } from '../log';
|
|
4
|
+
import { maybeCreateGitFolder } from '../maybe-create-git-folder';
|
|
3
5
|
|
|
4
6
|
import {
|
|
5
7
|
Package,
|
|
@@ -11,6 +13,7 @@ import {
|
|
|
11
13
|
|
|
12
14
|
jest.mock('execa', () => ({ sync: jest.fn() }));
|
|
13
15
|
jest.mock('../get-configuration');
|
|
16
|
+
jest.mock('../maybe-create-git-folder');
|
|
14
17
|
|
|
15
18
|
describe('[startup] Utils', () => {
|
|
16
19
|
const packages: Pick<Package, 'name' | 'location' | 'type'>[] = [
|
|
@@ -19,6 +22,15 @@ describe('[startup] Utils', () => {
|
|
|
19
22
|
{ name: 'baz', location: 'packages/baz', type: PackageType.Webpack },
|
|
20
23
|
];
|
|
21
24
|
|
|
25
|
+
beforeEach(() => jest.clearAllMocks());
|
|
26
|
+
|
|
27
|
+
function expectExecaToBeCalledWith(command: string, options?: execa.SyncOptions) {
|
|
28
|
+
const [file, ...args] = command.split(' ');
|
|
29
|
+
const { calls } = jest.mocked(execa.sync).mock;
|
|
30
|
+
const expected: any[] = [file, args, ...(options ? [options] : [])];
|
|
31
|
+
expect(calls).toContainEqual(expect.arrayContaining(expected));
|
|
32
|
+
}
|
|
33
|
+
|
|
22
34
|
describe(`${getPackages.name}`, () => {
|
|
23
35
|
let options: Parameters<typeof getPackages>[0] | undefined;
|
|
24
36
|
let dependencies: Record<string, string[]> | undefined;
|
|
@@ -40,6 +52,16 @@ describe('[startup] Utils', () => {
|
|
|
40
52
|
return result;
|
|
41
53
|
}
|
|
42
54
|
|
|
55
|
+
function resolvePackages(args: string[]) {
|
|
56
|
+
if (args.includes('--graph')) {
|
|
57
|
+
return packageGraph();
|
|
58
|
+
}
|
|
59
|
+
if (args.includes('--scope')) {
|
|
60
|
+
return scopedPackages().map(({ type, ...pkg }) => pkg);
|
|
61
|
+
}
|
|
62
|
+
return packages.map(({ type, ...pkg }) => pkg);
|
|
63
|
+
}
|
|
64
|
+
|
|
43
65
|
beforeEach(() => {
|
|
44
66
|
options = undefined;
|
|
45
67
|
dependencies = undefined;
|
|
@@ -52,15 +74,7 @@ describe('[startup] Utils', () => {
|
|
|
52
74
|
);
|
|
53
75
|
// @ts-expect-error because implementation doesn't match all exec.sync signatures
|
|
54
76
|
jest.mocked(execa.sync).mockImplementation((_: string, args: string[]): any => {
|
|
55
|
-
return {
|
|
56
|
-
stdout: JSON.stringify(
|
|
57
|
-
args.includes('--graph')
|
|
58
|
-
? packageGraph()
|
|
59
|
-
: args.includes('--scope')
|
|
60
|
-
? scopedPackages().map(({ type, ...pkg }) => pkg)
|
|
61
|
-
: packages.map(({ type, ...pkg }) => pkg)
|
|
62
|
-
),
|
|
63
|
-
};
|
|
77
|
+
return { stdout: JSON.stringify(resolvePackages(args)) };
|
|
64
78
|
});
|
|
65
79
|
});
|
|
66
80
|
|
|
@@ -68,7 +82,34 @@ describe('[startup] Utils', () => {
|
|
|
68
82
|
|
|
69
83
|
test('returns lerna packages with type metadata', () => {
|
|
70
84
|
expect(subject()).toEqual(packages);
|
|
71
|
-
|
|
85
|
+
expectExecaToBeCalledWith('npx lerna la --json');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test('conditionally creates .git folder', () => {
|
|
89
|
+
subject();
|
|
90
|
+
|
|
91
|
+
expect(maybeCreateGitFolder).toHaveBeenCalled();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
describe('when running on Windows', () => {
|
|
95
|
+
const originalPlatform = process.platform;
|
|
96
|
+
beforeEach(() => {
|
|
97
|
+
Object.defineProperty(process, 'platform', { value: 'win32' });
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
afterEach(() => {
|
|
101
|
+
Object.defineProperty(process, 'platform', { value: originalPlatform });
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test('sets NX_CACHE_PROJECT_GRAPH=false', () => {
|
|
105
|
+
subject();
|
|
106
|
+
|
|
107
|
+
expectExecaToBeCalledWith('npx lerna la --json', {
|
|
108
|
+
extendEnv: true,
|
|
109
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
110
|
+
env: { NX_CACHE_PROJECT_GRAPH: 'false' },
|
|
111
|
+
});
|
|
112
|
+
});
|
|
72
113
|
});
|
|
73
114
|
|
|
74
115
|
describe.each(['scope', 'ignore'])('with "%s"', option => {
|
|
@@ -77,10 +118,7 @@ describe('[startup] Utils', () => {
|
|
|
77
118
|
test(`passes "${option}" option to lerna`, () => {
|
|
78
119
|
subject();
|
|
79
120
|
|
|
80
|
-
|
|
81
|
-
'npx',
|
|
82
|
-
`lerna la --${option} foo --json`.split(' ')
|
|
83
|
-
);
|
|
121
|
+
expectExecaToBeCalledWith(`npx lerna la --${option} foo --json`);
|
|
84
122
|
});
|
|
85
123
|
});
|
|
86
124
|
|
|
@@ -101,6 +139,18 @@ describe('[startup] Utils', () => {
|
|
|
101
139
|
});
|
|
102
140
|
});
|
|
103
141
|
});
|
|
142
|
+
|
|
143
|
+
describe('when execa returns unexpected output', () => {
|
|
144
|
+
beforeEach(() =>
|
|
145
|
+
jest.mocked(execa.sync).mockReturnValue({ stdout: Buffer.from('foo') } as any)
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
test('throws an error and logs the output', () => {
|
|
149
|
+
const logSpy = jest.spyOn(log, 'error');
|
|
150
|
+
expect(() => subject()).toThrow();
|
|
151
|
+
expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('\nfoo'));
|
|
152
|
+
});
|
|
153
|
+
});
|
|
104
154
|
});
|
|
105
155
|
|
|
106
156
|
describe(`${getPackagesGraph.name}`, () => {
|
|
@@ -118,7 +168,7 @@ describe('[startup] Utils', () => {
|
|
|
118
168
|
|
|
119
169
|
test('returns lerna package graph', () => {
|
|
120
170
|
expect(subject()).toEqual(packageGraph);
|
|
121
|
-
|
|
171
|
+
expectExecaToBeCalledWith('npx lerna la --graph');
|
|
122
172
|
});
|
|
123
173
|
|
|
124
174
|
describe.each(['scope', 'ignore'])('with "%s"', option => {
|
|
@@ -127,16 +177,13 @@ describe('[startup] Utils', () => {
|
|
|
127
177
|
test(`passes "${option}" option to lerna`, () => {
|
|
128
178
|
subject();
|
|
129
179
|
|
|
130
|
-
|
|
131
|
-
'npx',
|
|
132
|
-
`lerna la --${option} foo --graph`.split(' ')
|
|
133
|
-
);
|
|
180
|
+
expectExecaToBeCalledWith(`npx lerna la --${option} foo --graph`);
|
|
134
181
|
});
|
|
135
182
|
});
|
|
136
183
|
});
|
|
137
184
|
|
|
138
185
|
describe(`${splitPackagesByType.name}`, () => {
|
|
139
|
-
const subject = (packages: Package[]) => splitPackagesByType(packages
|
|
186
|
+
const subject = (packages: Package[]) => splitPackagesByType(packages);
|
|
140
187
|
|
|
141
188
|
test('groups packages by type', () => {
|
|
142
189
|
expect(subject(packages as Package[])).toEqual(
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { fs, vol } from 'memfs';
|
|
2
|
+
|
|
3
|
+
import { maybeCreateGitFolder } from '../maybe-create-git-folder';
|
|
4
|
+
|
|
5
|
+
jest.mock('fs', () => fs);
|
|
6
|
+
|
|
7
|
+
describe(`[startup] Utils`, () => {
|
|
8
|
+
describe(`${maybeCreateGitFolder.name}`, () => {
|
|
9
|
+
const mkdirSpy = jest.spyOn(fs, 'mkdirSync').mockImplementation(jest.fn());
|
|
10
|
+
|
|
11
|
+
beforeEach(() => vol.fromJSON({}));
|
|
12
|
+
|
|
13
|
+
afterEach(() => vol.reset);
|
|
14
|
+
|
|
15
|
+
const subject = () => maybeCreateGitFolder();
|
|
16
|
+
|
|
17
|
+
describe('when running on Windows', () => {
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
Object.defineProperty(process, 'platform', { value: 'win32' });
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test('creates .git folder', () => {
|
|
23
|
+
subject();
|
|
24
|
+
|
|
25
|
+
expect(mkdirSpy).toHaveBeenCalledWith('.git');
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe('when not running on Windows', () => {
|
|
30
|
+
beforeEach(() => {
|
|
31
|
+
Object.defineProperty(process, 'platform', { value: 'linux' });
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('does not create .git folder', () => {
|
|
35
|
+
subject();
|
|
36
|
+
|
|
37
|
+
expect(mkdirSpy).not.toHaveBeenCalledWith();
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
});
|