@b9g/shovel 0.2.6 → 0.2.8
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/CHANGELOG.md +12 -0
- package/bin/cli.js +2 -2
- package/bin/create.js +124 -63
- package/package.json +5 -5
- package/src/_chunks/{build-KBQU2OA7.js → build-O5LLUOND.js} +1 -1
- package/src/_chunks/{chunk-ABGHNBNM.js → chunk-DQDUKJQ4.js} +16 -32
- package/src/_chunks/{develop-JUQG2G7M.js → develop-SVLFKAF5.js} +27 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to Shovel will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.2.7] - 2026-02-06
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
- **Request logger middleware** - New `logger()` middleware in `@b9g/router/middleware` logs requests and responses with timing via LogTape (default category: `["app", "router"]`)
|
|
10
|
+
- **CLI flags for create-shovel** - `--template`, `--typescript`/`--no-typescript`, `--platform` flags to bypass interactive prompts. `--template crank` is shorthand for static-site + Crank.js.
|
|
11
|
+
- **Logger in generated templates** - All Router-based templates (api, full-stack) now include `router.use(logger())` out of the box
|
|
12
|
+
|
|
13
|
+
### Dependencies
|
|
14
|
+
|
|
15
|
+
- **`@b9g/router`** `0.2.2` - Added `@logtape/logtape` as explicit dependency (was previously resolved via workspace only)
|
|
16
|
+
|
|
5
17
|
## [0.2.6] - 2026-02-06
|
|
6
18
|
|
|
7
19
|
### Features
|
package/bin/cli.js
CHANGED
|
@@ -75,7 +75,7 @@ program.command("develop <entrypoint>").description("Start development server wi
|
|
|
75
75
|
DEFAULTS.WORKERS
|
|
76
76
|
).option("--platform <name>", "Runtime platform (node, cloudflare, bun)").action(async (entrypoint, options) => {
|
|
77
77
|
checkPlatformReexec(options);
|
|
78
|
-
const { developCommand } = await import("../src/_chunks/develop-
|
|
78
|
+
const { developCommand } = await import("../src/_chunks/develop-SVLFKAF5.js");
|
|
79
79
|
await developCommand(entrypoint, options, config);
|
|
80
80
|
});
|
|
81
81
|
program.command("create [name]").description("Create a new Shovel project").action(async (name) => {
|
|
@@ -91,7 +91,7 @@ program.command("build <entrypoint>").description("Build app for production").op
|
|
|
91
91
|
"Run ServiceWorker lifecycle after build (install or activate, default: activate)"
|
|
92
92
|
).action(async (entrypoint, options) => {
|
|
93
93
|
checkPlatformReexec(options);
|
|
94
|
-
const { buildCommand } = await import("../src/_chunks/build-
|
|
94
|
+
const { buildCommand } = await import("../src/_chunks/build-O5LLUOND.js");
|
|
95
95
|
await buildCommand(entrypoint, options, config);
|
|
96
96
|
process.exit(0);
|
|
97
97
|
});
|
package/bin/create.js
CHANGED
|
@@ -20,10 +20,26 @@ function validateProjectName(name) {
|
|
|
20
20
|
return "Use lowercase letters, numbers, and hyphens only";
|
|
21
21
|
return void 0;
|
|
22
22
|
}
|
|
23
|
+
function parseFlags(args) {
|
|
24
|
+
const flags = {};
|
|
25
|
+
for (let i = 0; i < args.length; i++) {
|
|
26
|
+
const arg = args[i];
|
|
27
|
+
if (arg === "--template" && args[i + 1])
|
|
28
|
+
flags.template = args[++i];
|
|
29
|
+
else if (arg === "--typescript")
|
|
30
|
+
flags.typescript = true;
|
|
31
|
+
else if (arg === "--no-typescript")
|
|
32
|
+
flags.typescript = false;
|
|
33
|
+
else if (arg === "--platform" && args[i + 1])
|
|
34
|
+
flags.platform = args[++i];
|
|
35
|
+
}
|
|
36
|
+
return flags;
|
|
37
|
+
}
|
|
23
38
|
async function main() {
|
|
24
39
|
console.info("");
|
|
25
40
|
intro("Create Shovel App");
|
|
26
|
-
|
|
41
|
+
const flags = parseFlags(process.argv.slice(2));
|
|
42
|
+
let projectName = process.argv[2]?.startsWith("-") ? void 0 : process.argv[2];
|
|
27
43
|
if (projectName) {
|
|
28
44
|
const validationError = validateProjectName(projectName);
|
|
29
45
|
if (validationError) {
|
|
@@ -52,37 +68,53 @@ async function main() {
|
|
|
52
68
|
process.exit(0);
|
|
53
69
|
}
|
|
54
70
|
}
|
|
55
|
-
|
|
56
|
-
message: "Choose a starter template:",
|
|
57
|
-
options: [
|
|
58
|
-
{
|
|
59
|
-
value: "hello-world",
|
|
60
|
-
label: "Hello World",
|
|
61
|
-
hint: "Minimal fetch handler to get started"
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
value: "api",
|
|
65
|
-
label: "API",
|
|
66
|
-
hint: "REST endpoints with JSON responses"
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
value: "static-site",
|
|
70
|
-
label: "Static Site",
|
|
71
|
-
hint: "Server-rendered HTML pages"
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
value: "full-stack",
|
|
75
|
-
label: "Full Stack",
|
|
76
|
-
hint: "HTML pages + API routes"
|
|
77
|
-
}
|
|
78
|
-
]
|
|
79
|
-
});
|
|
80
|
-
if (typeof template === "symbol") {
|
|
81
|
-
outro("Project creation cancelled");
|
|
82
|
-
process.exit(0);
|
|
83
|
-
}
|
|
71
|
+
let template;
|
|
84
72
|
let uiFramework = "vanilla";
|
|
85
|
-
if (template === "
|
|
73
|
+
if (flags.template === "crank") {
|
|
74
|
+
template = "static-site";
|
|
75
|
+
uiFramework = "crank";
|
|
76
|
+
} else if (flags.template) {
|
|
77
|
+
const valid = ["hello-world", "api", "static-site", "full-stack"];
|
|
78
|
+
if (!valid.includes(flags.template)) {
|
|
79
|
+
console.error(
|
|
80
|
+
`Error: Unknown template "${flags.template}". Valid options: ${valid.join(", ")}, crank`
|
|
81
|
+
);
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
template = flags.template;
|
|
85
|
+
} else {
|
|
86
|
+
const templateResult = await select({
|
|
87
|
+
message: "Choose a starter template:",
|
|
88
|
+
options: [
|
|
89
|
+
{
|
|
90
|
+
value: "hello-world",
|
|
91
|
+
label: "Hello World",
|
|
92
|
+
hint: "Minimal fetch handler to get started"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
value: "api",
|
|
96
|
+
label: "API",
|
|
97
|
+
hint: "REST endpoints with JSON responses"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
value: "static-site",
|
|
101
|
+
label: "Static Site",
|
|
102
|
+
hint: "Server-rendered HTML pages"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
value: "full-stack",
|
|
106
|
+
label: "Full Stack",
|
|
107
|
+
hint: "HTML pages + API routes"
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
});
|
|
111
|
+
if (typeof templateResult === "symbol") {
|
|
112
|
+
outro("Project creation cancelled");
|
|
113
|
+
process.exit(0);
|
|
114
|
+
}
|
|
115
|
+
template = templateResult;
|
|
116
|
+
}
|
|
117
|
+
if (uiFramework === "vanilla" && (template === "static-site" || template === "full-stack")) {
|
|
86
118
|
const framework = await select({
|
|
87
119
|
message: "UI framework:",
|
|
88
120
|
initialValue: "crank",
|
|
@@ -115,39 +147,58 @@ async function main() {
|
|
|
115
147
|
}
|
|
116
148
|
uiFramework = framework;
|
|
117
149
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
150
|
+
let typescript;
|
|
151
|
+
if (flags.typescript !== void 0) {
|
|
152
|
+
typescript = flags.typescript;
|
|
153
|
+
} else {
|
|
154
|
+
const tsResult = await confirm({
|
|
155
|
+
message: "Use TypeScript?",
|
|
156
|
+
initialValue: true
|
|
157
|
+
});
|
|
158
|
+
if (typeof tsResult === "symbol") {
|
|
159
|
+
outro("Project creation cancelled");
|
|
160
|
+
process.exit(0);
|
|
161
|
+
}
|
|
162
|
+
typescript = tsResult;
|
|
125
163
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
164
|
+
let platform;
|
|
165
|
+
if (flags.platform) {
|
|
166
|
+
const valid = ["node", "bun", "cloudflare"];
|
|
167
|
+
if (!valid.includes(flags.platform)) {
|
|
168
|
+
console.error(
|
|
169
|
+
`Error: Unknown platform "${flags.platform}". Valid options: ${valid.join(", ")}`
|
|
170
|
+
);
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
platform = flags.platform;
|
|
174
|
+
} else {
|
|
175
|
+
const detectedPlatform = detectPlatform();
|
|
176
|
+
const platformResult = await select({
|
|
177
|
+
message: "Which platform?",
|
|
178
|
+
initialValue: detectedPlatform,
|
|
179
|
+
options: [
|
|
180
|
+
{
|
|
181
|
+
value: "node",
|
|
182
|
+
label: "Node.js",
|
|
183
|
+
hint: detectedPlatform === "node" ? "detected" : void 0
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
value: "bun",
|
|
187
|
+
label: "Bun",
|
|
188
|
+
hint: detectedPlatform === "bun" ? "detected" : void 0
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
value: "cloudflare",
|
|
192
|
+
label: "Cloudflare Workers",
|
|
193
|
+
hint: "Edge runtime"
|
|
194
|
+
}
|
|
195
|
+
]
|
|
196
|
+
});
|
|
197
|
+
if (typeof platformResult === "symbol") {
|
|
198
|
+
outro("Project creation cancelled");
|
|
199
|
+
process.exit(0);
|
|
200
|
+
}
|
|
201
|
+
platform = platformResult;
|
|
151
202
|
}
|
|
152
203
|
const config = {
|
|
153
204
|
name: projectName,
|
|
@@ -287,8 +338,10 @@ self.addEventListener("fetch", (event) => {
|
|
|
287
338
|
}
|
|
288
339
|
function generateApi(config) {
|
|
289
340
|
return `import { Router } from "@b9g/router";
|
|
341
|
+
import { logger } from "@b9g/router/middleware";
|
|
290
342
|
|
|
291
343
|
const router = new Router();
|
|
344
|
+
router.use(logger());
|
|
292
345
|
|
|
293
346
|
// In-memory data store
|
|
294
347
|
const users = [
|
|
@@ -622,8 +675,10 @@ function generateFullStackVanilla(config) {
|
|
|
622
675
|
const ext = config.typescript ? "ts" : "js";
|
|
623
676
|
const t = config.typescript;
|
|
624
677
|
return `import { Router } from "@b9g/router";
|
|
678
|
+
import { logger } from "@b9g/router/middleware";
|
|
625
679
|
|
|
626
680
|
const router = new Router();
|
|
681
|
+
router.use(logger());
|
|
627
682
|
|
|
628
683
|
// API routes
|
|
629
684
|
router.route("/api/hello").get(() => {
|
|
@@ -688,8 +743,10 @@ function generateFullStackHtmx(config) {
|
|
|
688
743
|
const ext = config.typescript ? "ts" : "js";
|
|
689
744
|
const t = config.typescript;
|
|
690
745
|
return `import { Router } from "@b9g/router";
|
|
746
|
+
import { logger } from "@b9g/router/middleware";
|
|
691
747
|
|
|
692
748
|
const router = new Router();
|
|
749
|
+
router.use(logger());
|
|
693
750
|
|
|
694
751
|
// API routes \u2014 return HTML fragments when HTMX requests, JSON otherwise
|
|
695
752
|
router.route("/api/hello").get((req) => {
|
|
@@ -764,8 +821,10 @@ function generateFullStackAlpine(config) {
|
|
|
764
821
|
const ext = config.typescript ? "ts" : "js";
|
|
765
822
|
const t = config.typescript;
|
|
766
823
|
return `import { Router } from "@b9g/router";
|
|
824
|
+
import { logger } from "@b9g/router/middleware";
|
|
767
825
|
|
|
768
826
|
const router = new Router();
|
|
827
|
+
router.use(logger());
|
|
769
828
|
|
|
770
829
|
// API routes
|
|
771
830
|
router.route("/api/hello").get(() => {
|
|
@@ -837,9 +896,11 @@ self.addEventListener("fetch", (event) => {
|
|
|
837
896
|
function generateFullStackCrank(config) {
|
|
838
897
|
const t = config.typescript;
|
|
839
898
|
return `import { Router } from "@b9g/router";
|
|
899
|
+
import { logger } from "@b9g/router/middleware";
|
|
840
900
|
import {renderer} from "@b9g/crank/html";
|
|
841
901
|
|
|
842
902
|
const router = new Router();
|
|
903
|
+
router.use(logger());
|
|
843
904
|
|
|
844
905
|
const css = \`
|
|
845
906
|
${css}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@b9g/shovel",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"description": "ServiceWorker-first universal deployment platform. Write ServiceWorker apps once, deploy anywhere (Node/Bun/Cloudflare). Registry-based multi-app orchestration.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
|
-
"url": "https://github.com/bikeshaving/shovel.git"
|
|
8
|
+
"url": "git+https://github.com/bikeshaving/shovel.git"
|
|
9
9
|
},
|
|
10
10
|
"bin": {
|
|
11
11
|
"shovel": "bin/cli.js",
|
|
@@ -16,11 +16,11 @@
|
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@b9g/async-context": "^0.2.1",
|
|
18
18
|
"@b9g/cache": "^0.2.2",
|
|
19
|
-
"@b9g/filesystem": "^0.1.
|
|
19
|
+
"@b9g/filesystem": "^0.1.11",
|
|
20
20
|
"@b9g/http-errors": "^0.2.1",
|
|
21
21
|
"@b9g/node-webworker": "^0.2.1",
|
|
22
22
|
"@b9g/platform": "^0.1.17",
|
|
23
|
-
"@b9g/platform-bun": "^0.1.
|
|
23
|
+
"@b9g/platform-bun": "^0.1.16",
|
|
24
24
|
"@b9g/platform-cloudflare": "^0.1.15",
|
|
25
25
|
"@b9g/platform-node": "^0.1.17",
|
|
26
26
|
"@clack/prompts": "^0.7.0",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"@b9g/assets": "^0.2.1",
|
|
37
37
|
"@b9g/crank": "^0.7.2",
|
|
38
38
|
"@b9g/libuild": "^0.1.22",
|
|
39
|
-
"@b9g/router": "^0.2.
|
|
39
|
+
"@b9g/router": "^0.2.2",
|
|
40
40
|
"@logtape/file": "^1.0.0",
|
|
41
41
|
"@types/bun": "^1.3.4",
|
|
42
42
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
@@ -448,10 +448,15 @@ function createConfigPlugin(projectRoot, outDir = "dist", options = {}) {
|
|
|
448
448
|
const typesPath = join2(serverOutDir, "shovel.d.ts");
|
|
449
449
|
writeFileSync2(typesPath, typesCode);
|
|
450
450
|
}
|
|
451
|
+
const watchFiles = [
|
|
452
|
+
join2(projectRoot, "shovel.json"),
|
|
453
|
+
join2(projectRoot, "package.json")
|
|
454
|
+
];
|
|
451
455
|
return {
|
|
452
456
|
contents: configModuleCode,
|
|
453
457
|
loader: "js",
|
|
454
|
-
resolveDir: projectRoot
|
|
458
|
+
resolveDir: projectRoot,
|
|
459
|
+
watchFiles
|
|
455
460
|
};
|
|
456
461
|
});
|
|
457
462
|
}
|
|
@@ -720,7 +725,6 @@ var ServerBundler = class {
|
|
|
720
725
|
#initialBuildComplete;
|
|
721
726
|
#initialBuildResolve;
|
|
722
727
|
#currentOutputs;
|
|
723
|
-
#configWatchers;
|
|
724
728
|
#dirWatchers;
|
|
725
729
|
#userEntryPath;
|
|
726
730
|
#watchOptions;
|
|
@@ -732,7 +736,6 @@ var ServerBundler = class {
|
|
|
732
736
|
this.#projectRoot = findProjectRoot();
|
|
733
737
|
this.#initialBuildComplete = false;
|
|
734
738
|
this.#currentOutputs = { worker: "" };
|
|
735
|
-
this.#configWatchers = [];
|
|
736
739
|
this.#dirWatchers = /* @__PURE__ */ new Map();
|
|
737
740
|
this.#userEntryPath = "";
|
|
738
741
|
this.#changedFiles = /* @__PURE__ */ new Set();
|
|
@@ -798,9 +801,18 @@ var ServerBundler = class {
|
|
|
798
801
|
this.#ctx = await ESBuild2.context(buildOptions);
|
|
799
802
|
logger3.debug("Starting esbuild watch mode");
|
|
800
803
|
await this.#ctx.watch();
|
|
801
|
-
this.#watchConfigFiles();
|
|
802
804
|
return initialBuildPromise;
|
|
803
805
|
}
|
|
806
|
+
/**
|
|
807
|
+
* Trigger an immediate rebuild.
|
|
808
|
+
* Only works in watch mode (after calling watch()).
|
|
809
|
+
*/
|
|
810
|
+
async rebuild() {
|
|
811
|
+
if (!this.#ctx) {
|
|
812
|
+
throw new Error("Cannot rebuild: bundler is not in watch mode");
|
|
813
|
+
}
|
|
814
|
+
await this.#ctx.rebuild();
|
|
815
|
+
}
|
|
804
816
|
/**
|
|
805
817
|
* Stop watching and dispose of resources.
|
|
806
818
|
*/
|
|
@@ -809,10 +821,6 @@ var ServerBundler = class {
|
|
|
809
821
|
clearTimeout(this.#rebuildTimeout);
|
|
810
822
|
this.#rebuildTimeout = void 0;
|
|
811
823
|
}
|
|
812
|
-
for (const watcher of this.#configWatchers) {
|
|
813
|
-
watcher.close();
|
|
814
|
-
}
|
|
815
|
-
this.#configWatchers = [];
|
|
816
824
|
for (const entry of this.#dirWatchers.values()) {
|
|
817
825
|
entry.watcher.close();
|
|
818
826
|
}
|
|
@@ -1123,30 +1131,6 @@ These modules are not bundled and won't be available at runtime.`
|
|
|
1123
1131
|
}
|
|
1124
1132
|
}
|
|
1125
1133
|
}
|
|
1126
|
-
/**
|
|
1127
|
-
* Watch config files for changes.
|
|
1128
|
-
*/
|
|
1129
|
-
#watchConfigFiles() {
|
|
1130
|
-
const configFiles = ["shovel.json", "package.json"];
|
|
1131
|
-
for (const filename of configFiles) {
|
|
1132
|
-
const filepath = join5(this.#projectRoot, filename);
|
|
1133
|
-
if (!existsSync4(filepath))
|
|
1134
|
-
continue;
|
|
1135
|
-
try {
|
|
1136
|
-
const watcher = watch(filepath, { persistent: false }, (event) => {
|
|
1137
|
-
if (event === "change") {
|
|
1138
|
-
this.#scheduleRebuild(filepath);
|
|
1139
|
-
}
|
|
1140
|
-
});
|
|
1141
|
-
this.#configWatchers.push(watcher);
|
|
1142
|
-
} catch (err) {
|
|
1143
|
-
logger3.warn("Failed to watch {file}: {error}", {
|
|
1144
|
-
file: filename,
|
|
1145
|
-
error: err
|
|
1146
|
-
});
|
|
1147
|
-
}
|
|
1148
|
-
}
|
|
1149
|
-
}
|
|
1150
1134
|
/**
|
|
1151
1135
|
* Update source file watchers from metafile.
|
|
1152
1136
|
*/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ServerBundler,
|
|
3
3
|
loadPlatformModule
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-DQDUKJQ4.js";
|
|
5
5
|
import {
|
|
6
6
|
DEFAULTS
|
|
7
7
|
} from "./chunk-7GONPLNW.js";
|
|
@@ -56,6 +56,7 @@ async function developCommand(entrypoint, options, config) {
|
|
|
56
56
|
const platformModule = await loadPlatformModule(platformName);
|
|
57
57
|
const platformESBuildConfig = platformModule.getESBuildConfig();
|
|
58
58
|
let devServer = null;
|
|
59
|
+
const SHORTCUTS_HELP = "Shortcuts: Ctrl+R (reload) \xB7 Ctrl+L (clear) \xB7 Ctrl+C (quit) \xB7 ? (help)";
|
|
59
60
|
const startOrReloadServer = async (workerPath) => {
|
|
60
61
|
if (!devServer) {
|
|
61
62
|
devServer = await platformModule.createDevServer({
|
|
@@ -73,6 +74,9 @@ async function developCommand(entrypoint, options, config) {
|
|
|
73
74
|
} else {
|
|
74
75
|
logger.info("Server running at {url}", { url: urls.local });
|
|
75
76
|
}
|
|
77
|
+
if (process.stdin.isTTY) {
|
|
78
|
+
logger.info(SHORTCUTS_HELP);
|
|
79
|
+
}
|
|
76
80
|
} else {
|
|
77
81
|
await devServer.reload(workerPath);
|
|
78
82
|
}
|
|
@@ -109,6 +113,28 @@ async function developCommand(entrypoint, options, config) {
|
|
|
109
113
|
};
|
|
110
114
|
process.on("SIGINT", () => shutdown("SIGINT"));
|
|
111
115
|
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
|
116
|
+
if (process.stdin.isTTY) {
|
|
117
|
+
process.stdin.setRawMode(true);
|
|
118
|
+
process.stdin.resume();
|
|
119
|
+
process.stdin.setEncoding("utf8");
|
|
120
|
+
process.stdin.on("data", async (key) => {
|
|
121
|
+
switch (key) {
|
|
122
|
+
case "":
|
|
123
|
+
logger.info("Manual reload...");
|
|
124
|
+
await bundler.rebuild();
|
|
125
|
+
break;
|
|
126
|
+
case "\f":
|
|
127
|
+
console.clear();
|
|
128
|
+
break;
|
|
129
|
+
case "":
|
|
130
|
+
await shutdown("SIGINT");
|
|
131
|
+
break;
|
|
132
|
+
case "?":
|
|
133
|
+
logger.info(SHORTCUTS_HELP);
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
}
|
|
112
138
|
await new Promise(() => {
|
|
113
139
|
});
|
|
114
140
|
} catch (error) {
|