@adonisjs/assembler 6.1.3-2 → 6.1.3-21
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/LICENSE.md +1 -1
- package/README.md +3 -6
- package/build/index.d.ts +1 -0
- package/build/index.js +9 -0
- package/build/src/assets_dev_server.d.ts +32 -0
- package/build/src/assets_dev_server.js +158 -0
- package/build/src/bundler.d.ts +9 -0
- package/build/src/bundler.js +70 -17
- package/build/src/code_transformer/main.d.ts +28 -0
- package/build/src/code_transformer/main.js +201 -0
- package/build/src/code_transformer/rc_file_transformer.d.ts +43 -0
- package/build/src/code_transformer/rc_file_transformer.js +272 -0
- package/build/src/debug.d.ts +3 -0
- package/build/src/debug.js +10 -0
- package/build/src/dev_server.d.ts +32 -0
- package/build/src/dev_server.js +146 -179
- package/build/src/helpers.d.ts +50 -0
- package/build/src/helpers.js +183 -0
- package/build/src/test_runner.d.ts +47 -0
- package/build/src/test_runner.js +310 -0
- package/build/src/types.d.ts +102 -0
- package/build/src/types.js +8 -0
- package/package.json +52 -66
- package/build/src/parse_config.d.ts +0 -3
- package/build/src/parse_config.js +0 -15
- package/build/src/run.d.ts +0 -4
- package/build/src/run.js +0 -37
- package/build/src/watch.d.ts +0 -8
- package/build/src/watch.js +0 -12
package/build/src/dev_server.js
CHANGED
|
@@ -1,23 +1,46 @@
|
|
|
1
|
-
|
|
1
|
+
/*
|
|
2
|
+
* @adonisjs/assembler
|
|
3
|
+
*
|
|
4
|
+
* (c) AdonisJS
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
2
9
|
import picomatch from 'picomatch';
|
|
3
10
|
import { cliui } from '@poppinss/cliui';
|
|
4
|
-
import {
|
|
5
|
-
import { watch } from './
|
|
6
|
-
|
|
11
|
+
import { AssetsDevServer } from './assets_dev_server.js';
|
|
12
|
+
import { getPort, isDotEnvFile, isRcFile, runNode, watch } from './helpers.js';
|
|
13
|
+
/**
|
|
14
|
+
* Instance of CLIUI
|
|
15
|
+
*/
|
|
7
16
|
const ui = cliui();
|
|
17
|
+
/**
|
|
18
|
+
* Exposes the API to start the development. Optionally, the watch API can be
|
|
19
|
+
* used to watch for file changes and restart the development server.
|
|
20
|
+
*
|
|
21
|
+
* The Dev server performs the following actions
|
|
22
|
+
*
|
|
23
|
+
* - Assigns a random PORT, when PORT inside .env file is in use
|
|
24
|
+
* - Uses tsconfig.json file to collect a list of files to watch.
|
|
25
|
+
* - Uses metaFiles from .adonisrc.json file to collect a list of files to watch.
|
|
26
|
+
* - Restart HTTP server on every file change.
|
|
27
|
+
*/
|
|
8
28
|
export class DevServer {
|
|
9
29
|
#cwd;
|
|
10
30
|
#logger = ui.logger;
|
|
11
31
|
#options;
|
|
12
32
|
#isWatching = false;
|
|
13
33
|
#scriptFile = 'bin/server.js';
|
|
14
|
-
#httpServerProcess;
|
|
15
34
|
#isMetaFileWithReloadsEnabled;
|
|
16
35
|
#isMetaFileWithReloadsDisabled;
|
|
17
|
-
#watcher;
|
|
18
|
-
#assetsServerProcess;
|
|
19
36
|
#onError;
|
|
20
37
|
#onClose;
|
|
38
|
+
#httpServer;
|
|
39
|
+
#watcher;
|
|
40
|
+
#assetsServer;
|
|
41
|
+
/**
|
|
42
|
+
* Getting reference to colors library from logger
|
|
43
|
+
*/
|
|
21
44
|
get #colors() {
|
|
22
45
|
return this.#logger.getColors();
|
|
23
46
|
}
|
|
@@ -31,15 +54,9 @@ export class DevServer {
|
|
|
31
54
|
.filter(({ reloadServer }) => reloadServer !== true)
|
|
32
55
|
.map(({ pattern }) => pattern));
|
|
33
56
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
return filePath.includes('.env.');
|
|
39
|
-
}
|
|
40
|
-
#isRcFile(filePath) {
|
|
41
|
-
return filePath === '.adonisrc.json';
|
|
42
|
-
}
|
|
57
|
+
/**
|
|
58
|
+
* Inspect if child process message is from AdonisJS HTTP server
|
|
59
|
+
*/
|
|
43
60
|
#isAdonisJSReadyMessage(message) {
|
|
44
61
|
return (message !== null &&
|
|
45
62
|
typeof message === 'object' &&
|
|
@@ -47,65 +64,25 @@ export class DevServer {
|
|
|
47
64
|
'environment' in message &&
|
|
48
65
|
message.environment === 'web');
|
|
49
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Conditionally clear the terminal screen
|
|
69
|
+
*/
|
|
50
70
|
#clearScreen() {
|
|
51
71
|
if (this.#options.clearScreen) {
|
|
52
72
|
process.stdout.write('\u001Bc');
|
|
53
73
|
}
|
|
54
74
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if (dataString.includes('ready in')) {
|
|
59
|
-
console.log('');
|
|
60
|
-
console.log(dataString.trim());
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
if (dataString.includes('Local') && dataString.includes('Network')) {
|
|
64
|
-
const sticker = ui.sticker().useColors(this.#colors).useRenderer(this.#logger.getRenderer());
|
|
65
|
-
lines.forEach((line) => {
|
|
66
|
-
if (line.trim()) {
|
|
67
|
-
sticker.add(line);
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
sticker.render();
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
lines.forEach((line) => {
|
|
74
|
-
if (line.trim()) {
|
|
75
|
-
console.log(line);
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
#logAssetsDevServerMessage(data) {
|
|
80
|
-
const dataString = data.toString();
|
|
81
|
-
const lines = dataString.split('\n');
|
|
82
|
-
lines.forEach((line) => {
|
|
83
|
-
if (line.trim()) {
|
|
84
|
-
console.log(line);
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
async #getPort() {
|
|
89
|
-
if (process.env.PORT) {
|
|
90
|
-
return getPort({ port: Number(process.env.PORT) });
|
|
91
|
-
}
|
|
92
|
-
const files = await new EnvLoader(this.#cwd).load();
|
|
93
|
-
for (let file of files) {
|
|
94
|
-
const envVariables = new EnvParser(file.contents).parse();
|
|
95
|
-
if (envVariables.PORT) {
|
|
96
|
-
return getPort({ port: Number(envVariables.PORT) });
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
return getPort({ port: 3333 });
|
|
100
|
-
}
|
|
75
|
+
/**
|
|
76
|
+
* Starts the HTTP server
|
|
77
|
+
*/
|
|
101
78
|
#startHTTPServer(port, mode) {
|
|
102
|
-
this.#
|
|
79
|
+
this.#httpServer = runNode(this.#cwd, {
|
|
103
80
|
script: this.#scriptFile,
|
|
104
81
|
env: { PORT: port, ...this.#options.env },
|
|
105
82
|
nodeArgs: this.#options.nodeArgs,
|
|
106
83
|
scriptArgs: this.#options.scriptArgs,
|
|
107
84
|
});
|
|
108
|
-
this.#
|
|
85
|
+
this.#httpServer.on('message', (message) => {
|
|
109
86
|
if (this.#isAdonisJSReadyMessage(message)) {
|
|
110
87
|
ui.sticker()
|
|
111
88
|
.useColors(this.#colors)
|
|
@@ -115,172 +92,162 @@ export class DevServer {
|
|
|
115
92
|
.render();
|
|
116
93
|
}
|
|
117
94
|
});
|
|
118
|
-
this.#
|
|
95
|
+
this.#httpServer
|
|
119
96
|
.then((result) => {
|
|
120
|
-
this.#logger.warning(`underlying HTTP server closed with status code "${result.exitCode}"`);
|
|
121
97
|
if (mode === 'nonblocking') {
|
|
122
98
|
this.#onClose?.(result.exitCode);
|
|
123
99
|
this.#watcher?.close();
|
|
100
|
+
this.#assetsServer?.stop();
|
|
124
101
|
}
|
|
125
102
|
})
|
|
126
103
|
.catch((error) => {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
104
|
+
if (mode === 'nonblocking') {
|
|
105
|
+
this.#onError?.(error);
|
|
106
|
+
this.#watcher?.close();
|
|
107
|
+
this.#assetsServer?.stop();
|
|
108
|
+
}
|
|
131
109
|
});
|
|
132
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* Starts the assets server
|
|
113
|
+
*/
|
|
133
114
|
#startAssetsServer() {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
115
|
+
this.#assetsServer = new AssetsDevServer(this.#cwd, this.#options.assets);
|
|
116
|
+
this.#assetsServer.setLogger(this.#logger);
|
|
117
|
+
this.#assetsServer.start();
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Restarts the HTTP server
|
|
121
|
+
*/
|
|
122
|
+
#restartHTTPServer(port) {
|
|
123
|
+
if (this.#httpServer) {
|
|
124
|
+
this.#httpServer.removeAllListeners();
|
|
125
|
+
this.#httpServer.kill('SIGKILL');
|
|
137
126
|
}
|
|
138
|
-
this.#
|
|
139
|
-
this.#assetsServerProcess = run(this.#cwd, {
|
|
140
|
-
script: assetsBundler.cmd,
|
|
141
|
-
stdio: 'pipe',
|
|
142
|
-
scriptArgs: this.#options.scriptArgs,
|
|
143
|
-
});
|
|
144
|
-
this.#assetsServerProcess.stdout?.on('data', (data) => {
|
|
145
|
-
if (assetsBundler.driver === 'vite') {
|
|
146
|
-
this.#logViteDevServerMessage(data);
|
|
147
|
-
}
|
|
148
|
-
else {
|
|
149
|
-
this.#logAssetsDevServerMessage(data);
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
this.#assetsServerProcess.stderr?.on('data', (data) => {
|
|
153
|
-
if (assetsBundler.driver === 'vite') {
|
|
154
|
-
this.#logViteDevServerMessage(data);
|
|
155
|
-
}
|
|
156
|
-
else {
|
|
157
|
-
this.#logAssetsDevServerMessage(data);
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
this.#assetsServerProcess
|
|
161
|
-
.then((result) => {
|
|
162
|
-
this.#logger.warning(`"${assetsBundler.driver}" dev server closed with status code "${result.exitCode}"`);
|
|
163
|
-
})
|
|
164
|
-
.catch((error) => {
|
|
165
|
-
this.#logger.warning(`unable to connect to "${assetsBundler.driver}" dev server`);
|
|
166
|
-
this.#logger.fatal(error);
|
|
167
|
-
});
|
|
127
|
+
this.#startHTTPServer(port, 'blocking');
|
|
168
128
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
129
|
+
/**
|
|
130
|
+
* Handles a non TypeScript file change
|
|
131
|
+
*/
|
|
132
|
+
#handleFileChange(action, port, relativePath) {
|
|
133
|
+
if (isDotEnvFile(relativePath) || isRcFile(relativePath)) {
|
|
134
|
+
this.#clearScreen();
|
|
135
|
+
this.#logger.log(`${this.#colors.green(action)} ${relativePath}`);
|
|
136
|
+
this.#restartHTTPServer(port);
|
|
137
|
+
return;
|
|
173
138
|
}
|
|
174
|
-
this.#
|
|
139
|
+
if (this.#isMetaFileWithReloadsEnabled(relativePath)) {
|
|
140
|
+
this.#clearScreen();
|
|
141
|
+
this.#logger.log(`${this.#colors.green(action)} ${relativePath}`);
|
|
142
|
+
this.#restartHTTPServer(port);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (this.#isMetaFileWithReloadsDisabled(relativePath)) {
|
|
146
|
+
this.#clearScreen();
|
|
147
|
+
this.#logger.log(`${this.#colors.green(action)} ${relativePath}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Handles TypeScript source file change
|
|
152
|
+
*/
|
|
153
|
+
#handleSourceFileChange(action, port, relativePath) {
|
|
154
|
+
this.#clearScreen();
|
|
155
|
+
this.#logger.log(`${this.#colors.green(action)} ${relativePath}`);
|
|
156
|
+
this.#restartHTTPServer(port);
|
|
175
157
|
}
|
|
158
|
+
/**
|
|
159
|
+
* Set a custom CLI UI logger
|
|
160
|
+
*/
|
|
176
161
|
setLogger(logger) {
|
|
177
162
|
this.#logger = logger;
|
|
163
|
+
this.#assetsServer?.setLogger(logger);
|
|
178
164
|
return this;
|
|
179
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* Add listener to get notified when dev server is
|
|
168
|
+
* closed
|
|
169
|
+
*/
|
|
180
170
|
onClose(callback) {
|
|
181
171
|
this.#onClose = callback;
|
|
182
172
|
return this;
|
|
183
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* Add listener to get notified when dev server exists
|
|
176
|
+
* with an error
|
|
177
|
+
*/
|
|
184
178
|
onError(callback) {
|
|
185
179
|
this.#onError = callback;
|
|
186
180
|
return this;
|
|
187
181
|
}
|
|
182
|
+
/**
|
|
183
|
+
* Close watchers and running child processes
|
|
184
|
+
*/
|
|
185
|
+
async close() {
|
|
186
|
+
await this.#watcher?.close();
|
|
187
|
+
this.#assetsServer?.stop();
|
|
188
|
+
if (this.#httpServer) {
|
|
189
|
+
this.#httpServer.removeAllListeners();
|
|
190
|
+
this.#httpServer.kill('SIGKILL');
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Start the development server
|
|
195
|
+
*/
|
|
188
196
|
async start() {
|
|
189
197
|
this.#clearScreen();
|
|
190
198
|
this.#logger.info('starting HTTP server...');
|
|
191
|
-
this.#startHTTPServer(String(await this.#
|
|
199
|
+
this.#startHTTPServer(String(await getPort(this.#cwd)), 'nonblocking');
|
|
192
200
|
this.#startAssetsServer();
|
|
193
201
|
}
|
|
202
|
+
/**
|
|
203
|
+
* Start the development server in watch mode
|
|
204
|
+
*/
|
|
194
205
|
async startAndWatch(ts, options) {
|
|
195
|
-
const port = String(await this.#
|
|
206
|
+
const port = String(await getPort(this.#cwd));
|
|
196
207
|
this.#isWatching = true;
|
|
197
208
|
this.#clearScreen();
|
|
198
209
|
this.#logger.info('starting HTTP server...');
|
|
199
210
|
this.#startHTTPServer(port, 'blocking');
|
|
200
211
|
this.#startAssetsServer();
|
|
212
|
+
/**
|
|
213
|
+
* Create watcher using tsconfig.json file
|
|
214
|
+
*/
|
|
201
215
|
const output = watch(this.#cwd, ts, options || {});
|
|
202
216
|
if (!output) {
|
|
203
217
|
this.#onClose?.(1);
|
|
204
218
|
return;
|
|
205
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* Storing reference to watcher, so that we can close it
|
|
222
|
+
* when HTTP server exists with error
|
|
223
|
+
*/
|
|
206
224
|
this.#watcher = output.chokidar;
|
|
225
|
+
/**
|
|
226
|
+
* Notify the watcher is ready
|
|
227
|
+
*/
|
|
207
228
|
output.watcher.on('watcher:ready', () => {
|
|
208
229
|
this.#logger.info('watching file system for changes...');
|
|
209
230
|
});
|
|
231
|
+
/**
|
|
232
|
+
* Cleanup when watcher dies
|
|
233
|
+
*/
|
|
210
234
|
output.chokidar.on('error', (error) => {
|
|
211
235
|
this.#logger.warning('file system watcher failure');
|
|
212
236
|
this.#logger.fatal(error);
|
|
213
237
|
this.#onError?.(error);
|
|
214
238
|
output.chokidar.close();
|
|
215
239
|
});
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
});
|
|
221
|
-
output.watcher.on('source:
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
});
|
|
226
|
-
output.watcher.on('
|
|
227
|
-
|
|
228
|
-
this.#logger.log(`${this.#colors.green('delete')} ${relativePath}`);
|
|
229
|
-
this.#restart(port);
|
|
230
|
-
});
|
|
231
|
-
output.watcher.on('add', ({ relativePath }) => {
|
|
232
|
-
if (this.#isDotEnvFile(relativePath) || this.#isRcFile(relativePath)) {
|
|
233
|
-
this.#clearScreen();
|
|
234
|
-
this.#logger.log(`${this.#colors.green('add')} ${relativePath}`);
|
|
235
|
-
this.#restart(port);
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
if (this.#isMetaFileWithReloadsEnabled(relativePath)) {
|
|
239
|
-
this.#clearScreen();
|
|
240
|
-
this.#logger.log(`${this.#colors.green('add')} ${relativePath}`);
|
|
241
|
-
this.#restart(port);
|
|
242
|
-
return;
|
|
243
|
-
}
|
|
244
|
-
if (this.#isMetaFileWithReloadsDisabled(relativePath)) {
|
|
245
|
-
this.#clearScreen();
|
|
246
|
-
this.#logger.log(`${this.#colors.green('add')} ${relativePath}`);
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
output.watcher.on('change', ({ relativePath }) => {
|
|
250
|
-
if (this.#isDotEnvFile(relativePath) || this.#isRcFile(relativePath)) {
|
|
251
|
-
this.#clearScreen();
|
|
252
|
-
this.#logger.log(`${this.#colors.green('update')} ${relativePath}`);
|
|
253
|
-
this.#restart(port);
|
|
254
|
-
return;
|
|
255
|
-
}
|
|
256
|
-
if (this.#isMetaFileWithReloadsEnabled(relativePath)) {
|
|
257
|
-
this.#clearScreen();
|
|
258
|
-
this.#logger.log(`${this.#colors.green('update')} ${relativePath}`);
|
|
259
|
-
this.#restart(port);
|
|
260
|
-
return;
|
|
261
|
-
}
|
|
262
|
-
if (this.#isMetaFileWithReloadsDisabled(relativePath)) {
|
|
263
|
-
this.#clearScreen();
|
|
264
|
-
this.#logger.log(`${this.#colors.green('update')} ${relativePath}`);
|
|
265
|
-
}
|
|
266
|
-
});
|
|
267
|
-
output.watcher.on('unlink', ({ relativePath }) => {
|
|
268
|
-
if (this.#isDotEnvFile(relativePath) || this.#isRcFile(relativePath)) {
|
|
269
|
-
this.#clearScreen();
|
|
270
|
-
this.#logger.log(`${this.#colors.green('delete')} ${relativePath}`);
|
|
271
|
-
this.#restart(port);
|
|
272
|
-
return;
|
|
273
|
-
}
|
|
274
|
-
if (this.#isMetaFileWithReloadsEnabled(relativePath)) {
|
|
275
|
-
this.#clearScreen();
|
|
276
|
-
this.#logger.log(`${this.#colors.green('delete')} ${relativePath}`);
|
|
277
|
-
this.#restart(port);
|
|
278
|
-
return;
|
|
279
|
-
}
|
|
280
|
-
if (this.#isMetaFileWithReloadsDisabled(relativePath)) {
|
|
281
|
-
this.#clearScreen();
|
|
282
|
-
this.#logger.log(`${this.#colors.green('delete')} ${relativePath}`);
|
|
283
|
-
}
|
|
284
|
-
});
|
|
240
|
+
/**
|
|
241
|
+
* Changes in TypeScript source file
|
|
242
|
+
*/
|
|
243
|
+
output.watcher.on('source:add', ({ relativePath }) => this.#handleSourceFileChange('add', port, relativePath));
|
|
244
|
+
output.watcher.on('source:change', ({ relativePath }) => this.#handleSourceFileChange('update', port, relativePath));
|
|
245
|
+
output.watcher.on('source:unlink', ({ relativePath }) => this.#handleSourceFileChange('delete', port, relativePath));
|
|
246
|
+
/**
|
|
247
|
+
* Changes in non-TypeScript source files
|
|
248
|
+
*/
|
|
249
|
+
output.watcher.on('add', ({ relativePath }) => this.#handleFileChange('add', port, relativePath));
|
|
250
|
+
output.watcher.on('change', ({ relativePath }) => this.#handleFileChange('update', port, relativePath));
|
|
251
|
+
output.watcher.on('unlink', ({ relativePath }) => this.#handleFileChange('delete', port, relativePath));
|
|
285
252
|
}
|
|
286
253
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
import type tsStatic from 'typescript';
|
|
3
|
+
import { Watcher } from '@poppinss/chokidar-ts';
|
|
4
|
+
import type { RunOptions, WatchOptions } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Parses tsconfig.json and prints errors using typescript compiler
|
|
7
|
+
* host
|
|
8
|
+
*/
|
|
9
|
+
export declare function parseConfig(cwd: string | URL, ts: typeof tsStatic): tsStatic.ParsedCommandLine | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* Runs a Node.js script as a child process and inherits the stdio streams
|
|
12
|
+
*/
|
|
13
|
+
export declare function runNode(cwd: string | URL, options: RunOptions): import("execa").ExecaChildProcess<string>;
|
|
14
|
+
/**
|
|
15
|
+
* Runs a script as a child process and inherits the stdio streams
|
|
16
|
+
*/
|
|
17
|
+
export declare function run(cwd: string | URL, options: Omit<RunOptions, 'nodeArgs'>): import("execa").ExecaChildProcess<string>;
|
|
18
|
+
/**
|
|
19
|
+
* Watches the file system using tsconfig file
|
|
20
|
+
*/
|
|
21
|
+
export declare function watch(cwd: string | URL, ts: typeof tsStatic, options: WatchOptions): {
|
|
22
|
+
watcher: Watcher;
|
|
23
|
+
chokidar: import("chokidar").FSWatcher;
|
|
24
|
+
} | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Check if file is an .env file
|
|
27
|
+
*/
|
|
28
|
+
export declare function isDotEnvFile(filePath: string): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Check if file is .adonisrc.json file
|
|
31
|
+
*/
|
|
32
|
+
export declare function isRcFile(filePath: string): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Returns the port to use after inspect the dot-env files inside
|
|
35
|
+
* a given directory.
|
|
36
|
+
*
|
|
37
|
+
* A random port is used when the specified port is in use. Following
|
|
38
|
+
* is the logic for finding a specified port.
|
|
39
|
+
*
|
|
40
|
+
* - The "process.env.PORT" value is used if exists.
|
|
41
|
+
* - The dot-env files are loaded using the "EnvLoader" and the PORT
|
|
42
|
+
* value is by iterating over all the loaded files. The iteration
|
|
43
|
+
* stops after first find.
|
|
44
|
+
*/
|
|
45
|
+
export declare function getPort(cwd: URL): Promise<number>;
|
|
46
|
+
/**
|
|
47
|
+
* Helper function to copy files from relative paths or glob
|
|
48
|
+
* patterns
|
|
49
|
+
*/
|
|
50
|
+
export declare function copyFiles(files: string[], cwd: string, outDir: string): Promise<string[]>;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @adonisjs/assembler
|
|
3
|
+
*
|
|
4
|
+
* (c) AdonisJS
|
|
5
|
+
*
|
|
6
|
+
* For the full copyright and license information, please view the LICENSE
|
|
7
|
+
* file that was distributed with this source code.
|
|
8
|
+
*/
|
|
9
|
+
import cpy from 'cpy';
|
|
10
|
+
import { isNotJunk } from 'junk';
|
|
11
|
+
import fastGlob from 'fast-glob';
|
|
12
|
+
import getRandomPort from 'get-port';
|
|
13
|
+
import { fileURLToPath } from 'node:url';
|
|
14
|
+
import { execaNode, execa } from 'execa';
|
|
15
|
+
import { isAbsolute, relative } from 'node:path';
|
|
16
|
+
import { EnvLoader, EnvParser } from '@adonisjs/env';
|
|
17
|
+
import { ConfigParser, Watcher } from '@poppinss/chokidar-ts';
|
|
18
|
+
import debug from './debug.js';
|
|
19
|
+
/**
|
|
20
|
+
* Default set of args to pass in order to run TypeScript
|
|
21
|
+
* source. Used by "run" and "runNode" scripts
|
|
22
|
+
*/
|
|
23
|
+
const DEFAULT_NODE_ARGS = [
|
|
24
|
+
// Use ts-node/esm loader. The project must install it
|
|
25
|
+
'--loader=ts-node/esm',
|
|
26
|
+
// Disable annonying warnings
|
|
27
|
+
'--no-warnings',
|
|
28
|
+
// Enable expiremental meta resolve for cases where someone uses magic import string
|
|
29
|
+
'--experimental-import-meta-resolve',
|
|
30
|
+
// Enable source maps, since TSNode source maps are broken
|
|
31
|
+
'--enable-source-maps',
|
|
32
|
+
];
|
|
33
|
+
/**
|
|
34
|
+
* Parses tsconfig.json and prints errors using typescript compiler
|
|
35
|
+
* host
|
|
36
|
+
*/
|
|
37
|
+
export function parseConfig(cwd, ts) {
|
|
38
|
+
const { config, error } = new ConfigParser(cwd, 'tsconfig.json', ts).parse();
|
|
39
|
+
if (error) {
|
|
40
|
+
const compilerHost = ts.createCompilerHost({});
|
|
41
|
+
console.log(ts.formatDiagnosticsWithColorAndContext([error], compilerHost));
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (config.errors.length) {
|
|
45
|
+
const compilerHost = ts.createCompilerHost({});
|
|
46
|
+
console.log(ts.formatDiagnosticsWithColorAndContext(config.errors, compilerHost));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
return config;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Runs a Node.js script as a child process and inherits the stdio streams
|
|
53
|
+
*/
|
|
54
|
+
export function runNode(cwd, options) {
|
|
55
|
+
const childProcess = execaNode(options.script, options.scriptArgs, {
|
|
56
|
+
nodeOptions: DEFAULT_NODE_ARGS.concat(options.nodeArgs),
|
|
57
|
+
preferLocal: true,
|
|
58
|
+
windowsHide: false,
|
|
59
|
+
localDir: cwd,
|
|
60
|
+
cwd,
|
|
61
|
+
buffer: false,
|
|
62
|
+
stdio: options.stdio || 'inherit',
|
|
63
|
+
env: {
|
|
64
|
+
...(options.stdio === 'pipe' ? { FORCE_COLOR: 'true' } : {}),
|
|
65
|
+
...options.env,
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
return childProcess;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Runs a script as a child process and inherits the stdio streams
|
|
72
|
+
*/
|
|
73
|
+
export function run(cwd, options) {
|
|
74
|
+
const childProcess = execa(options.script, options.scriptArgs, {
|
|
75
|
+
preferLocal: true,
|
|
76
|
+
windowsHide: false,
|
|
77
|
+
localDir: cwd,
|
|
78
|
+
cwd,
|
|
79
|
+
buffer: false,
|
|
80
|
+
stdio: options.stdio || 'inherit',
|
|
81
|
+
env: {
|
|
82
|
+
...(options.stdio === 'pipe' ? { FORCE_COLOR: 'true' } : {}),
|
|
83
|
+
...options.env,
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
return childProcess;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Watches the file system using tsconfig file
|
|
90
|
+
*/
|
|
91
|
+
export function watch(cwd, ts, options) {
|
|
92
|
+
const config = parseConfig(cwd, ts);
|
|
93
|
+
if (!config) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const watcher = new Watcher(typeof cwd === 'string' ? cwd : fileURLToPath(cwd), config);
|
|
97
|
+
const chokidar = watcher.watch(['.'], { usePolling: options.poll });
|
|
98
|
+
return { watcher, chokidar };
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Check if file is an .env file
|
|
102
|
+
*/
|
|
103
|
+
export function isDotEnvFile(filePath) {
|
|
104
|
+
if (filePath === '.env') {
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
return filePath.includes('.env.');
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Check if file is .adonisrc.json file
|
|
111
|
+
*/
|
|
112
|
+
export function isRcFile(filePath) {
|
|
113
|
+
return filePath === '.adonisrc.json';
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Returns the port to use after inspect the dot-env files inside
|
|
117
|
+
* a given directory.
|
|
118
|
+
*
|
|
119
|
+
* A random port is used when the specified port is in use. Following
|
|
120
|
+
* is the logic for finding a specified port.
|
|
121
|
+
*
|
|
122
|
+
* - The "process.env.PORT" value is used if exists.
|
|
123
|
+
* - The dot-env files are loaded using the "EnvLoader" and the PORT
|
|
124
|
+
* value is by iterating over all the loaded files. The iteration
|
|
125
|
+
* stops after first find.
|
|
126
|
+
*/
|
|
127
|
+
export async function getPort(cwd) {
|
|
128
|
+
/**
|
|
129
|
+
* Use existing port if exists
|
|
130
|
+
*/
|
|
131
|
+
if (process.env.PORT) {
|
|
132
|
+
return getRandomPort({ port: Number(process.env.PORT) });
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Loop over files and use the port from their contents. Stops
|
|
136
|
+
* after first match
|
|
137
|
+
*/
|
|
138
|
+
const files = await new EnvLoader(cwd).load();
|
|
139
|
+
for (let file of files) {
|
|
140
|
+
const envVariables = new EnvParser(file.contents).parse();
|
|
141
|
+
if (envVariables.PORT) {
|
|
142
|
+
return getRandomPort({ port: Number(envVariables.PORT) });
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Use 3333 as the port
|
|
147
|
+
*/
|
|
148
|
+
return getRandomPort({ port: 3333 });
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Helper function to copy files from relative paths or glob
|
|
152
|
+
* patterns
|
|
153
|
+
*/
|
|
154
|
+
export async function copyFiles(files, cwd, outDir) {
|
|
155
|
+
/**
|
|
156
|
+
* Looping over files and create a new collection with paths
|
|
157
|
+
* and glob patterns
|
|
158
|
+
*/
|
|
159
|
+
const { paths, patterns } = files.reduce((result, file) => {
|
|
160
|
+
if (fastGlob.isDynamicPattern(file)) {
|
|
161
|
+
result.patterns.push(file);
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
result.paths.push(file);
|
|
165
|
+
}
|
|
166
|
+
return result;
|
|
167
|
+
}, { patterns: [], paths: [] });
|
|
168
|
+
debug('copyFiles inputs: %O, paths: %O, patterns: %O', files, paths, patterns);
|
|
169
|
+
/**
|
|
170
|
+
* Getting list of relative paths from glob patterns
|
|
171
|
+
*/
|
|
172
|
+
const filePaths = paths.concat(await fastGlob(patterns, { cwd }));
|
|
173
|
+
/**
|
|
174
|
+
* Computing relative destination. This is because, cpy is buggy when
|
|
175
|
+
* outDir is an absolute path.
|
|
176
|
+
*/
|
|
177
|
+
const destination = isAbsolute(outDir) ? relative(cwd, outDir) : outDir;
|
|
178
|
+
debug('copying files %O to destination "%s"', filePaths, destination);
|
|
179
|
+
return cpy(filePaths.filter(isNotJunk), destination, {
|
|
180
|
+
cwd: cwd,
|
|
181
|
+
flat: false,
|
|
182
|
+
});
|
|
183
|
+
}
|