@tramvai/cli 3.11.0 → 3.13.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/lib/api/start/providers/application/shared.d.ts.map +1 -1
- package/lib/api/start/providers/application/shared.js +5 -3
- package/lib/api/start/providers/application/shared.js.map +1 -1
- package/lib/api/start/providers/child-app/shared.d.ts.map +1 -1
- package/lib/api/start/providers/child-app/shared.js +6 -4
- package/lib/api/start/providers/child-app/shared.js.map +1 -1
- package/lib/api/start/providers/module/shared.d.ts.map +1 -1
- package/lib/api/start/providers/module/shared.js +6 -4
- package/lib/api/start/providers/module/shared.js.map +1 -1
- package/lib/api/start/utils/stopServer.d.ts.map +1 -1
- package/lib/api/start/utils/stopServer.js.map +1 -1
- package/lib/api/start-prod/application.d.ts.map +1 -1
- package/lib/api/start-prod/application.js +0 -2
- package/lib/api/start-prod/application.js.map +1 -1
- package/lib/api/start-prod/providers/shared.d.ts.map +1 -1
- package/lib/api/start-prod/providers/shared.js +3 -1
- package/lib/api/start-prod/providers/shared.js.map +1 -1
- package/lib/commands/analyze/command.d.ts.map +1 -1
- package/lib/commands/analyze/command.js +2 -0
- package/lib/commands/analyze/command.js.map +1 -1
- package/lib/commands/build/command.d.ts.map +1 -1
- package/lib/commands/build/command.js +2 -0
- package/lib/commands/build/command.js.map +1 -1
- package/lib/commands/start/command.d.ts.map +1 -1
- package/lib/commands/start/command.js +2 -0
- package/lib/commands/start/command.js.map +1 -1
- package/lib/commands/start-prod/command.d.ts.map +1 -1
- package/lib/commands/start-prod/command.js +2 -0
- package/lib/commands/start-prod/command.js.map +1 -1
- package/lib/commands/static/application.d.ts.map +1 -1
- package/lib/commands/static/application.js +8 -3
- package/lib/commands/static/application.js.map +1 -1
- package/lib/di/providers/network.d.ts.map +1 -1
- package/lib/di/providers/network.js +6 -0
- package/lib/di/providers/network.js.map +1 -1
- package/lib/models/port-manager.d.ts +21 -7
- package/lib/models/port-manager.d.ts.map +1 -1
- package/lib/models/port-manager.js +140 -26
- package/lib/models/port-manager.js.map +1 -1
- package/lib/schema/autogeneratedSchema.json +18 -18
- package/lib/typings/application.d.ts +8 -4
- package/lib/typings/application.d.ts.map +1 -1
- package/lib/typings/configEntry/cli.d.ts +1 -1
- package/lib/validators/commands/checkSwcDependencies.d.ts +3 -0
- package/lib/validators/commands/checkSwcDependencies.d.ts.map +1 -0
- package/lib/validators/commands/checkSwcDependencies.js +40 -0
- package/lib/validators/commands/checkSwcDependencies.js.map +1 -0
- package/package.json +5 -2
- package/schema.json +18 -18
- package/src/api/benchmark/__integration__/start.test.ts +0 -2
- package/src/api/start/__integration__/start.test.ts +14 -95
- package/src/api/start/providers/application/shared.ts +4 -2
- package/src/api/start/providers/child-app/shared.ts +5 -2
- package/src/api/start/providers/module/shared.ts +5 -2
- package/src/api/start/utils/stopServer.ts +1 -0
- package/src/api/start-prod/application.ts +1 -4
- package/src/api/start-prod/providers/shared.ts +5 -2
- package/src/commands/analyze/command.ts +2 -0
- package/src/commands/build/command.ts +2 -0
- package/src/commands/start/command.ts +2 -0
- package/src/commands/start-prod/command.ts +2 -0
- package/src/commands/static/application.ts +10 -4
- package/src/di/providers/network.ts +6 -0
- package/src/library/swc/__integration__/swc.start.test.ts +0 -2
- package/src/models/port-manager.ts +154 -35
- package/src/schema/autogeneratedSchema.json +18 -18
- package/src/typings/application.ts +8 -4
- package/src/typings/configEntry/cli.ts +1 -1
- package/src/validators/commands/checkSwcDependencies.spec.ts +117 -0
- package/src/validators/commands/checkSwcDependencies.ts +40 -0
|
@@ -1,29 +1,43 @@
|
|
|
1
|
+
import { access, outputFile, appendFile, readFile } from 'fs-extra';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import findCacheDir from 'find-cache-dir';
|
|
1
4
|
import detectPort from 'detect-port';
|
|
5
|
+
import { lock } from 'proper-lockfile';
|
|
2
6
|
|
|
3
7
|
import type { ConfigEntry } from '../typings/configEntry/common';
|
|
4
8
|
import type { Params as StartParams } from '../api/start';
|
|
5
9
|
import type { Params as StartProdParams } from '../api/start-prod';
|
|
10
|
+
import type { Logger } from './logger';
|
|
6
11
|
|
|
7
12
|
interface NetworkConstructorPayload {
|
|
8
13
|
configEntry: ConfigEntry;
|
|
9
14
|
commandParams: StartParams | StartProdParams;
|
|
15
|
+
logger: Logger;
|
|
10
16
|
}
|
|
11
17
|
|
|
12
18
|
export class PortManager {
|
|
13
|
-
static DEFAULT_PORT = 3000;
|
|
14
|
-
static DEFAULT_MODULE_PORT =
|
|
15
|
-
static DEFAULT_STATIC_PORT = 4000;
|
|
16
|
-
static DEFAULT_MODULE_STATIC_PORT = 4040;
|
|
19
|
+
static readonly DEFAULT_PORT = 3000;
|
|
20
|
+
static readonly DEFAULT_MODULE_PORT = 3040;
|
|
21
|
+
static readonly DEFAULT_STATIC_PORT = 4000;
|
|
22
|
+
static readonly DEFAULT_MODULE_STATIC_PORT = 4040;
|
|
17
23
|
|
|
18
|
-
private configEntry: ConfigEntry;
|
|
19
|
-
private commandParams: StartParams | StartProdParams;
|
|
24
|
+
private readonly configEntry: ConfigEntry;
|
|
25
|
+
private readonly commandParams: StartParams | StartProdParams;
|
|
26
|
+
private readonly cachePath: string;
|
|
27
|
+
private readonly logger: Logger;
|
|
20
28
|
|
|
21
29
|
public port: number | null = null;
|
|
22
30
|
public staticPort: number | null = null;
|
|
23
31
|
|
|
24
|
-
constructor({ configEntry, commandParams }: NetworkConstructorPayload) {
|
|
32
|
+
constructor({ configEntry, commandParams, logger }: NetworkConstructorPayload) {
|
|
25
33
|
this.configEntry = configEntry;
|
|
26
34
|
this.commandParams = commandParams;
|
|
35
|
+
this.logger = logger;
|
|
36
|
+
|
|
37
|
+
this.cachePath = join(
|
|
38
|
+
findCacheDir({ cwd: __dirname, create: true, name: 'tramvai' }),
|
|
39
|
+
'used-ports'
|
|
40
|
+
);
|
|
27
41
|
}
|
|
28
42
|
|
|
29
43
|
/**
|
|
@@ -33,47 +47,152 @@ export class PortManager {
|
|
|
33
47
|
* Also, handle zero port (it means any random port) as the edge case,
|
|
34
48
|
* because we must pass a final number to the config manager.
|
|
35
49
|
*/
|
|
36
|
-
public async computeAvailablePorts()
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
50
|
+
public async computeAvailablePorts() {
|
|
51
|
+
await this.createCacheFile();
|
|
52
|
+
const release = await this.lockCacheFile();
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
if (this.commandParams.port !== undefined && this.commandParams.port !== 0) {
|
|
56
|
+
// @ts-expect-error There is a string actually
|
|
57
|
+
this.port = parseInt(this.commandParams.port, 10);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (this.commandParams.staticPort !== undefined && this.commandParams.staticPort !== 0) {
|
|
61
|
+
// @ts-expect-error There is a string actually
|
|
62
|
+
this.staticPort = parseInt(this.commandParams.staticPort, 10);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
switch (this.configEntry.type) {
|
|
66
|
+
case 'child-app':
|
|
67
|
+
await this.forChildApp();
|
|
68
|
+
break;
|
|
69
|
+
|
|
70
|
+
case 'module':
|
|
71
|
+
await this.forModule();
|
|
72
|
+
break;
|
|
73
|
+
|
|
74
|
+
case 'application':
|
|
75
|
+
await this.forApplication();
|
|
76
|
+
break;
|
|
77
|
+
|
|
78
|
+
default:
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
await this.appendCacheFile([this.port, this.staticPort].join(','));
|
|
83
|
+
} catch (error) {
|
|
84
|
+
this.logger.event({
|
|
85
|
+
type: 'warning',
|
|
86
|
+
event: 'PORT_MANAGER:GET_AVAILABLE_PORTS',
|
|
87
|
+
message: `Can't get free ports for ${this.configEntry.type}:`,
|
|
88
|
+
payload: error.message ?? '',
|
|
89
|
+
});
|
|
90
|
+
} finally {
|
|
91
|
+
await release();
|
|
40
92
|
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Cleanup a cache file by removing ports were written previously.
|
|
97
|
+
*/
|
|
98
|
+
public async cleanup() {
|
|
99
|
+
const release = await this.lockCacheFile();
|
|
41
100
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
101
|
+
try {
|
|
102
|
+
const cache = await this.readCacheFile();
|
|
103
|
+
|
|
104
|
+
await this.writeCacheFile(
|
|
105
|
+
cache
|
|
106
|
+
.filter(Boolean)
|
|
107
|
+
.filter((port) => port !== this.port.toString() && port !== this.staticPort.toString())
|
|
108
|
+
.join(',')
|
|
109
|
+
);
|
|
110
|
+
} catch (error) {
|
|
111
|
+
this.logger.event({
|
|
112
|
+
type: 'warning',
|
|
113
|
+
event: 'PORT_MANAGER:CLEANUP',
|
|
114
|
+
message: "Can't perform a cleanup of previously used ports:",
|
|
115
|
+
payload: error.message ?? '',
|
|
116
|
+
});
|
|
117
|
+
} finally {
|
|
118
|
+
await release();
|
|
45
119
|
}
|
|
120
|
+
}
|
|
46
121
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
122
|
+
private async forApplication() {
|
|
123
|
+
this.port = this.port ?? (await this.resolveFreePort(PortManager.DEFAULT_PORT));
|
|
124
|
+
this.staticPort =
|
|
125
|
+
this.staticPort ?? (await this.resolveFreePort(PortManager.DEFAULT_STATIC_PORT));
|
|
126
|
+
}
|
|
51
127
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
128
|
+
private async forModule() {
|
|
129
|
+
this.port = this.port ?? (await this.resolveFreePort(PortManager.DEFAULT_MODULE_PORT));
|
|
130
|
+
this.staticPort =
|
|
131
|
+
this.staticPort ?? (await this.resolveFreePort(PortManager.DEFAULT_MODULE_STATIC_PORT));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
private async forChildApp() {
|
|
135
|
+
this.port = this.port ?? (await this.resolveFreePort(PortManager.DEFAULT_MODULE_PORT));
|
|
136
|
+
this.staticPort =
|
|
137
|
+
this.staticPort ?? (await this.resolveFreePort(PortManager.DEFAULT_MODULE_STATIC_PORT));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
private lockCacheFile() {
|
|
141
|
+
return lock(this.cachePath, { retries: 10 });
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private async createCacheFile() {
|
|
145
|
+
try {
|
|
146
|
+
await access(this.cachePath);
|
|
147
|
+
} catch (error) {
|
|
148
|
+
await outputFile(this.cachePath, '');
|
|
149
|
+
}
|
|
150
|
+
}
|
|
55
151
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
152
|
+
private async readCacheFile() {
|
|
153
|
+
try {
|
|
154
|
+
const content = await readFile(this.cachePath, { encoding: 'utf-8' });
|
|
59
155
|
|
|
60
|
-
|
|
61
|
-
|
|
156
|
+
return content.split(',');
|
|
157
|
+
} catch (error) {
|
|
158
|
+
return [];
|
|
62
159
|
}
|
|
63
160
|
}
|
|
64
161
|
|
|
65
|
-
private async
|
|
66
|
-
|
|
67
|
-
this.staticPort = this.staticPort ?? (await detectPort(PortManager.DEFAULT_STATIC_PORT));
|
|
162
|
+
private async writeCacheFile(content: string) {
|
|
163
|
+
await outputFile(this.cachePath, content);
|
|
68
164
|
}
|
|
69
165
|
|
|
70
|
-
private async
|
|
71
|
-
|
|
72
|
-
this.staticPort = this.staticPort ?? (await detectPort(PortManager.DEFAULT_MODULE_STATIC_PORT));
|
|
166
|
+
private async appendCacheFile(content: string) {
|
|
167
|
+
await appendFile(this.cachePath, `,${content}`);
|
|
73
168
|
}
|
|
74
169
|
|
|
75
|
-
private async
|
|
76
|
-
|
|
77
|
-
|
|
170
|
+
private async resolveFreePort(initial: number) {
|
|
171
|
+
try {
|
|
172
|
+
const cache = await this.readCacheFile();
|
|
173
|
+
let port = await detectPort(initial);
|
|
174
|
+
let attempts = 1;
|
|
175
|
+
|
|
176
|
+
while (cache.includes(port.toString())) {
|
|
177
|
+
if (attempts >= 3) {
|
|
178
|
+
throw new Error(`Max attempts exceeded (${attempts})`);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
port = await detectPort(0);
|
|
182
|
+
|
|
183
|
+
attempts++;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return port;
|
|
187
|
+
} catch (error) {
|
|
188
|
+
this.logger.event({
|
|
189
|
+
type: 'info',
|
|
190
|
+
event: 'PORT_MANAGER:RESOLVE_FREE_PORT',
|
|
191
|
+
message: "Can't resolve a free port, fallback to an initial one:",
|
|
192
|
+
payload: error.message ?? '',
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
return initial;
|
|
196
|
+
}
|
|
78
197
|
}
|
|
79
198
|
}
|
|
@@ -1144,23 +1144,23 @@
|
|
|
1144
1144
|
"dotAll": {
|
|
1145
1145
|
"type": "boolean"
|
|
1146
1146
|
},
|
|
1147
|
-
"__@match@
|
|
1147
|
+
"__@match@6850": {
|
|
1148
1148
|
"type": "object",
|
|
1149
1149
|
"additionalProperties": false
|
|
1150
1150
|
},
|
|
1151
|
-
"__@replace@
|
|
1151
|
+
"__@replace@6852": {
|
|
1152
1152
|
"type": "object",
|
|
1153
1153
|
"additionalProperties": false
|
|
1154
1154
|
},
|
|
1155
|
-
"__@search@
|
|
1155
|
+
"__@search@6855": {
|
|
1156
1156
|
"type": "object",
|
|
1157
1157
|
"additionalProperties": false
|
|
1158
1158
|
},
|
|
1159
|
-
"__@split@
|
|
1159
|
+
"__@split@6857": {
|
|
1160
1160
|
"type": "object",
|
|
1161
1161
|
"additionalProperties": false
|
|
1162
1162
|
},
|
|
1163
|
-
"__@matchAll@
|
|
1163
|
+
"__@matchAll@6859": {
|
|
1164
1164
|
"type": "object",
|
|
1165
1165
|
"additionalProperties": false
|
|
1166
1166
|
}
|
|
@@ -1402,7 +1402,7 @@
|
|
|
1402
1402
|
"singleton": {
|
|
1403
1403
|
"title": "if dependency is marked as singleton the dependency will be initialized only once and will not be updated",
|
|
1404
1404
|
"description": "Do not overuse that feature as it may lead to subtle bugs in case of different versions on different sides",
|
|
1405
|
-
"default":
|
|
1405
|
+
"default": false,
|
|
1406
1406
|
"type": "boolean"
|
|
1407
1407
|
}
|
|
1408
1408
|
},
|
|
@@ -1814,23 +1814,23 @@
|
|
|
1814
1814
|
"dotAll": {
|
|
1815
1815
|
"type": "boolean"
|
|
1816
1816
|
},
|
|
1817
|
-
"__@match@
|
|
1817
|
+
"__@match@6850": {
|
|
1818
1818
|
"type": "object",
|
|
1819
1819
|
"additionalProperties": false
|
|
1820
1820
|
},
|
|
1821
|
-
"__@replace@
|
|
1821
|
+
"__@replace@6852": {
|
|
1822
1822
|
"type": "object",
|
|
1823
1823
|
"additionalProperties": false
|
|
1824
1824
|
},
|
|
1825
|
-
"__@search@
|
|
1825
|
+
"__@search@6855": {
|
|
1826
1826
|
"type": "object",
|
|
1827
1827
|
"additionalProperties": false
|
|
1828
1828
|
},
|
|
1829
|
-
"__@split@
|
|
1829
|
+
"__@split@6857": {
|
|
1830
1830
|
"type": "object",
|
|
1831
1831
|
"additionalProperties": false
|
|
1832
1832
|
},
|
|
1833
|
-
"__@matchAll@
|
|
1833
|
+
"__@matchAll@6859": {
|
|
1834
1834
|
"type": "object",
|
|
1835
1835
|
"additionalProperties": false
|
|
1836
1836
|
}
|
|
@@ -2072,7 +2072,7 @@
|
|
|
2072
2072
|
"singleton": {
|
|
2073
2073
|
"title": "if dependency is marked as singleton the dependency will be initialized only once and will not be updated",
|
|
2074
2074
|
"description": "Do not overuse that feature as it may lead to subtle bugs in case of different versions on different sides",
|
|
2075
|
-
"default":
|
|
2075
|
+
"default": false,
|
|
2076
2076
|
"type": "boolean"
|
|
2077
2077
|
}
|
|
2078
2078
|
},
|
|
@@ -2484,23 +2484,23 @@
|
|
|
2484
2484
|
"dotAll": {
|
|
2485
2485
|
"type": "boolean"
|
|
2486
2486
|
},
|
|
2487
|
-
"__@match@
|
|
2487
|
+
"__@match@6850": {
|
|
2488
2488
|
"type": "object",
|
|
2489
2489
|
"additionalProperties": false
|
|
2490
2490
|
},
|
|
2491
|
-
"__@replace@
|
|
2491
|
+
"__@replace@6852": {
|
|
2492
2492
|
"type": "object",
|
|
2493
2493
|
"additionalProperties": false
|
|
2494
2494
|
},
|
|
2495
|
-
"__@search@
|
|
2495
|
+
"__@search@6855": {
|
|
2496
2496
|
"type": "object",
|
|
2497
2497
|
"additionalProperties": false
|
|
2498
2498
|
},
|
|
2499
|
-
"__@split@
|
|
2499
|
+
"__@split@6857": {
|
|
2500
2500
|
"type": "object",
|
|
2501
2501
|
"additionalProperties": false
|
|
2502
2502
|
},
|
|
2503
|
-
"__@matchAll@
|
|
2503
|
+
"__@matchAll@6859": {
|
|
2504
2504
|
"type": "object",
|
|
2505
2505
|
"additionalProperties": false
|
|
2506
2506
|
}
|
|
@@ -2742,7 +2742,7 @@
|
|
|
2742
2742
|
"singleton": {
|
|
2743
2743
|
"title": "if dependency is marked as singleton the dependency will be initialized only once and will not be updated",
|
|
2744
2744
|
"description": "Do not overuse that feature as it may lead to subtle bugs in case of different versions on different sides",
|
|
2745
|
-
"default":
|
|
2745
|
+
"default": false,
|
|
2746
2746
|
"type": "boolean"
|
|
2747
2747
|
}
|
|
2748
2748
|
},
|
|
@@ -20,19 +20,23 @@ declare module '*.woff2' {
|
|
|
20
20
|
type ImageString = string;
|
|
21
21
|
|
|
22
22
|
declare module '*.png' {
|
|
23
|
-
|
|
23
|
+
const src: ImageString;
|
|
24
|
+
export default src;
|
|
24
25
|
export const image: ImageObject;
|
|
25
26
|
}
|
|
26
27
|
declare module '*.jpg' {
|
|
27
|
-
|
|
28
|
+
const src: ImageString;
|
|
29
|
+
export default src;
|
|
28
30
|
export const image: ImageObject;
|
|
29
31
|
}
|
|
30
32
|
declare module '*.jpeg' {
|
|
31
|
-
|
|
33
|
+
const src: ImageString;
|
|
34
|
+
export default src;
|
|
32
35
|
export const image: ImageObject;
|
|
33
36
|
}
|
|
34
37
|
declare module '*.webp' {
|
|
35
|
-
|
|
38
|
+
const src: ImageString;
|
|
39
|
+
export default src;
|
|
36
40
|
export const image: ImageObject;
|
|
37
41
|
}
|
|
38
42
|
|
|
@@ -331,7 +331,7 @@ export interface CliConfigEntry extends ConfigEntry {
|
|
|
331
331
|
/**
|
|
332
332
|
* @title if dependency is marked as singleton the dependency will be initialized only once and will not be updated
|
|
333
333
|
* @description Do not overuse that feature as it may lead to subtle bugs in case of different versions on different sides
|
|
334
|
-
* @default
|
|
334
|
+
* @default false
|
|
335
335
|
*/
|
|
336
336
|
singleton: boolean;
|
|
337
337
|
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { sync as mockResolve } from 'resolve';
|
|
2
|
+
import type { Context } from '../../models/context';
|
|
3
|
+
import { checkSwcDependencies } from './checkSwcDependencies';
|
|
4
|
+
|
|
5
|
+
const mockSwcIntegration = (version, mockCliVersion, mockRootVersion) => {
|
|
6
|
+
jest.mock(
|
|
7
|
+
`/app/basedir/@tramvai/swc-integration/package.json`,
|
|
8
|
+
() => {
|
|
9
|
+
return { dependencies: { '@swc/core': version } };
|
|
10
|
+
},
|
|
11
|
+
{ virtual: true }
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
jest.mock(
|
|
15
|
+
`/app/@swc/core/package.json`,
|
|
16
|
+
() => {
|
|
17
|
+
return { version: mockCliVersion };
|
|
18
|
+
},
|
|
19
|
+
{ virtual: true }
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
jest.mock(
|
|
23
|
+
`/app/basedir/@swc/core/package.json`,
|
|
24
|
+
() => {
|
|
25
|
+
return { version: mockRootVersion };
|
|
26
|
+
},
|
|
27
|
+
{ virtual: true }
|
|
28
|
+
);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
jest.mock('resolve', () => ({
|
|
32
|
+
sync: jest
|
|
33
|
+
.fn((name) => require.resolve(name))
|
|
34
|
+
.mockImplementation((name, { basedir = '' } = {}) => {
|
|
35
|
+
if (basedir) {
|
|
36
|
+
return `/app/basedir/${name}`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return `/app/${name}`;
|
|
40
|
+
}),
|
|
41
|
+
}));
|
|
42
|
+
|
|
43
|
+
describe('validators/checkSwcDependencies', () => {
|
|
44
|
+
const mockLog = jest.fn();
|
|
45
|
+
const context = {} as Context;
|
|
46
|
+
|
|
47
|
+
beforeEach(() => {
|
|
48
|
+
mockLog.mockClear();
|
|
49
|
+
jest.resetModules();
|
|
50
|
+
(mockResolve as jest.Mock).mockClear();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('returns ok if there is no @tramvai/swc-integration', async () => {
|
|
54
|
+
expect(await checkSwcDependencies(context, {})).toMatchInlineSnapshot(`
|
|
55
|
+
{
|
|
56
|
+
"name": "checkSwcDependencies",
|
|
57
|
+
"status": "ok",
|
|
58
|
+
}
|
|
59
|
+
`);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('returns ok if there is @tramvai/swc-integration with correct version from root & cli', async () => {
|
|
63
|
+
mockSwcIntegration('1.0.0', '1.0.0', '1.0.0');
|
|
64
|
+
|
|
65
|
+
expect(await checkSwcDependencies(context, {})).toMatchInlineSnapshot(`
|
|
66
|
+
{
|
|
67
|
+
"name": "checkSwcDependencies",
|
|
68
|
+
"status": "ok",
|
|
69
|
+
}
|
|
70
|
+
`);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('returns error if there is @tramvai/swc-integration with different version from root & cli', async () => {
|
|
74
|
+
mockSwcIntegration('1.0.1', '1.0.0', '1.0.0');
|
|
75
|
+
|
|
76
|
+
expect(await checkSwcDependencies(context, {})).toMatchInlineSnapshot(`
|
|
77
|
+
{
|
|
78
|
+
"message": "Version of @swc/core mismatch between
|
|
79
|
+
@tramvai/swc-integration (version: 1.0.1),
|
|
80
|
+
@tramvai/cli (version: 1.0.0) and
|
|
81
|
+
process.cwd() (version: 1.0.0)",
|
|
82
|
+
"name": "checkSwcDependencies",
|
|
83
|
+
"status": "error",
|
|
84
|
+
}
|
|
85
|
+
`);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('returns error if there is correct version between @tramvai/swc-integration and root but different in cli', async () => {
|
|
89
|
+
mockSwcIntegration('1.0.0', '1.0.1', '1.0.0');
|
|
90
|
+
|
|
91
|
+
expect(await checkSwcDependencies(context, {})).toMatchInlineSnapshot(`
|
|
92
|
+
{
|
|
93
|
+
"message": "Version of @swc/core mismatch between
|
|
94
|
+
@tramvai/swc-integration (version: 1.0.0),
|
|
95
|
+
@tramvai/cli (version: 1.0.1) and
|
|
96
|
+
process.cwd() (version: 1.0.0)",
|
|
97
|
+
"name": "checkSwcDependencies",
|
|
98
|
+
"status": "error",
|
|
99
|
+
}
|
|
100
|
+
`);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('returns error if there is correct version between @tramvai/swc-integration and cli but different in root', async () => {
|
|
104
|
+
mockSwcIntegration('1.0.0', '1.0.0', '1.0.1');
|
|
105
|
+
|
|
106
|
+
expect(await checkSwcDependencies(context, {})).toMatchInlineSnapshot(`
|
|
107
|
+
{
|
|
108
|
+
"message": "Version of @swc/core mismatch between
|
|
109
|
+
@tramvai/swc-integration (version: 1.0.0),
|
|
110
|
+
@tramvai/cli (version: 1.0.0) and
|
|
111
|
+
process.cwd() (version: 1.0.1)",
|
|
112
|
+
"name": "checkSwcDependencies",
|
|
113
|
+
"status": "error",
|
|
114
|
+
}
|
|
115
|
+
`);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { sync as resolve } from 'resolve';
|
|
2
|
+
import type { Validator } from './validator.h';
|
|
3
|
+
|
|
4
|
+
export const checkSwcDependencies: Validator = async () => {
|
|
5
|
+
const rootDir = process.cwd();
|
|
6
|
+
const packagePath = `@swc/core/package.json`;
|
|
7
|
+
const pathFromCli = resolve(packagePath);
|
|
8
|
+
const pathFromRoot = resolve(packagePath, { basedir: rootDir });
|
|
9
|
+
const pathFromRootToIntegration = resolve(`@tramvai/swc-integration/package.json`, {
|
|
10
|
+
basedir: rootDir,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
let versionFromIntegration = '';
|
|
14
|
+
let versionFromRoot = '_from_root_version_';
|
|
15
|
+
let versionFromCli = '_from_cli_version_';
|
|
16
|
+
try {
|
|
17
|
+
versionFromIntegration = require(pathFromRootToIntegration).dependencies['@swc/core'];
|
|
18
|
+
versionFromRoot = require(pathFromRoot).version;
|
|
19
|
+
versionFromCli = require(pathFromCli).version;
|
|
20
|
+
} catch (e) {}
|
|
21
|
+
|
|
22
|
+
const allVersionsAreCorrect =
|
|
23
|
+
versionFromRoot === versionFromCli && versionFromCli === versionFromIntegration;
|
|
24
|
+
|
|
25
|
+
if (!versionFromIntegration || allVersionsAreCorrect) {
|
|
26
|
+
return {
|
|
27
|
+
name: 'checkSwcDependencies',
|
|
28
|
+
status: 'ok',
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
name: 'checkSwcDependencies',
|
|
34
|
+
status: 'error',
|
|
35
|
+
message: `Version of @swc/core mismatch between
|
|
36
|
+
@tramvai/swc-integration (version: ${versionFromIntegration}),
|
|
37
|
+
@tramvai/cli (version: ${versionFromCli}) and
|
|
38
|
+
process.cwd() (version: ${versionFromRoot})`,
|
|
39
|
+
};
|
|
40
|
+
};
|