@servicetitan/startup 28.5.0 → 30.0.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/bin/index.js +1 -1
- package/dist/cli/commands/convert-eslint-config.d.ts +21 -0
- package/dist/cli/commands/convert-eslint-config.d.ts.map +1 -0
- package/dist/cli/commands/convert-eslint-config.js +235 -0
- package/dist/cli/commands/convert-eslint-config.js.map +1 -0
- package/dist/cli/commands/get-command.d.ts.map +1 -1
- package/dist/cli/commands/get-command.js +6 -0
- package/dist/cli/commands/get-command.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +4 -3
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/lint.d.ts +1 -1
- package/dist/cli/commands/lint.js +2 -2
- package/dist/cli/commands/mfe-package-clean.d.ts +5 -1
- package/dist/cli/commands/mfe-package-clean.d.ts.map +1 -1
- package/dist/cli/commands/mfe-package-clean.js +46 -36
- package/dist/cli/commands/mfe-package-clean.js.map +1 -1
- package/dist/cli/commands/mfe-package-publish.d.ts +1 -1
- package/dist/cli/commands/mfe-package-publish.d.ts.map +1 -1
- package/dist/cli/commands/mfe-package-publish.js +3 -13
- package/dist/cli/commands/mfe-package-publish.js.map +1 -1
- package/dist/cli/commands/mfe-publish.d.ts.map +1 -1
- package/dist/cli/commands/mfe-publish.js +6 -5
- package/dist/cli/commands/mfe-publish.js.map +1 -1
- package/dist/cli/commands/run-task.d.ts +13 -0
- package/dist/cli/commands/run-task.d.ts.map +1 -0
- package/dist/cli/commands/run-task.js +53 -0
- package/dist/cli/commands/run-task.js.map +1 -0
- package/dist/cli/index.js +13 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/tasks/cli-task.d.ts +16 -0
- package/dist/cli/tasks/cli-task.d.ts.map +1 -0
- package/dist/cli/tasks/cli-task.js +58 -0
- package/dist/cli/tasks/cli-task.js.map +1 -0
- package/dist/cli/tasks/swc-compile-package.d.ts +12 -0
- package/dist/cli/tasks/swc-compile-package.d.ts.map +1 -0
- package/dist/cli/tasks/swc-compile-package.js +66 -0
- package/dist/cli/tasks/swc-compile-package.js.map +1 -0
- package/dist/cli/tasks/task.d.ts +42 -0
- package/dist/cli/tasks/task.d.ts.map +1 -0
- package/dist/cli/tasks/task.js +113 -0
- package/dist/cli/tasks/task.js.map +1 -0
- package/dist/cli/tasks/tsc-compile-package.d.ts +12 -0
- package/dist/cli/tasks/tsc-compile-package.d.ts.map +1 -0
- package/dist/cli/tasks/tsc-compile-package.js +42 -0
- package/dist/cli/tasks/tsc-compile-package.js.map +1 -0
- package/dist/cli/tasks/tsc-compile.d.ts +16 -0
- package/dist/cli/tasks/tsc-compile.d.ts.map +1 -0
- package/dist/cli/tasks/tsc-compile.js +48 -0
- package/dist/cli/tasks/tsc-compile.js.map +1 -0
- package/dist/cli/utils/bundle.js +1 -1
- package/dist/cli/utils/bundle.js.map +1 -1
- package/dist/cli/utils/cli-npm.d.ts +10 -3
- package/dist/cli/utils/cli-npm.d.ts.map +1 -1
- package/dist/cli/utils/cli-npm.js +13 -15
- package/dist/cli/utils/cli-npm.js.map +1 -1
- package/dist/cli/utils/cli-os.d.ts.map +1 -1
- package/dist/cli/utils/cli-os.js +2 -2
- package/dist/cli/utils/cli-os.js.map +1 -1
- package/dist/cli/utils/eslint.d.ts.map +1 -1
- package/dist/cli/utils/eslint.js +13 -12
- package/dist/cli/utils/eslint.js.map +1 -1
- package/dist/cli/utils/is-module-installed.js +1 -1
- package/dist/cli/utils/is-module-installed.js.map +1 -1
- package/dist/cli/utils/publish.d.ts.map +1 -1
- package/dist/cli/utils/tsc.d.ts +3 -2
- package/dist/cli/utils/tsc.d.ts.map +1 -1
- package/dist/cli/utils/tsc.js +20 -16
- package/dist/cli/utils/tsc.js.map +1 -1
- package/dist/utils/get-configuration.d.ts +3 -1
- package/dist/utils/get-configuration.d.ts.map +1 -1
- package/dist/utils/get-configuration.js +2 -0
- package/dist/utils/get-configuration.js.map +1 -1
- package/dist/utils/get-destination-folders.d.ts.map +1 -1
- package/dist/utils/get-destination-folders.js +9 -13
- package/dist/utils/get-destination-folders.js.map +1 -1
- package/dist/utils/get-folders.js +2 -2
- package/dist/utils/get-folders.js.map +1 -1
- package/dist/utils/get-jest-config.d.ts.map +1 -1
- package/dist/utils/log.d.ts +1 -0
- package/dist/utils/log.d.ts.map +1 -1
- package/dist/utils/log.js +3 -0
- package/dist/utils/log.js.map +1 -1
- package/dist/webpack/configs/plugins/ignore-plugin/check-resource.d.ts.map +1 -1
- package/dist/webpack/configs/plugins/ignore-plugin/check-resource.js +1 -1
- package/dist/webpack/configs/plugins/ignore-plugin/check-resource.js.map +1 -1
- package/dist/webpack/utils/hash-mod.d.ts.map +1 -1
- package/dist/webpack/utils/testing/execute.d.ts.map +1 -1
- package/dist/webpack/utils/testing/get-compiler.d.ts.map +1 -1
- package/package.json +28 -24
- package/src/cli/commands/__tests__/convert-eslint-config.test.ts +455 -0
- package/src/cli/commands/__tests__/lint.test.ts +2 -2
- package/src/cli/commands/__tests__/mfe-package-clean.test.ts +143 -73
- package/src/cli/commands/__tests__/mfe-package-publish.test.ts +27 -20
- package/src/cli/commands/__tests__/mfe-publish.test.ts +18 -7
- package/src/cli/commands/convert-eslint-config.ts +289 -0
- package/src/cli/commands/get-command.ts +6 -0
- package/src/cli/commands/init.ts +4 -3
- package/src/cli/commands/lint.ts +3 -3
- package/src/cli/commands/mfe-package-clean.ts +53 -52
- package/src/cli/commands/mfe-package-publish.ts +7 -21
- package/src/cli/commands/mfe-publish.ts +6 -5
- package/src/cli/commands/run-task.ts +41 -0
- package/src/cli/index.ts +16 -4
- package/src/cli/tasks/__tests__/cli-task.test.ts +115 -0
- package/src/cli/tasks/__tests__/swc-compile.test.ts +192 -0
- package/src/cli/tasks/__tests__/task.test.ts +88 -0
- package/src/cli/tasks/__tests__/tsc-compile-package.test.ts +72 -0
- package/src/cli/tasks/__tests__/tsc-compile.test.ts +156 -0
- package/src/cli/tasks/cli-task.ts +64 -0
- package/src/cli/tasks/swc-cli.d.ts +3 -0
- package/src/cli/tasks/swc-compile-package.ts +70 -0
- package/src/cli/tasks/task.ts +112 -0
- package/src/cli/tasks/tsc-compile-package.ts +47 -0
- package/src/cli/tasks/tsc-compile.ts +64 -0
- package/src/cli/utils/__tests__/assets-copy.test.ts +1 -1
- package/src/cli/utils/__tests__/bundle.test.ts +1 -1
- package/src/cli/utils/__tests__/cli-npm.test.ts +39 -26
- package/src/cli/utils/__tests__/cli-os.test.ts +2 -2
- package/src/cli/utils/__tests__/eslint.test.ts +37 -8
- package/src/cli/utils/__tests__/styles-copy.test.ts +1 -1
- package/src/cli/utils/__tests__/tsc.test.ts +34 -55
- package/src/cli/utils/bundle.ts +1 -1
- package/src/cli/utils/cli-npm.ts +25 -16
- package/src/cli/utils/cli-os.ts +2 -2
- package/src/cli/utils/eslint.ts +16 -13
- package/src/cli/utils/is-module-installed.ts +1 -1
- package/src/cli/utils/tsc.ts +25 -20
- package/src/utils/__tests__/get-destination-folders.test.ts +1 -1
- package/src/utils/__tests__/get-folders.test.ts +6 -18
- package/src/utils/__tests__/log.test.ts +6 -0
- package/src/utils/get-configuration.ts +2 -0
- package/src/utils/get-destination-folders.ts +11 -17
- package/src/utils/get-folders.ts +2 -2
- package/src/utils/log.ts +4 -0
- package/src/webpack/configs/plugins/ignore-plugin/check-resource.ts +1 -1
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import execa from 'execa';
|
|
2
|
+
import { fs, vol } from 'memfs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { TscCompile } from '../tsc-compile';
|
|
5
|
+
|
|
6
|
+
jest.mock('fs', () => fs);
|
|
7
|
+
jest.mock('execa', () =>
|
|
8
|
+
jest.fn().mockReturnValue(
|
|
9
|
+
Object.assign(Promise.resolve(), {
|
|
10
|
+
stdout: {
|
|
11
|
+
on: jest.fn(),
|
|
12
|
+
},
|
|
13
|
+
})
|
|
14
|
+
)
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
describe(`[startup] ${TscCompile.name} task`, () => {
|
|
18
|
+
let watch = false;
|
|
19
|
+
let typeCheckOnly = false;
|
|
20
|
+
let scope: string[];
|
|
21
|
+
let ignore: string[];
|
|
22
|
+
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
vol.fromJSON({
|
|
25
|
+
'packages/foo/tsconfig.json': JSON.stringify({}),
|
|
26
|
+
'packages/foo/package.json': JSON.stringify({
|
|
27
|
+
name: 'foo',
|
|
28
|
+
cli: {
|
|
29
|
+
webpack: false,
|
|
30
|
+
},
|
|
31
|
+
dependencies: {
|
|
32
|
+
baz: '*',
|
|
33
|
+
},
|
|
34
|
+
}),
|
|
35
|
+
'packages/bar/tsconfig.json': JSON.stringify({}),
|
|
36
|
+
'packages/bar/package.json': JSON.stringify({
|
|
37
|
+
name: 'bar',
|
|
38
|
+
cli: {
|
|
39
|
+
webpack: false,
|
|
40
|
+
},
|
|
41
|
+
}),
|
|
42
|
+
'packages/baz/tsconfig.json': JSON.stringify({}),
|
|
43
|
+
'packages/baz/package.json': JSON.stringify({
|
|
44
|
+
name: 'baz',
|
|
45
|
+
cli: {
|
|
46
|
+
webpack: false,
|
|
47
|
+
},
|
|
48
|
+
}),
|
|
49
|
+
'package.json': JSON.stringify({ workspaces: ['packages/*'] }),
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
afterEach(() => {
|
|
54
|
+
vol.reset();
|
|
55
|
+
globalThis.performance.clearMarks();
|
|
56
|
+
globalThis.performance.clearMeasures();
|
|
57
|
+
jest.clearAllMocks();
|
|
58
|
+
watch = false;
|
|
59
|
+
typeCheckOnly = false;
|
|
60
|
+
scope = [];
|
|
61
|
+
ignore = [];
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
function itRunsTsc(
|
|
65
|
+
caption: string,
|
|
66
|
+
{
|
|
67
|
+
watch = false,
|
|
68
|
+
typeCheckOnly = false,
|
|
69
|
+
tsConfigs,
|
|
70
|
+
stdio,
|
|
71
|
+
}: {
|
|
72
|
+
watch?: boolean;
|
|
73
|
+
typeCheckOnly?: boolean;
|
|
74
|
+
tsConfigs: string[];
|
|
75
|
+
stdio: string | string[];
|
|
76
|
+
}
|
|
77
|
+
) {
|
|
78
|
+
test(`runs tsc ${caption}`, () => {
|
|
79
|
+
subject();
|
|
80
|
+
|
|
81
|
+
expect(execa).toHaveBeenCalledWith(
|
|
82
|
+
'tsc',
|
|
83
|
+
expect.arrayContaining(
|
|
84
|
+
[
|
|
85
|
+
'-b',
|
|
86
|
+
watch ? '-w' : undefined,
|
|
87
|
+
'--pretty',
|
|
88
|
+
'--preserveWatchOutput',
|
|
89
|
+
typeCheckOnly ? '--emitDeclarationOnly' : undefined,
|
|
90
|
+
...tsConfigs.map(config => expect.stringContaining(path.normalize(config))),
|
|
91
|
+
].filter(item => item !== undefined)
|
|
92
|
+
),
|
|
93
|
+
{
|
|
94
|
+
stdio,
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const subject = () => new TscCompile({ watch, typeCheckOnly, scope, ignore }).execute();
|
|
101
|
+
|
|
102
|
+
itRunsTsc('', {
|
|
103
|
+
tsConfigs: ['foo/tsconfig.json', 'bar/tsconfig.json'],
|
|
104
|
+
stdio: 'inherit',
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
describe('in watch mode', () => {
|
|
108
|
+
beforeEach(() => (watch = true));
|
|
109
|
+
|
|
110
|
+
itRunsTsc('in watch mode', {
|
|
111
|
+
watch: true,
|
|
112
|
+
tsConfigs: ['foo/tsconfig.json', 'bar/tsconfig.json'],
|
|
113
|
+
stdio: ['inherit', 'pipe', 'inherit'],
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
describe('with "typeCheckOnly" mode', () => {
|
|
118
|
+
beforeEach(() => (typeCheckOnly = true));
|
|
119
|
+
|
|
120
|
+
itRunsTsc('in "typeCheckOnly" mode', {
|
|
121
|
+
typeCheckOnly: true,
|
|
122
|
+
tsConfigs: ['foo/tsconfig.json', 'bar/tsconfig.json'],
|
|
123
|
+
stdio: 'inherit',
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
describe('with "scope"', () => {
|
|
128
|
+
beforeEach(() => (scope = ['foo']));
|
|
129
|
+
|
|
130
|
+
itRunsTsc('with only specified package', {
|
|
131
|
+
tsConfigs: ['foo/tsconfig.json'],
|
|
132
|
+
stdio: 'inherit',
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
describe('with "ignore"', () => {
|
|
137
|
+
beforeEach(() => (ignore = ['foo']));
|
|
138
|
+
|
|
139
|
+
itRunsTsc('without specified package', {
|
|
140
|
+
tsConfigs: ['baz/tsconfig.json', 'bar/tsconfig.json'],
|
|
141
|
+
stdio: 'inherit',
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
describe('with both "scope" and "ignore"', () => {
|
|
146
|
+
beforeEach(() => {
|
|
147
|
+
scope = ['ba*'];
|
|
148
|
+
ignore = ['bar'];
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
itRunsTsc('with combined filters', {
|
|
152
|
+
tsConfigs: ['baz/tsconfig.json'],
|
|
153
|
+
stdio: 'inherit',
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import execa from 'execa';
|
|
2
|
+
import { Task, TaskParameters } from './task';
|
|
3
|
+
|
|
4
|
+
export interface Indicators {
|
|
5
|
+
end: string;
|
|
6
|
+
watchStart: string;
|
|
7
|
+
watchEnd?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface CliTaskParameters extends TaskParameters {
|
|
11
|
+
indicators: Indicators;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export abstract class CliTask extends Task {
|
|
15
|
+
private readonly indicators: Indicators;
|
|
16
|
+
|
|
17
|
+
constructor({ indicators, ...rest }: CliTaskParameters) {
|
|
18
|
+
super(rest);
|
|
19
|
+
this.indicators = indicators;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
protected async runChildProcess(command: string, args: string[]) {
|
|
23
|
+
const childProcess = execa(
|
|
24
|
+
command,
|
|
25
|
+
args,
|
|
26
|
+
this.watch
|
|
27
|
+
? {
|
|
28
|
+
stdio: ['inherit', 'pipe', 'inherit'],
|
|
29
|
+
}
|
|
30
|
+
: {
|
|
31
|
+
stdio: 'inherit',
|
|
32
|
+
}
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
if (!this.watch) {
|
|
36
|
+
try {
|
|
37
|
+
await childProcess;
|
|
38
|
+
} finally {
|
|
39
|
+
this.logCompletionResults(this.taskTimer.end());
|
|
40
|
+
}
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
childProcess.stdout!.on('data', this.stdoutDataHandler);
|
|
45
|
+
await childProcess;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private readonly stdoutDataHandler = (data: Uint8Array | string) => {
|
|
49
|
+
process.stdout.write(data);
|
|
50
|
+
|
|
51
|
+
const dataStr = data.toString();
|
|
52
|
+
|
|
53
|
+
if (dataStr.includes(this.indicators.watchStart)) {
|
|
54
|
+
this.taskTimer.start();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (
|
|
58
|
+
dataStr.includes(this.indicators.end) ||
|
|
59
|
+
(this.indicators.watchEnd && dataStr.includes(this.indicators.watchEnd))
|
|
60
|
+
) {
|
|
61
|
+
this.logCompletionResults(this.taskTimer.end());
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { swcDir } from '@swc/cli';
|
|
2
|
+
import { compilerOptions as baseCompilerOptions } from '../../../tsconfig/base.json';
|
|
3
|
+
|
|
4
|
+
import { Task } from './task';
|
|
5
|
+
import { getFolders, log, readJson } from '../../utils';
|
|
6
|
+
|
|
7
|
+
interface Args {
|
|
8
|
+
[key: string]: unknown;
|
|
9
|
+
watch?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class SwcCompilePackage extends Task {
|
|
13
|
+
constructor({ watch }: Args) {
|
|
14
|
+
super({ name: 'swc-compile-package', global: false, watch });
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
description() {
|
|
18
|
+
return 'Compiles TypeScript files to JavaScript with SWC within package folder';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async execute(): Promise<void> {
|
|
22
|
+
const { source, destination } = getFolders();
|
|
23
|
+
const compilerOptions = readJson('tsconfig.json').compilerOptions ?? {};
|
|
24
|
+
|
|
25
|
+
return new Promise((resolve, reject) => {
|
|
26
|
+
swcDir({
|
|
27
|
+
cliOptions: {
|
|
28
|
+
watch: this.watch,
|
|
29
|
+
outDir: destination,
|
|
30
|
+
stripLeadingPaths: true,
|
|
31
|
+
extensions: ['.ts', '.tsx'],
|
|
32
|
+
filenames: [source],
|
|
33
|
+
},
|
|
34
|
+
swcOptions: {
|
|
35
|
+
jsc: {
|
|
36
|
+
parser: {
|
|
37
|
+
syntax: 'typescript',
|
|
38
|
+
tsx: true,
|
|
39
|
+
decorators: true,
|
|
40
|
+
},
|
|
41
|
+
target: baseCompilerOptions.target,
|
|
42
|
+
transform: {
|
|
43
|
+
legacyDecorator: baseCompilerOptions.experimentalDecorators,
|
|
44
|
+
decoratorMetadata: baseCompilerOptions.emitDecoratorMetadata,
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
sourceMaps: baseCompilerOptions.sourceMap,
|
|
48
|
+
module: {
|
|
49
|
+
type: compilerOptions.module === 'commonjs' ? 'commonjs' : 'es6',
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
callbacks: {
|
|
53
|
+
onSuccess: (e: { duration: number }) => {
|
|
54
|
+
this.logCompletionResults(this.taskTimer.add(e.duration));
|
|
55
|
+
if (!this.watch) {
|
|
56
|
+
resolve();
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
onFail: (e: { duration: number; reasons: Map<string, string> }) => {
|
|
60
|
+
log.text([...e.reasons.values()][0]);
|
|
61
|
+
this.logCompletionResults(this.taskTimer.add(e.duration));
|
|
62
|
+
if (!this.watch) {
|
|
63
|
+
reject(new Error('Compilation failed'));
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { log, readJsonSafe } from '../../utils';
|
|
2
|
+
|
|
3
|
+
class TaskTimer {
|
|
4
|
+
private counter = 0;
|
|
5
|
+
|
|
6
|
+
private get currentMarkName() {
|
|
7
|
+
return `${this.name}[${this.counter}]`;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
private get currentMarkList() {
|
|
11
|
+
return globalThis.performance.getEntriesByName(this.currentMarkName, 'mark');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
constructor(private readonly name: string) {
|
|
15
|
+
this.start();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
start() {
|
|
19
|
+
if (this.currentMarkList.length > 0) {
|
|
20
|
+
this.cancel();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
globalThis.performance.mark(this.currentMarkName);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
end() {
|
|
27
|
+
if (this.currentMarkList.length === 0) {
|
|
28
|
+
throw new Error(`There are no tasks in progress for ${this.currentMarkName}`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const measure = globalThis.performance.measure(this.currentMarkName, this.currentMarkName);
|
|
32
|
+
return { measure, counter: this.counter++ };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
cancel() {
|
|
36
|
+
if (this.currentMarkList.length === 0) {
|
|
37
|
+
throw new Error(`There are no tasks in progress for ${this.currentMarkName}`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const measure = globalThis.performance.measure(this.currentMarkName, {
|
|
41
|
+
start: this.currentMarkName,
|
|
42
|
+
detail: {
|
|
43
|
+
status: 'cancelled',
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
return { measure, counter: this.counter++ };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
add(duration: number) {
|
|
51
|
+
const measure = globalThis.performance.measure(this.currentMarkName, {
|
|
52
|
+
duration,
|
|
53
|
+
end: globalThis.performance.now(),
|
|
54
|
+
});
|
|
55
|
+
return { measure, counter: this.counter++ };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface TaskParameters {
|
|
60
|
+
name: string;
|
|
61
|
+
watch?: boolean;
|
|
62
|
+
global: boolean;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export abstract class Task {
|
|
66
|
+
protected readonly watch: boolean;
|
|
67
|
+
protected readonly taskTimer: TaskTimer;
|
|
68
|
+
private readonly name: string;
|
|
69
|
+
private readonly global: boolean;
|
|
70
|
+
|
|
71
|
+
constructor({ name, watch, global }: TaskParameters) {
|
|
72
|
+
this.name = name;
|
|
73
|
+
this.watch = !!watch;
|
|
74
|
+
this.global = global;
|
|
75
|
+
this.taskTimer = new TaskTimer(name);
|
|
76
|
+
this.checkRunLocation();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
protected logCompletionResults({
|
|
80
|
+
measure,
|
|
81
|
+
counter,
|
|
82
|
+
}: {
|
|
83
|
+
measure: PerformanceMeasure;
|
|
84
|
+
counter: number;
|
|
85
|
+
}) {
|
|
86
|
+
const enumerator = counter === 0 ? 'Initial ' : 'Subsequent ';
|
|
87
|
+
log.info(
|
|
88
|
+
`${this.watch ? enumerator : ''}${this.name} task completed in ${this.formatDuration(measure.duration)}`
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
private formatDuration(duration: number) {
|
|
93
|
+
if (duration < 1000) {
|
|
94
|
+
return `${duration.toFixed(0)}ms`;
|
|
95
|
+
}
|
|
96
|
+
return `${(duration / 1000).toFixed(2)}s`;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private checkRunLocation() {
|
|
100
|
+
const packageJson = readJsonSafe('package.json');
|
|
101
|
+
if (!packageJson?.workspaces && this.global) {
|
|
102
|
+
throw new Error(`Task ${this.name} has to run inside the workspace root directory`);
|
|
103
|
+
}
|
|
104
|
+
if ((!packageJson || packageJson.workspaces) && !this.global) {
|
|
105
|
+
throw new Error(`Task ${this.name} has to run inside the package directory`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
abstract description(): string;
|
|
110
|
+
|
|
111
|
+
abstract execute(): Promise<void>;
|
|
112
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { CliTask } from './cli-task';
|
|
2
|
+
import { getTsConfig } from '../../utils';
|
|
3
|
+
interface Args {
|
|
4
|
+
[key: string]: unknown;
|
|
5
|
+
watch?: boolean;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class TscCompilePackage extends CliTask {
|
|
9
|
+
constructor({ watch }: Args) {
|
|
10
|
+
super({
|
|
11
|
+
name: 'tsc-compile-package',
|
|
12
|
+
global: false,
|
|
13
|
+
indicators: {
|
|
14
|
+
end: 'Watching for file changes.',
|
|
15
|
+
watchStart: 'Starting incremental compilation.',
|
|
16
|
+
},
|
|
17
|
+
watch,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
description() {
|
|
22
|
+
return 'Compiles TypeScript files to JavaScript with TSC within package folder';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async execute() {
|
|
26
|
+
const tsConfig = getTsConfig();
|
|
27
|
+
await this.runChildProcess(
|
|
28
|
+
'tsc',
|
|
29
|
+
[
|
|
30
|
+
this.watch ? '-w' : undefined,
|
|
31
|
+
'--pretty',
|
|
32
|
+
'--preserveWatchOutput',
|
|
33
|
+
'--noCheck',
|
|
34
|
+
'--composite',
|
|
35
|
+
'false',
|
|
36
|
+
'--declaration',
|
|
37
|
+
'false',
|
|
38
|
+
'--declarationMap',
|
|
39
|
+
'false',
|
|
40
|
+
'--tsBuildInfoFile',
|
|
41
|
+
'tsconfig.compile.tsbuildinfo',
|
|
42
|
+
'--project',
|
|
43
|
+
tsConfig,
|
|
44
|
+
].filter(i => i !== undefined)
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getPackages,
|
|
3
|
+
getPackagesGraph,
|
|
4
|
+
getTsConfig,
|
|
5
|
+
Package,
|
|
6
|
+
PackageType,
|
|
7
|
+
splitPackagesByType,
|
|
8
|
+
} from '../../utils';
|
|
9
|
+
import { CliTask } from './cli-task';
|
|
10
|
+
|
|
11
|
+
interface Args {
|
|
12
|
+
[key: string]: unknown;
|
|
13
|
+
ignore?: string | string[];
|
|
14
|
+
scope?: string | string[];
|
|
15
|
+
watch?: boolean;
|
|
16
|
+
typeCheckOnly?: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class TscCompile extends CliTask {
|
|
20
|
+
constructor(private readonly args: Args) {
|
|
21
|
+
super({
|
|
22
|
+
name: 'tsc-compile',
|
|
23
|
+
watch: args.watch,
|
|
24
|
+
global: true,
|
|
25
|
+
indicators: {
|
|
26
|
+
end: 'Watching for file changes.',
|
|
27
|
+
watchStart: 'Starting incremental compilation.',
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
description() {
|
|
33
|
+
return 'Compiles one or more TypeScript projects with optional type checking';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async execute() {
|
|
37
|
+
const packages = splitPackagesByType(
|
|
38
|
+
getPackages({ scope: this.args.scope, ignore: this.args.ignore })
|
|
39
|
+
)[PackageType.TSC];
|
|
40
|
+
const tsConfigs = collapsePackages(packages).map(({ location }) => getTsConfig(location));
|
|
41
|
+
await this.runChildProcess(
|
|
42
|
+
'tsc',
|
|
43
|
+
[
|
|
44
|
+
'-b',
|
|
45
|
+
this.watch ? '-w' : undefined,
|
|
46
|
+
'--pretty',
|
|
47
|
+
'--preserveWatchOutput',
|
|
48
|
+
this.args.typeCheckOnly ? '--emitDeclarationOnly' : undefined,
|
|
49
|
+
...tsConfigs,
|
|
50
|
+
].filter(i => i !== undefined)
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Exclude dependant packages as they will be built through project references
|
|
57
|
+
*/
|
|
58
|
+
function collapsePackages(packages: Package[]) {
|
|
59
|
+
const dependencies = new Set(
|
|
60
|
+
Object.values(getPackagesGraph({ scope: packages.map(({ name }) => name) })).flat()
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
return packages.filter(({ name }) => !dependencies.has(name));
|
|
64
|
+
}
|
|
@@ -106,7 +106,7 @@ describe('[startup] Cli Utils', () => {
|
|
|
106
106
|
|
|
107
107
|
test('returns errors', () => {
|
|
108
108
|
const toStringSpy = jest.spyOn(stats, 'toString');
|
|
109
|
-
expect(subject).rejects.
|
|
109
|
+
expect(subject).rejects.toThrow(stats.toString());
|
|
110
110
|
expect(toStringSpy).toHaveBeenCalledWith('errors-only');
|
|
111
111
|
});
|
|
112
112
|
});
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { runCommand, runCommandOutput } from '../cli-os';
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
|
-
npmGetPackageVersionDates,
|
|
5
4
|
npmGetPackageVersions,
|
|
5
|
+
npmGetPackageVersionsDetails,
|
|
6
6
|
npmPackageSet,
|
|
7
7
|
npmPublish,
|
|
8
|
-
npmPublishDry,
|
|
9
8
|
npmTagVersion,
|
|
10
9
|
npmUnpublish,
|
|
11
10
|
} from '../cli-npm';
|
|
@@ -48,7 +47,7 @@ describe('[startup] Cli Utils (Npm)', () => {
|
|
|
48
47
|
});
|
|
49
48
|
}
|
|
50
49
|
|
|
51
|
-
describe(
|
|
50
|
+
describe(npmGetPackageVersions.name, () => {
|
|
52
51
|
let args: Parameters<typeof npmGetPackageVersions>;
|
|
53
52
|
|
|
54
53
|
beforeEach(() => (args = ['{registry}', '{packageName}']));
|
|
@@ -82,30 +81,42 @@ describe('[startup] Cli Utils (Npm)', () => {
|
|
|
82
81
|
});
|
|
83
82
|
});
|
|
84
83
|
|
|
85
|
-
describe(
|
|
86
|
-
let args: Parameters<typeof
|
|
84
|
+
describe(npmGetPackageVersionsDetails.name, () => {
|
|
85
|
+
let args: Parameters<typeof npmGetPackageVersionsDetails>;
|
|
87
86
|
|
|
88
|
-
beforeEach(() =>
|
|
87
|
+
beforeEach(() => {
|
|
88
|
+
jest.useFakeTimers();
|
|
89
|
+
args = ['{registry}', '{packageName}'];
|
|
90
|
+
});
|
|
89
91
|
|
|
90
|
-
|
|
92
|
+
afterEach(() => jest.useRealTimers());
|
|
91
93
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
94
|
+
const subject = () => npmGetPackageVersionsDetails(...args);
|
|
95
|
+
|
|
96
|
+
itRunsCommandOutput(
|
|
97
|
+
subject,
|
|
98
|
+
'npm view {packageName} time dist-tags --registry {registry} --json',
|
|
99
|
+
{ timeout: 10000 }
|
|
100
|
+
);
|
|
95
101
|
|
|
96
|
-
test('converts results to
|
|
102
|
+
test('converts results to Version[]', () => {
|
|
97
103
|
function dayAgo(count: number) {
|
|
98
104
|
const date = new Date();
|
|
99
105
|
date.setDate(-count);
|
|
100
106
|
return date;
|
|
101
107
|
}
|
|
102
|
-
const result = {
|
|
108
|
+
const result = {
|
|
109
|
+
'time': { '1.0.1': dayAgo(3), '2.1.0': dayAgo(2), '3.0.0': dayAgo(1) },
|
|
110
|
+
'dist-tags': { latest: '3.0.0' },
|
|
111
|
+
};
|
|
103
112
|
|
|
104
113
|
jest.mocked(runCommandOutput).mockReturnValue(JSON.stringify(result));
|
|
105
114
|
|
|
106
|
-
expect(subject()).toEqual(
|
|
107
|
-
|
|
108
|
-
|
|
115
|
+
expect(subject()).toEqual([
|
|
116
|
+
{ name: '1.0.1', date: dayAgo(3) },
|
|
117
|
+
{ name: '2.1.0', date: dayAgo(2) },
|
|
118
|
+
{ name: '3.0.0', date: dayAgo(1), tag: 'latest' },
|
|
119
|
+
]);
|
|
109
120
|
});
|
|
110
121
|
|
|
111
122
|
describe('when an error occurs', () => {
|
|
@@ -121,7 +132,7 @@ describe('[startup] Cli Utils (Npm)', () => {
|
|
|
121
132
|
});
|
|
122
133
|
});
|
|
123
134
|
|
|
124
|
-
describe(
|
|
135
|
+
describe(npmPackageSet.name, () => {
|
|
125
136
|
let args: Parameters<typeof npmPackageSet>;
|
|
126
137
|
|
|
127
138
|
beforeEach(() => (args = ['{key}', '{value}']));
|
|
@@ -131,27 +142,29 @@ describe('[startup] Cli Utils (Npm)', () => {
|
|
|
131
142
|
itRunsCommand(subject, 'npm pkg set {key}={value}');
|
|
132
143
|
});
|
|
133
144
|
|
|
134
|
-
describe(
|
|
135
|
-
let
|
|
145
|
+
describe(npmPublish.name, () => {
|
|
146
|
+
let options: Parameters<typeof npmPublish>[0];
|
|
136
147
|
|
|
137
|
-
beforeEach(() => (
|
|
148
|
+
beforeEach(() => (options = {}));
|
|
138
149
|
|
|
139
|
-
const subject = async () => npmPublish(
|
|
150
|
+
const subject = async () => npmPublish(options);
|
|
140
151
|
|
|
141
152
|
itRunsCommand(subject, 'npm publish');
|
|
142
153
|
|
|
143
154
|
describe('with a tag', () => {
|
|
144
|
-
beforeEach(() =>
|
|
155
|
+
beforeEach(() => (options.tag = '{tag}'));
|
|
145
156
|
|
|
146
157
|
itRunsCommand(subject, 'npm publish --tag {tag}');
|
|
147
158
|
});
|
|
148
|
-
});
|
|
149
159
|
|
|
150
|
-
|
|
151
|
-
|
|
160
|
+
describe('with {dry: true}', () => {
|
|
161
|
+
beforeEach(() => (options.dry = true));
|
|
162
|
+
|
|
163
|
+
itRunsCommand(subject, 'npm publish --dry-run');
|
|
164
|
+
});
|
|
152
165
|
});
|
|
153
166
|
|
|
154
|
-
describe(
|
|
167
|
+
describe(npmUnpublish.name, () => {
|
|
155
168
|
let args: Parameters<typeof npmUnpublish>;
|
|
156
169
|
|
|
157
170
|
beforeEach(() => (args = ['{registry}', '{packageName}', '{packageVersion}']));
|
|
@@ -165,7 +178,7 @@ describe('[startup] Cli Utils (Npm)', () => {
|
|
|
165
178
|
);
|
|
166
179
|
});
|
|
167
180
|
|
|
168
|
-
describe(
|
|
181
|
+
describe(npmTagVersion.name, () => {
|
|
169
182
|
let args: Parameters<typeof npmTagVersion>[0];
|
|
170
183
|
|
|
171
184
|
beforeEach(() => {
|
|
@@ -57,13 +57,13 @@ describe('[startup] Cli Utils (OS)', () => {
|
|
|
57
57
|
beforeEach(() => (exitCode = 2));
|
|
58
58
|
|
|
59
59
|
test('rejects promise', () => {
|
|
60
|
-
expect(subject('foo')).rejects.
|
|
60
|
+
expect(subject('foo')).rejects.toThrow(`command exited with code: ${exitCode}`);
|
|
61
61
|
});
|
|
62
62
|
});
|
|
63
63
|
|
|
64
64
|
['', [], ['']].forEach(command =>
|
|
65
65
|
test(`rejects promise when called with ${JSON.stringify(command)}`, () => {
|
|
66
|
-
expect(subject(command)).rejects.
|
|
66
|
+
expect(subject(command)).rejects.toThrow('invalid command');
|
|
67
67
|
})
|
|
68
68
|
);
|
|
69
69
|
|