@servicetitan/startup 29.0.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.
Files changed (106) hide show
  1. package/bin/index.js +1 -1
  2. package/dist/cli/commands/convert-eslint-config.d.ts +21 -0
  3. package/dist/cli/commands/convert-eslint-config.d.ts.map +1 -0
  4. package/dist/cli/commands/convert-eslint-config.js +235 -0
  5. package/dist/cli/commands/convert-eslint-config.js.map +1 -0
  6. package/dist/cli/commands/get-command.d.ts.map +1 -1
  7. package/dist/cli/commands/get-command.js +6 -0
  8. package/dist/cli/commands/get-command.js.map +1 -1
  9. package/dist/cli/commands/init.d.ts.map +1 -1
  10. package/dist/cli/commands/init.js +4 -3
  11. package/dist/cli/commands/init.js.map +1 -1
  12. package/dist/cli/commands/lint.d.ts +1 -1
  13. package/dist/cli/commands/lint.js +2 -2
  14. package/dist/cli/commands/run-task.d.ts +13 -0
  15. package/dist/cli/commands/run-task.d.ts.map +1 -0
  16. package/dist/cli/commands/run-task.js +53 -0
  17. package/dist/cli/commands/run-task.js.map +1 -0
  18. package/dist/cli/index.js +13 -4
  19. package/dist/cli/index.js.map +1 -1
  20. package/dist/cli/tasks/cli-task.d.ts +16 -0
  21. package/dist/cli/tasks/cli-task.d.ts.map +1 -0
  22. package/dist/cli/tasks/cli-task.js +58 -0
  23. package/dist/cli/tasks/cli-task.js.map +1 -0
  24. package/dist/cli/tasks/swc-compile-package.d.ts +12 -0
  25. package/dist/cli/tasks/swc-compile-package.d.ts.map +1 -0
  26. package/dist/cli/tasks/swc-compile-package.js +66 -0
  27. package/dist/cli/tasks/swc-compile-package.js.map +1 -0
  28. package/dist/cli/tasks/task.d.ts +42 -0
  29. package/dist/cli/tasks/task.d.ts.map +1 -0
  30. package/dist/cli/tasks/task.js +113 -0
  31. package/dist/cli/tasks/task.js.map +1 -0
  32. package/dist/cli/tasks/tsc-compile-package.d.ts +12 -0
  33. package/dist/cli/tasks/tsc-compile-package.d.ts.map +1 -0
  34. package/dist/cli/tasks/tsc-compile-package.js +42 -0
  35. package/dist/cli/tasks/tsc-compile-package.js.map +1 -0
  36. package/dist/cli/tasks/tsc-compile.d.ts +16 -0
  37. package/dist/cli/tasks/tsc-compile.d.ts.map +1 -0
  38. package/dist/cli/tasks/tsc-compile.js +48 -0
  39. package/dist/cli/tasks/tsc-compile.js.map +1 -0
  40. package/dist/cli/utils/bundle.js +1 -1
  41. package/dist/cli/utils/bundle.js.map +1 -1
  42. package/dist/cli/utils/cli-os.js +2 -2
  43. package/dist/cli/utils/cli-os.js.map +1 -1
  44. package/dist/cli/utils/eslint.d.ts.map +1 -1
  45. package/dist/cli/utils/eslint.js +13 -12
  46. package/dist/cli/utils/eslint.js.map +1 -1
  47. package/dist/cli/utils/is-module-installed.js +1 -1
  48. package/dist/cli/utils/is-module-installed.js.map +1 -1
  49. package/dist/cli/utils/tsc.d.ts +3 -2
  50. package/dist/cli/utils/tsc.d.ts.map +1 -1
  51. package/dist/cli/utils/tsc.js +20 -16
  52. package/dist/cli/utils/tsc.js.map +1 -1
  53. package/dist/utils/get-configuration.d.ts +3 -1
  54. package/dist/utils/get-configuration.d.ts.map +1 -1
  55. package/dist/utils/get-configuration.js +2 -0
  56. package/dist/utils/get-configuration.js.map +1 -1
  57. package/dist/utils/get-destination-folders.d.ts.map +1 -1
  58. package/dist/utils/get-destination-folders.js +9 -13
  59. package/dist/utils/get-destination-folders.js.map +1 -1
  60. package/dist/utils/get-folders.js +2 -2
  61. package/dist/utils/get-folders.js.map +1 -1
  62. package/dist/utils/log.d.ts +1 -0
  63. package/dist/utils/log.d.ts.map +1 -1
  64. package/dist/utils/log.js +3 -0
  65. package/dist/utils/log.js.map +1 -1
  66. package/dist/webpack/configs/plugins/ignore-plugin/check-resource.js +1 -1
  67. package/dist/webpack/configs/plugins/ignore-plugin/check-resource.js.map +1 -1
  68. package/package.json +15 -9
  69. package/src/cli/commands/__tests__/convert-eslint-config.test.ts +455 -0
  70. package/src/cli/commands/__tests__/lint.test.ts +2 -2
  71. package/src/cli/commands/convert-eslint-config.ts +289 -0
  72. package/src/cli/commands/get-command.ts +6 -0
  73. package/src/cli/commands/init.ts +4 -3
  74. package/src/cli/commands/lint.ts +3 -3
  75. package/src/cli/commands/run-task.ts +41 -0
  76. package/src/cli/index.ts +16 -4
  77. package/src/cli/tasks/__tests__/cli-task.test.ts +115 -0
  78. package/src/cli/tasks/__tests__/swc-compile.test.ts +192 -0
  79. package/src/cli/tasks/__tests__/task.test.ts +88 -0
  80. package/src/cli/tasks/__tests__/tsc-compile-package.test.ts +72 -0
  81. package/src/cli/tasks/__tests__/tsc-compile.test.ts +156 -0
  82. package/src/cli/tasks/cli-task.ts +64 -0
  83. package/src/cli/tasks/swc-cli.d.ts +3 -0
  84. package/src/cli/tasks/swc-compile-package.ts +70 -0
  85. package/src/cli/tasks/task.ts +112 -0
  86. package/src/cli/tasks/tsc-compile-package.ts +47 -0
  87. package/src/cli/tasks/tsc-compile.ts +64 -0
  88. package/src/cli/utils/__tests__/assets-copy.test.ts +1 -1
  89. package/src/cli/utils/__tests__/bundle.test.ts +1 -1
  90. package/src/cli/utils/__tests__/cli-os.test.ts +2 -2
  91. package/src/cli/utils/__tests__/eslint.test.ts +37 -8
  92. package/src/cli/utils/__tests__/styles-copy.test.ts +1 -1
  93. package/src/cli/utils/__tests__/tsc.test.ts +34 -55
  94. package/src/cli/utils/bundle.ts +1 -1
  95. package/src/cli/utils/cli-os.ts +2 -2
  96. package/src/cli/utils/eslint.ts +16 -13
  97. package/src/cli/utils/is-module-installed.ts +1 -1
  98. package/src/cli/utils/tsc.ts +25 -20
  99. package/src/utils/__tests__/get-destination-folders.test.ts +1 -1
  100. package/src/utils/__tests__/get-folders.test.ts +6 -18
  101. package/src/utils/__tests__/log.test.ts +6 -0
  102. package/src/utils/get-configuration.ts +2 -0
  103. package/src/utils/get-destination-folders.ts +11 -17
  104. package/src/utils/get-folders.ts +2 -2
  105. package/src/utils/log.ts +4 -0
  106. package/src/webpack/configs/plugins/ignore-plugin/check-resource.ts +1 -1
@@ -0,0 +1,192 @@
1
+ import { swcDir } from '@swc/cli';
2
+ import { log, readJson } from '../../../utils';
3
+ import { SwcCompilePackage } from '../swc-compile-package';
4
+ import { compilerOptions } from '../../../../tsconfig/base.json';
5
+
6
+ jest.mock('@swc/cli', () => ({
7
+ swcDir: jest.fn(),
8
+ }));
9
+
10
+ jest.mock('../../../utils', () => ({
11
+ getFolders: jest.fn().mockReturnValue({
12
+ source: 'src',
13
+ destination: 'dist',
14
+ }),
15
+ log: { info: jest.fn(), text: jest.fn() },
16
+ readJsonSafe: jest.fn().mockReturnValue({}),
17
+ readJson: jest.fn().mockReturnValue({}),
18
+ }));
19
+
20
+ describe(`[startup] ${SwcCompilePackage.name} task`, () => {
21
+ beforeEach(() => {
22
+ globalThis.performance.clearMarks();
23
+ globalThis.performance.clearMeasures();
24
+ jest.clearAllMocks();
25
+ jest.restoreAllMocks();
26
+ });
27
+
28
+ let watch = false;
29
+
30
+ const subject = () => new SwcCompilePackage({ watch }).execute();
31
+
32
+ const onSuccessHandlerParams = {
33
+ duration: 10,
34
+ };
35
+ const callOnSuccessHandler = (parameters: { duration: number }) => {
36
+ jest.mocked(swcDir).mock.calls[0][0].callbacks.onSuccess(parameters);
37
+ };
38
+
39
+ const onFailHandlerParams = {
40
+ duration: 10,
41
+ reasons: new Map([['index.js', 'Syntax error']]),
42
+ };
43
+ const callOnFailHandler = (parameters: { duration: number; reasons: Map<string, string> }) => {
44
+ jest.mocked(swcDir).mock.calls[0][0].callbacks.onFail(parameters);
45
+ };
46
+
47
+ test('calls swcDir', () => {
48
+ subject();
49
+
50
+ expect(swcDir).toHaveBeenCalledWith({
51
+ cliOptions: {
52
+ watch: false,
53
+ outDir: 'dist',
54
+ stripLeadingPaths: true,
55
+ extensions: ['.ts', '.tsx'],
56
+ filenames: ['src'],
57
+ },
58
+ swcOptions: {
59
+ jsc: {
60
+ parser: {
61
+ syntax: 'typescript',
62
+ tsx: true,
63
+ decorators: true,
64
+ },
65
+ target: compilerOptions.target,
66
+ transform: {
67
+ legacyDecorator: compilerOptions.experimentalDecorators,
68
+ decoratorMetadata: compilerOptions.emitDecoratorMetadata,
69
+ },
70
+ },
71
+ sourceMaps: compilerOptions.sourceMap,
72
+ module: {
73
+ type: 'es6',
74
+ },
75
+ },
76
+ callbacks: {
77
+ onSuccess: expect.any(Function),
78
+ onFail: expect.any(Function),
79
+ },
80
+ });
81
+ });
82
+
83
+ describe('when package is commonjs', () => {
84
+ beforeEach(() => {
85
+ jest.mocked(readJson).mockReturnValueOnce({
86
+ compilerOptions: { module: 'commonjs' },
87
+ });
88
+ });
89
+
90
+ test('swc module type is commonjs', () => {
91
+ subject();
92
+
93
+ expect(swcDir).toHaveBeenCalledWith(
94
+ expect.objectContaining({
95
+ swcOptions: expect.objectContaining({
96
+ module: { type: 'commonjs' },
97
+ }),
98
+ })
99
+ );
100
+ });
101
+ });
102
+
103
+ test('onSuccess handler completes task and logs completion message', async () => {
104
+ const task = subject();
105
+
106
+ callOnSuccessHandler(onSuccessHandlerParams);
107
+
108
+ await task;
109
+
110
+ expect(log.info).toHaveBeenCalledWith(
111
+ expect.stringMatching(
112
+ `swc-compile-package task completed in ${onSuccessHandlerParams.duration}ms`
113
+ )
114
+ );
115
+ });
116
+
117
+ test('onFail handler fails task and logs completion message', async () => {
118
+ const task = subject();
119
+
120
+ callOnFailHandler(onFailHandlerParams);
121
+
122
+ await expect(task).rejects.toThrow('Compilation failed');
123
+
124
+ expect(log.text).toHaveBeenCalledWith('Syntax error');
125
+
126
+ expect(log.info).toHaveBeenCalledWith(
127
+ expect.stringMatching(
128
+ `swc-compile-package task completed in ${onFailHandlerParams.duration}ms`
129
+ )
130
+ );
131
+ });
132
+
133
+ describe('in watch mode', () => {
134
+ beforeEach(() => (watch = true));
135
+
136
+ test('calls swcDir with watch=true', () => {
137
+ subject();
138
+
139
+ expect(swcDir).toHaveBeenCalledWith(
140
+ expect.objectContaining({
141
+ cliOptions: expect.objectContaining({
142
+ watch: true,
143
+ }),
144
+ })
145
+ );
146
+ });
147
+
148
+ test('onSuccess handler logs completion messages', () => {
149
+ subject();
150
+
151
+ callOnSuccessHandler(onSuccessHandlerParams);
152
+
153
+ expect(log.info).toHaveBeenCalledWith(
154
+ expect.stringMatching(
155
+ `Initial swc-compile-package task completed in ${onSuccessHandlerParams.duration}ms`
156
+ )
157
+ );
158
+
159
+ callOnSuccessHandler(onSuccessHandlerParams);
160
+
161
+ expect(log.info).toHaveBeenCalledWith(
162
+ expect.stringMatching(
163
+ `Subsequent swc-compile-package task completed in ${onSuccessHandlerParams.duration}ms`
164
+ )
165
+ );
166
+ });
167
+
168
+ test('onFail handler logs completion message', () => {
169
+ subject();
170
+
171
+ callOnFailHandler(onFailHandlerParams);
172
+
173
+ expect(log.text).toHaveBeenCalledWith('Syntax error');
174
+
175
+ expect(log.info).toHaveBeenCalledWith(
176
+ expect.stringMatching(
177
+ `Initial swc-compile-package task completed in ${onFailHandlerParams.duration}ms`
178
+ )
179
+ );
180
+
181
+ callOnFailHandler(onFailHandlerParams);
182
+
183
+ expect(log.text).toHaveBeenCalledWith('Syntax error');
184
+
185
+ expect(log.info).toHaveBeenCalledWith(
186
+ expect.stringMatching(
187
+ `Subsequent swc-compile-package task completed in ${onFailHandlerParams.duration}ms`
188
+ )
189
+ );
190
+ });
191
+ });
192
+ });
@@ -0,0 +1,88 @@
1
+ import { readJsonSafe } from '../../../utils';
2
+ import { Task } from '../task';
3
+
4
+ jest.mock('../../../utils', () => ({
5
+ readJsonSafe: jest.fn().mockReturnValue({}),
6
+ }));
7
+
8
+ class GlobalTask extends Task {
9
+ constructor() {
10
+ super({ name: 'GlobalTask', watch: false, global: true });
11
+ }
12
+
13
+ description() {
14
+ return '';
15
+ }
16
+
17
+ execute() {
18
+ return Promise.resolve();
19
+ }
20
+ }
21
+
22
+ class PackageTask extends Task {
23
+ constructor() {
24
+ super({ name: 'PackageTask', watch: false, global: false });
25
+ }
26
+
27
+ description() {
28
+ return '';
29
+ }
30
+
31
+ execute() {
32
+ return Promise.resolve();
33
+ }
34
+ }
35
+
36
+ describe(`[startup] ${Task.name} entity`, () => {
37
+ beforeEach(() => {
38
+ globalThis.performance.clearMarks();
39
+ globalThis.performance.clearMeasures();
40
+ jest.clearAllMocks();
41
+ });
42
+
43
+ describe('Global task', () => {
44
+ const subject = () => new GlobalTask();
45
+
46
+ test('runs from the workspace root directory', () => {
47
+ jest.mocked(readJsonSafe).mockReturnValueOnce({
48
+ workspaces: ['packages/*'],
49
+ });
50
+
51
+ expect(subject).not.toThrow();
52
+ });
53
+
54
+ test("doesn't run from the package directory", () => {
55
+ jest.mocked(readJsonSafe).mockReturnValueOnce({});
56
+
57
+ expect(subject).toThrow();
58
+ });
59
+
60
+ test("doesn't run from the arbitrary directory", () => {
61
+ jest.mocked(readJsonSafe).mockReturnValueOnce(undefined);
62
+
63
+ expect(subject).toThrow();
64
+ });
65
+ });
66
+
67
+ describe('Package task', () => {
68
+ const subject = () => new PackageTask();
69
+
70
+ test('runs from the package directory', () => {
71
+ jest.mocked(readJsonSafe).mockReturnValueOnce({});
72
+
73
+ expect(subject).not.toThrow();
74
+ });
75
+
76
+ test("doesn't run from the workspace root directory", () => {
77
+ jest.mocked(readJsonSafe).mockReturnValueOnce({ workspaces: ['packages/*'] });
78
+
79
+ expect(subject).toThrow();
80
+ });
81
+
82
+ test("doesn't run from arbitrary directory", () => {
83
+ jest.mocked(readJsonSafe).mockReturnValueOnce(undefined);
84
+
85
+ expect(subject).toThrow();
86
+ });
87
+ });
88
+ });
@@ -0,0 +1,72 @@
1
+ import execa from 'execa';
2
+ import { TscCompilePackage } from '../tsc-compile-package';
3
+
4
+ jest.mock('execa', () =>
5
+ jest.fn().mockReturnValue(
6
+ Object.assign(Promise.resolve(), {
7
+ stdout: {
8
+ on: jest.fn(),
9
+ },
10
+ })
11
+ )
12
+ );
13
+
14
+ const tsConfig = 'tsconfig.build.json';
15
+
16
+ const tscOptions = [
17
+ '--pretty',
18
+ '--preserveWatchOutput',
19
+ '--noCheck',
20
+ '--composite',
21
+ 'false',
22
+ '--declaration',
23
+ 'false',
24
+ '--declarationMap',
25
+ 'false',
26
+ '--tsBuildInfoFile',
27
+ 'tsconfig.compile.tsbuildinfo',
28
+ '--project',
29
+ tsConfig,
30
+ ];
31
+
32
+ jest.mock('../../../utils', () => ({
33
+ getFolders: jest.fn().mockReturnValue({
34
+ source: 'src',
35
+ destination: 'dist',
36
+ }),
37
+ log: { info: jest.fn() },
38
+ readJsonSafe: jest.fn().mockReturnValue({}),
39
+ getTsConfig: () => tsConfig,
40
+ }));
41
+
42
+ describe(`[startup] ${TscCompilePackage.name} task`, () => {
43
+ beforeEach(() => {
44
+ globalThis.performance.clearMarks();
45
+ globalThis.performance.clearMeasures();
46
+ jest.clearAllMocks();
47
+ });
48
+
49
+ let watch = false;
50
+
51
+ const subject = () => new TscCompilePackage({ watch }).execute();
52
+
53
+ test('calls execa', () => {
54
+ subject();
55
+
56
+ expect(execa).toHaveBeenCalledWith('tsc', tscOptions, {
57
+ stdio: 'inherit',
58
+ });
59
+ });
60
+
61
+ describe('in watch mode', () => {
62
+ beforeEach(() => (watch = true));
63
+
64
+ test('calls execa', () => {
65
+ subject();
66
+
67
+ expect(execa).toHaveBeenCalledWith('tsc', ['-w', ...tscOptions], {
68
+ stdio: ['inherit', 'pipe', 'inherit'],
69
+ });
70
+ });
71
+ });
72
+ });
@@ -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,3 @@
1
+ declare module '@swc/cli' {
2
+ function swcDir(options: any): void;
3
+ }
@@ -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
+ }