@adonisjs/assembler 5.9.5 → 6.1.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/LICENSE.md +1 -1
- package/README.md +24 -37
- package/build/index.d.ts +2 -0
- package/build/index.js +2 -0
- package/build/src/bundler.d.ts +10 -0
- package/build/src/bundler.js +143 -0
- package/build/src/dev_server.d.ts +15 -0
- package/build/src/dev_server.js +214 -0
- package/build/src/run.d.ts +3 -0
- package/build/src/run.js +19 -0
- package/build/src/types.d.ts +26 -0
- package/build/src/watch.d.ts +8 -0
- package/build/src/watch.js +18 -0
- package/package.json +77 -99
- package/build/ace-manifest.json +0 -521
- package/build/commands/Build.d.ts +0 -37
- package/build/commands/Build.js +0 -138
- package/build/commands/Invoke.d.ts +0 -34
- package/build/commands/Invoke.js +0 -234
- package/build/commands/Make/Base.d.ts +0 -30
- package/build/commands/Make/Base.js +0 -75
- package/build/commands/Make/Command.d.ts +0 -35
- package/build/commands/Make/Command.js +0 -82
- package/build/commands/Make/Controller.d.ts +0 -37
- package/build/commands/Make/Controller.js +0 -89
- package/build/commands/Make/Exception.d.ts +0 -32
- package/build/commands/Make/Exception.js +0 -75
- package/build/commands/Make/Listener.d.ts +0 -30
- package/build/commands/Make/Listener.js +0 -70
- package/build/commands/Make/Middleware.d.ts +0 -31
- package/build/commands/Make/Middleware.js +0 -87
- package/build/commands/Make/PreloadFile.d.ts +0 -38
- package/build/commands/Make/PreloadFile.js +0 -157
- package/build/commands/Make/Provider.d.ts +0 -31
- package/build/commands/Make/Provider.js +0 -114
- package/build/commands/Make/Suite.d.ts +0 -41
- package/build/commands/Make/Suite.js +0 -120
- package/build/commands/Make/Test.d.ts +0 -35
- package/build/commands/Make/Test.js +0 -96
- package/build/commands/Make/Validator.d.ts +0 -31
- package/build/commands/Make/Validator.js +0 -71
- package/build/commands/Make/View.d.ts +0 -30
- package/build/commands/Make/View.js +0 -70
- package/build/commands/Serve.d.ts +0 -33
- package/build/commands/Serve.js +0 -112
- package/build/commands/Test.d.ts +0 -57
- package/build/commands/Test.js +0 -159
- package/build/commands/TypeCheck.d.ts +0 -16
- package/build/commands/TypeCheck.js +0 -85
- package/build/config/paths.d.ts +0 -7
- package/build/config/paths.js +0 -18
- package/build/register.js +0 -15
- package/build/src/AssetsBundler/index.d.ts +0 -76
- package/build/src/AssetsBundler/index.js +0 -216
- package/build/src/Compiler/index.d.ts +0 -62
- package/build/src/Compiler/index.js +0 -287
- package/build/src/Contracts/index.d.ts +0 -8
- package/build/src/Contracts/index.js +0 -10
- package/build/src/DevServer/index.d.ts +0 -70
- package/build/src/DevServer/index.js +0 -306
- package/build/src/EnvParser/index.d.ts +0 -21
- package/build/src/EnvParser/index.js +0 -48
- package/build/src/HttpServer/index.d.ts +0 -34
- package/build/src/HttpServer/index.js +0 -87
- package/build/src/Manifest/index.d.ts +0 -32
- package/build/src/Manifest/index.js +0 -88
- package/build/src/RcFile/index.d.ts +0 -72
- package/build/src/RcFile/index.js +0 -174
- package/build/src/Test/index.d.ts +0 -75
- package/build/src/Test/index.js +0 -346
- package/build/src/Test/process.d.ts +0 -22
- package/build/src/Test/process.js +0 -68
- package/build/src/Ts/index.d.ts +0 -24
- package/build/src/Ts/index.js +0 -55
- package/build/src/requireHook/index.d.ts +0 -5
- package/build/src/requireHook/index.js +0 -28
- package/build/src/requireHook/ioc-transformer.d.ts +0 -6
- package/build/src/requireHook/ioc-transformer.js +0 -21
- package/build/templates/command.txt +0 -33
- package/build/templates/controller.txt +0 -3
- package/build/templates/event-listener.txt +0 -3
- package/build/templates/exception.txt +0 -15
- package/build/templates/middleware.txt +0 -8
- package/build/templates/preload-file.txt +0 -9
- package/build/templates/provider.txt +0 -40
- package/build/templates/resource-controller.txt +0 -17
- package/build/templates/self-handle-exception.txt +0 -32
- package/build/templates/test-entrypoint.txt +0 -45
- package/build/templates/test.txt +0 -5
- package/build/templates/tests/bootstrap.txt +0 -69
- package/build/templates/tests/functional/hello_world_api.spec.txt +0 -8
- package/build/templates/tests/functional/hello_world_slim.spec.txt +0 -8
- package/build/templates/tests/functional/hello_world_web.spec.txt +0 -8
- package/build/templates/tests-contract.txt +0 -18
- package/build/templates/validator.txt +0 -40
- package/build/templates/view.txt +0 -0
- package/build/templates/webpack.config.txt +0 -214
- /package/build/{register.d.ts → src/types.js} +0 -0
package/LICENSE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# The MIT License
|
|
2
2
|
|
|
3
|
-
Copyright
|
|
3
|
+
Copyright (c) 2023 AdonisJS Framework
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
6
|
|
package/README.md
CHANGED
|
@@ -1,49 +1,36 @@
|
|
|
1
|
-
|
|
2
|
-
<img src="https://res.cloudinary.com/adonisjs/image/upload/q_100/v1558612869/adonis-readme_zscycu.jpg" width="600px">
|
|
3
|
-
</div>
|
|
1
|
+
# @adonisjs/assembler
|
|
4
2
|
|
|
5
3
|
<br />
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
<h3> Core Commands for building AdonisJS projects </h3>
|
|
9
|
-
<p>
|
|
10
|
-
Assembler contains a set of core commands to <strong>build and serve the AdonisJS typescript project</strong>, along with scaffolding <code>make</code> commands.
|
|
11
|
-
</p>
|
|
12
|
-
</div>
|
|
5
|
+
[![gh-workflow-image]][gh-workflow-url] [![npm-image]][npm-url] ![][typescript-image] [![license-image]][license-url] [![synk-image]][synk-url]
|
|
13
6
|
|
|
14
|
-
|
|
7
|
+
## Introduction
|
|
8
|
+
Assembler exports the API for starting the **AdonisJS development server**, **building project for production** and **running tests** in watch mode. Assembler must be used during development only.
|
|
9
|
+
|
|
10
|
+
## Official Documentation
|
|
11
|
+
The documentation is available on the official website
|
|
12
|
+
|
|
13
|
+
## Contributing
|
|
14
|
+
One of the primary goals of AdonisJS is to have a vibrant community of users and contributors who believes in the principles of the framework.
|
|
15
|
+
|
|
16
|
+
We encourage you to read the [contribution guide](https://github.com/adonisjs/.github/blob/main/docs/CONTRIBUTING.md) before contributing to the framework.
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
<h3>
|
|
24
|
-
<a href="https://adonisjs.com">
|
|
25
|
-
Website
|
|
26
|
-
</a>
|
|
27
|
-
<span> | </span>
|
|
28
|
-
<a href="https://docs.adonisjs.com/guides/installation">
|
|
29
|
-
Guides
|
|
30
|
-
</a>
|
|
31
|
-
<span> | </span>
|
|
32
|
-
<a href="CONTRIBUTING.md">
|
|
33
|
-
Contributing
|
|
34
|
-
</a>
|
|
35
|
-
</h3>
|
|
36
|
-
</div>
|
|
37
|
-
|
|
38
|
-
<div align="center">
|
|
39
|
-
<sub>Built with ❤︎ by <a href="https://twitter.com/AmanVirk1">Harminder Virk</a>
|
|
40
|
-
</div>
|
|
41
|
-
|
|
42
|
-
[gh-workflow-image]: https://img.shields.io/github/workflow/status/adonisjs/assembler/test?style=for-the-badge
|
|
18
|
+
## Code of Conduct
|
|
19
|
+
In order to ensure that the AdonisJS community is welcoming to all, please review and abide by the [Code of Conduct](https://github.com/adonisjs/.github/blob/main/docs/CODE_OF_CONDUCT.md).
|
|
20
|
+
|
|
21
|
+
## License
|
|
22
|
+
AdonisJS Assembler is open-sourced software licensed under the [MIT license](LICENSE.md).
|
|
23
|
+
|
|
24
|
+
[gh-workflow-image]: https://img.shields.io/github/actions/workflow/status/adonisjs/assembler/test.yml?style=for-the-badge
|
|
43
25
|
[gh-workflow-url]: https://github.com/adonisjs/assembler/actions/workflows/test.yml "Github action"
|
|
44
26
|
|
|
45
27
|
[npm-image]: https://img.shields.io/npm/v/@adonisjs/assembler/latest.svg?style=for-the-badge&logo=npm
|
|
46
28
|
[npm-url]: https://npmjs.org/package/@adonisjs/assembler/v/latest "npm"
|
|
47
29
|
|
|
30
|
+
[typescript-image]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript
|
|
31
|
+
|
|
32
|
+
[license-url]: LICENSE.md
|
|
33
|
+
[license-image]: https://img.shields.io/github/license/adonisjs/ace?style=for-the-badge
|
|
34
|
+
|
|
48
35
|
[synk-image]: https://img.shields.io/snyk/vulnerabilities/github/adonisjs/assembler?label=Synk%20Vulnerabilities&style=for-the-badge
|
|
49
36
|
[synk-url]: https://snyk.io/test/github/adonisjs/assembler?targetFile=package.json "synk"
|
package/build/index.d.ts
ADDED
package/build/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
import type tsStatic from 'typescript';
|
|
3
|
+
import { type Logger } from '@poppinss/cliui';
|
|
4
|
+
import type { BundlerOptions } from './types.js';
|
|
5
|
+
export declare class Bundler {
|
|
6
|
+
#private;
|
|
7
|
+
constructor(cwd: URL, ts: typeof tsStatic, options: BundlerOptions);
|
|
8
|
+
setLogger(logger: Logger): this;
|
|
9
|
+
bundle(stopOnError?: boolean, client?: 'npm' | 'yarn' | 'pnpm'): Promise<boolean>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import slash from 'slash';
|
|
3
|
+
import copyfiles from 'cpy';
|
|
4
|
+
import { execa } from 'execa';
|
|
5
|
+
import { join, relative } from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import { ConfigParser } from '@poppinss/chokidar-ts';
|
|
8
|
+
import { cliui } from '@poppinss/cliui';
|
|
9
|
+
const ui = cliui();
|
|
10
|
+
export class Bundler {
|
|
11
|
+
#cwd;
|
|
12
|
+
#cwdPath;
|
|
13
|
+
#ts;
|
|
14
|
+
#logger = ui.logger;
|
|
15
|
+
#options;
|
|
16
|
+
get #colors() {
|
|
17
|
+
return this.#logger.getColors();
|
|
18
|
+
}
|
|
19
|
+
constructor(cwd, ts, options) {
|
|
20
|
+
this.#cwd = cwd;
|
|
21
|
+
this.#cwdPath = fileURLToPath(this.#cwd);
|
|
22
|
+
this.#ts = ts;
|
|
23
|
+
this.#options = options;
|
|
24
|
+
}
|
|
25
|
+
#getRelativeName(filePath) {
|
|
26
|
+
return slash(relative(this.#cwdPath, filePath));
|
|
27
|
+
}
|
|
28
|
+
async #cleanupBuildDirectory(outDir) {
|
|
29
|
+
await fs.remove(outDir);
|
|
30
|
+
}
|
|
31
|
+
async #runTsc(outDir) {
|
|
32
|
+
try {
|
|
33
|
+
await execa('tsc', ['--outDir', outDir], {
|
|
34
|
+
cwd: this.#cwd,
|
|
35
|
+
preferLocal: true,
|
|
36
|
+
localDir: this.#cwd,
|
|
37
|
+
windowsHide: false,
|
|
38
|
+
buffer: false,
|
|
39
|
+
stdio: 'inherit',
|
|
40
|
+
});
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async #copyFiles(files, outDir) {
|
|
48
|
+
try {
|
|
49
|
+
await copyfiles(files, outDir, { cwd: this.#cwdPath });
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
if (!error.message.includes("the file doesn't exist")) {
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async #copyMetaFiles(outDir, additionalFilesToCopy) {
|
|
58
|
+
const metaFiles = (this.#options.metaFiles || [])
|
|
59
|
+
.map((file) => file.pattern)
|
|
60
|
+
.concat(additionalFilesToCopy);
|
|
61
|
+
await this.#copyFiles(metaFiles, outDir);
|
|
62
|
+
}
|
|
63
|
+
async #copyAdonisRcFile(outDir) {
|
|
64
|
+
const existingContents = await fs.readJSON(join(this.#cwdPath, '.adonisrc.json'));
|
|
65
|
+
const compiledContents = Object.assign({}, existingContents, {
|
|
66
|
+
typescript: false,
|
|
67
|
+
lastCompiledAt: new Date().toISOString(),
|
|
68
|
+
});
|
|
69
|
+
await fs.outputJSON(join(outDir, '.adonisrc.json'), compiledContents, { spaces: 2 });
|
|
70
|
+
}
|
|
71
|
+
#getClientLockFile(client) {
|
|
72
|
+
switch (client) {
|
|
73
|
+
case 'npm':
|
|
74
|
+
return 'package-lock.json';
|
|
75
|
+
case 'yarn':
|
|
76
|
+
return 'yarn.lock';
|
|
77
|
+
case 'pnpm':
|
|
78
|
+
return 'pnpm-lock.yaml';
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
#getClientInstallCommand(client) {
|
|
82
|
+
switch (client) {
|
|
83
|
+
case 'npm':
|
|
84
|
+
return 'npm ci --omit="dev"';
|
|
85
|
+
case 'yarn':
|
|
86
|
+
return 'yarn install --production';
|
|
87
|
+
case 'pnpm':
|
|
88
|
+
return 'pnpm i --prod';
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
setLogger(logger) {
|
|
92
|
+
this.#logger = logger;
|
|
93
|
+
return this;
|
|
94
|
+
}
|
|
95
|
+
async bundle(stopOnError = true, client = 'npm') {
|
|
96
|
+
const { config, error } = new ConfigParser(this.#cwd, 'tsconfig.json', this.#ts).parse();
|
|
97
|
+
if (error) {
|
|
98
|
+
const compilerHost = this.#ts.createCompilerHost({});
|
|
99
|
+
this.#logger.logError(this.#ts.formatDiagnosticsWithColorAndContext([error], compilerHost));
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
if (config.errors.length) {
|
|
103
|
+
const compilerHost = this.#ts.createCompilerHost({});
|
|
104
|
+
this.#logger.logError(this.#ts.formatDiagnosticsWithColorAndContext(config.errors, compilerHost));
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
if (!config) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
const outDir = config.options.outDir || fileURLToPath(new URL('build/', this.#cwd));
|
|
111
|
+
this.#logger.info('cleaning up output directory', { suffix: this.#getRelativeName(outDir) });
|
|
112
|
+
await this.#cleanupBuildDirectory(outDir);
|
|
113
|
+
this.#logger.info('compiling typescript source', { suffix: 'tsc' });
|
|
114
|
+
const buildCompleted = await this.#runTsc(outDir);
|
|
115
|
+
await this.#copyFiles(['ace.js'], outDir);
|
|
116
|
+
if (!buildCompleted && stopOnError) {
|
|
117
|
+
await this.#cleanupBuildDirectory(outDir);
|
|
118
|
+
const instructions = ui
|
|
119
|
+
.sticker()
|
|
120
|
+
.fullScreen()
|
|
121
|
+
.drawBorder((borderChar, colors) => colors.red(borderChar));
|
|
122
|
+
instructions.add(this.#colors.red('Cannot complete the build process as there are TypeScript errors.'));
|
|
123
|
+
instructions.add(this.#colors.red('Use "--ignore-ts-errors" flag to ignore TypeScript errors and continue the build.'));
|
|
124
|
+
this.#logger.logError(instructions.prepare());
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
const pkgFiles = ['package.json', this.#getClientLockFile(client)];
|
|
128
|
+
this.#logger.info('copying meta files to the output directory');
|
|
129
|
+
await this.#copyMetaFiles(outDir, pkgFiles);
|
|
130
|
+
this.#logger.info('copying .adonisrc.json file to the output directory');
|
|
131
|
+
await this.#copyAdonisRcFile(outDir);
|
|
132
|
+
this.#logger.success('build completed');
|
|
133
|
+
this.#logger.log('');
|
|
134
|
+
ui.instructions()
|
|
135
|
+
.useRenderer(this.#logger.getRenderer())
|
|
136
|
+
.heading('Run the following commands to start the server in production')
|
|
137
|
+
.add(this.#colors.cyan(`cd ${this.#getRelativeName(outDir)}`))
|
|
138
|
+
.add(this.#colors.cyan(this.#getClientInstallCommand(client)))
|
|
139
|
+
.add(this.#colors.cyan('node bin/server.js'))
|
|
140
|
+
.render();
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
import type tsStatic from 'typescript';
|
|
3
|
+
import { type Logger } from '@poppinss/cliui';
|
|
4
|
+
import type { DevServerOptions } from './types.js';
|
|
5
|
+
export declare class DevServer {
|
|
6
|
+
#private;
|
|
7
|
+
constructor(cwd: URL, options: DevServerOptions);
|
|
8
|
+
setLogger(logger: Logger): this;
|
|
9
|
+
onClose(callback: (exitCode: number) => any): this;
|
|
10
|
+
onError(callback: (error: any) => any): this;
|
|
11
|
+
start(): Promise<void>;
|
|
12
|
+
startAndWatch(ts: typeof tsStatic, options?: {
|
|
13
|
+
poll: boolean;
|
|
14
|
+
}): Promise<void>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import getPort from 'get-port';
|
|
2
|
+
import picomatch from 'picomatch';
|
|
3
|
+
import { cliui } from '@poppinss/cliui';
|
|
4
|
+
import { EnvLoader, EnvParser } from '@adonisjs/env';
|
|
5
|
+
import { run } from './run.js';
|
|
6
|
+
import { watch } from './watch.js';
|
|
7
|
+
const ui = cliui();
|
|
8
|
+
export class DevServer {
|
|
9
|
+
#cwd;
|
|
10
|
+
#logger = ui.logger;
|
|
11
|
+
#options;
|
|
12
|
+
#isWatching = false;
|
|
13
|
+
#scriptFile = 'bin/server.js';
|
|
14
|
+
#httpServerProcess;
|
|
15
|
+
#isMetaFileWithReloadsEnabled;
|
|
16
|
+
#isMetaFileWithReloadsDisabled;
|
|
17
|
+
#watcher;
|
|
18
|
+
#onError;
|
|
19
|
+
#onClose;
|
|
20
|
+
get #colors() {
|
|
21
|
+
return this.#logger.getColors();
|
|
22
|
+
}
|
|
23
|
+
constructor(cwd, options) {
|
|
24
|
+
this.#cwd = cwd;
|
|
25
|
+
this.#options = options;
|
|
26
|
+
this.#isMetaFileWithReloadsEnabled = picomatch((this.#options.metaFiles || [])
|
|
27
|
+
.filter(({ reloadServer }) => reloadServer === true)
|
|
28
|
+
.map(({ pattern }) => pattern));
|
|
29
|
+
this.#isMetaFileWithReloadsDisabled = picomatch((this.#options.metaFiles || [])
|
|
30
|
+
.filter(({ reloadServer }) => reloadServer !== true)
|
|
31
|
+
.map(({ pattern }) => pattern));
|
|
32
|
+
}
|
|
33
|
+
#isDotEnvFile(filePath) {
|
|
34
|
+
if (filePath === '.env') {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
return filePath.includes('.env.');
|
|
38
|
+
}
|
|
39
|
+
#isRcFile(filePath) {
|
|
40
|
+
return filePath === '.adonisrc.json';
|
|
41
|
+
}
|
|
42
|
+
#isAdonisJSReadyMessage(message) {
|
|
43
|
+
return (message !== null &&
|
|
44
|
+
typeof message === 'object' &&
|
|
45
|
+
'isAdonisJS' in message &&
|
|
46
|
+
'environment' in message &&
|
|
47
|
+
message.environment === 'web');
|
|
48
|
+
}
|
|
49
|
+
#clearScreen() {
|
|
50
|
+
if (this.#options.clearScreen) {
|
|
51
|
+
process.stdout.write('\u001Bc');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
async #getPort() {
|
|
55
|
+
if (process.env.PORT) {
|
|
56
|
+
return getPort({ port: Number(process.env.PORT) });
|
|
57
|
+
}
|
|
58
|
+
const files = await new EnvLoader(this.#cwd).load();
|
|
59
|
+
for (let file of files) {
|
|
60
|
+
const envVariables = new EnvParser(file.contents).parse();
|
|
61
|
+
if (envVariables.PORT) {
|
|
62
|
+
return getPort({ port: Number(envVariables.PORT) });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return getPort({ port: 3333 });
|
|
66
|
+
}
|
|
67
|
+
#startHTTPServer(port, mode) {
|
|
68
|
+
this.#httpServerProcess = run(this.#cwd, {
|
|
69
|
+
script: this.#scriptFile,
|
|
70
|
+
env: { PORT: port, ...this.#options.env },
|
|
71
|
+
nodeArgs: this.#options.nodeArgs,
|
|
72
|
+
scriptArgs: this.#options.scriptArgs,
|
|
73
|
+
});
|
|
74
|
+
this.#httpServerProcess.on('message', (message) => {
|
|
75
|
+
if (this.#isAdonisJSReadyMessage(message)) {
|
|
76
|
+
ui.sticker()
|
|
77
|
+
.useColors(this.#colors)
|
|
78
|
+
.useRenderer(this.#logger.getRenderer())
|
|
79
|
+
.add(`Server address: ${this.#colors.cyan(`http://${message.host}:${message.port}`)}`)
|
|
80
|
+
.add(`File system watcher: ${this.#colors.cyan(`${this.#isWatching ? 'enabled' : 'disabled'}`)}`)
|
|
81
|
+
.render();
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
this.#httpServerProcess
|
|
85
|
+
.then((result) => {
|
|
86
|
+
this.#logger.warning(`underlying HTTP server closed with status code "${result.exitCode}"`);
|
|
87
|
+
if (mode === 'nonblocking') {
|
|
88
|
+
this.#onClose?.(result.exitCode);
|
|
89
|
+
this.#watcher?.close();
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
.catch((error) => {
|
|
93
|
+
this.#logger.warning('unable to connect to underlying HTTP server process');
|
|
94
|
+
this.#logger.fatal(error);
|
|
95
|
+
this.#onError?.(error);
|
|
96
|
+
this.#watcher?.close();
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
#restart(port) {
|
|
100
|
+
if (this.#httpServerProcess) {
|
|
101
|
+
this.#httpServerProcess.removeAllListeners();
|
|
102
|
+
this.#httpServerProcess.kill('SIGKILL');
|
|
103
|
+
}
|
|
104
|
+
this.#startHTTPServer(port, 'blocking');
|
|
105
|
+
}
|
|
106
|
+
setLogger(logger) {
|
|
107
|
+
this.#logger = logger;
|
|
108
|
+
return this;
|
|
109
|
+
}
|
|
110
|
+
onClose(callback) {
|
|
111
|
+
this.#onClose = callback;
|
|
112
|
+
return this;
|
|
113
|
+
}
|
|
114
|
+
onError(callback) {
|
|
115
|
+
this.#onError = callback;
|
|
116
|
+
return this;
|
|
117
|
+
}
|
|
118
|
+
async start() {
|
|
119
|
+
this.#clearScreen();
|
|
120
|
+
this.#logger.info('starting HTTP server...');
|
|
121
|
+
this.#startHTTPServer(String(await this.#getPort()), 'nonblocking');
|
|
122
|
+
}
|
|
123
|
+
async startAndWatch(ts, options) {
|
|
124
|
+
this.#isWatching = true;
|
|
125
|
+
this.#clearScreen();
|
|
126
|
+
const port = String(await this.#getPort());
|
|
127
|
+
this.#logger.info('starting HTTP server...');
|
|
128
|
+
this.#startHTTPServer(port, 'blocking');
|
|
129
|
+
const output = watch(this.#cwd, ts, options || {});
|
|
130
|
+
if (!output) {
|
|
131
|
+
this.#onClose?.(1);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
this.#watcher = output.chokidar;
|
|
135
|
+
output.watcher.on('watcher:ready', () => {
|
|
136
|
+
this.#logger.info('watching file system for changes...');
|
|
137
|
+
});
|
|
138
|
+
output.chokidar.on('error', (error) => {
|
|
139
|
+
this.#logger.warning('file system watcher failure');
|
|
140
|
+
this.#logger.fatal(error);
|
|
141
|
+
this.#onError?.(error);
|
|
142
|
+
output.chokidar.close();
|
|
143
|
+
});
|
|
144
|
+
output.watcher.on('source:add', ({ relativePath }) => {
|
|
145
|
+
this.#clearScreen();
|
|
146
|
+
this.#logger.log(`${this.#colors.green('add')} ${relativePath}`);
|
|
147
|
+
this.#restart(port);
|
|
148
|
+
});
|
|
149
|
+
output.watcher.on('source:change', ({ relativePath }) => {
|
|
150
|
+
this.#clearScreen();
|
|
151
|
+
this.#logger.log(`${this.#colors.green('update')} ${relativePath}`);
|
|
152
|
+
this.#restart(port);
|
|
153
|
+
});
|
|
154
|
+
output.watcher.on('source:unlink', ({ relativePath }) => {
|
|
155
|
+
this.#clearScreen();
|
|
156
|
+
this.#logger.log(`${this.#colors.green('delete')} ${relativePath}`);
|
|
157
|
+
this.#restart(port);
|
|
158
|
+
});
|
|
159
|
+
output.watcher.on('add', ({ relativePath }) => {
|
|
160
|
+
if (this.#isDotEnvFile(relativePath) || this.#isRcFile(relativePath)) {
|
|
161
|
+
this.#clearScreen();
|
|
162
|
+
this.#logger.log(`${this.#colors.green('add')} ${relativePath}`);
|
|
163
|
+
this.#restart(port);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (this.#isMetaFileWithReloadsEnabled(relativePath)) {
|
|
167
|
+
this.#clearScreen();
|
|
168
|
+
this.#logger.log(`${this.#colors.green('add')} ${relativePath}`);
|
|
169
|
+
this.#restart(port);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
if (this.#isMetaFileWithReloadsDisabled(relativePath)) {
|
|
173
|
+
this.#clearScreen();
|
|
174
|
+
this.#logger.log(`${this.#colors.green('add')} ${relativePath}`);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
output.watcher.on('change', ({ relativePath }) => {
|
|
178
|
+
if (this.#isDotEnvFile(relativePath) || this.#isRcFile(relativePath)) {
|
|
179
|
+
this.#clearScreen();
|
|
180
|
+
this.#logger.log(`${this.#colors.green('update')} ${relativePath}`);
|
|
181
|
+
this.#restart(port);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
if (this.#isMetaFileWithReloadsEnabled(relativePath)) {
|
|
185
|
+
this.#clearScreen();
|
|
186
|
+
this.#logger.log(`${this.#colors.green('update')} ${relativePath}`);
|
|
187
|
+
this.#restart(port);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
if (this.#isMetaFileWithReloadsDisabled(relativePath)) {
|
|
191
|
+
this.#clearScreen();
|
|
192
|
+
this.#logger.log(`${this.#colors.green('update')} ${relativePath}`);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
output.watcher.on('unlink', ({ relativePath }) => {
|
|
196
|
+
if (this.#isDotEnvFile(relativePath) || this.#isRcFile(relativePath)) {
|
|
197
|
+
this.#clearScreen();
|
|
198
|
+
this.#logger.log(`${this.#colors.green('delete')} ${relativePath}`);
|
|
199
|
+
this.#restart(port);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
if (this.#isMetaFileWithReloadsEnabled(relativePath)) {
|
|
203
|
+
this.#clearScreen();
|
|
204
|
+
this.#logger.log(`${this.#colors.green('delete')} ${relativePath}`);
|
|
205
|
+
this.#restart(port);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
if (this.#isMetaFileWithReloadsDisabled(relativePath)) {
|
|
209
|
+
this.#clearScreen();
|
|
210
|
+
this.#logger.log(`${this.#colors.green('delete')} ${relativePath}`);
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
package/build/src/run.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { execaNode } from 'execa';
|
|
2
|
+
const DEFAULT_NODE_ARGS = [
|
|
3
|
+
'--loader=ts-node/esm',
|
|
4
|
+
'--no-warnings',
|
|
5
|
+
'--experimental-import-meta-resolve',
|
|
6
|
+
];
|
|
7
|
+
export function run(cwd, options) {
|
|
8
|
+
const childProces = execaNode(options.script, options.scriptArgs, {
|
|
9
|
+
nodeOptions: DEFAULT_NODE_ARGS.concat(options.nodeArgs),
|
|
10
|
+
preferLocal: true,
|
|
11
|
+
windowsHide: false,
|
|
12
|
+
localDir: cwd,
|
|
13
|
+
cwd,
|
|
14
|
+
buffer: false,
|
|
15
|
+
stdio: 'inherit',
|
|
16
|
+
env: options.env,
|
|
17
|
+
});
|
|
18
|
+
return childProces;
|
|
19
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
export type RunOptions = {
|
|
3
|
+
script: string;
|
|
4
|
+
scriptArgs: string[];
|
|
5
|
+
nodeArgs: string[];
|
|
6
|
+
env?: NodeJS.ProcessEnv;
|
|
7
|
+
};
|
|
8
|
+
export type WatchOptions = {
|
|
9
|
+
poll?: boolean;
|
|
10
|
+
};
|
|
11
|
+
export type DevServerOptions = {
|
|
12
|
+
scriptArgs: string[];
|
|
13
|
+
nodeArgs: string[];
|
|
14
|
+
clearScreen?: boolean;
|
|
15
|
+
env?: NodeJS.ProcessEnv;
|
|
16
|
+
metaFiles?: {
|
|
17
|
+
pattern: string;
|
|
18
|
+
reloadServer: boolean;
|
|
19
|
+
}[];
|
|
20
|
+
};
|
|
21
|
+
export type BundlerOptions = {
|
|
22
|
+
metaFiles?: {
|
|
23
|
+
pattern: string;
|
|
24
|
+
reloadServer: boolean;
|
|
25
|
+
}[];
|
|
26
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
import type tsStatic from 'typescript';
|
|
3
|
+
import { Watcher } from '@poppinss/chokidar-ts';
|
|
4
|
+
import type { WatchOptions } from './types.js';
|
|
5
|
+
export declare function watch(cwd: string | URL, ts: typeof tsStatic, options: WatchOptions): {
|
|
6
|
+
watcher: Watcher;
|
|
7
|
+
chokidar: import("chokidar").FSWatcher;
|
|
8
|
+
} | undefined;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { fileURLToPath } from 'node:url';
|
|
2
|
+
import { ConfigParser, Watcher } from '@poppinss/chokidar-ts';
|
|
3
|
+
export function watch(cwd, ts, options) {
|
|
4
|
+
const { config, error } = new ConfigParser(cwd, 'tsconfig.json', ts).parse();
|
|
5
|
+
if (error) {
|
|
6
|
+
const compilerHost = ts.createCompilerHost({});
|
|
7
|
+
console.log(ts.formatDiagnosticsWithColorAndContext([error], compilerHost));
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
if (config.errors.length) {
|
|
11
|
+
const compilerHost = ts.createCompilerHost({});
|
|
12
|
+
console.log(ts.formatDiagnosticsWithColorAndContext(config.errors, compilerHost));
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const watcher = new Watcher(typeof cwd === 'string' ? cwd : fileURLToPath(cwd), config);
|
|
16
|
+
const chokidar = watcher.watch(['.'], { usePolling: options.poll });
|
|
17
|
+
return { watcher, chokidar };
|
|
18
|
+
}
|