@b9g/shovel 0.2.0-beta.2 → 0.2.0-beta.4
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/bin/cli.js +88 -107
- package/package.json +4 -4
package/bin/cli.js
CHANGED
|
@@ -23,7 +23,6 @@ import * as Platform from "@b9g/platform";
|
|
|
23
23
|
|
|
24
24
|
// src/esbuild/watcher.ts
|
|
25
25
|
import * as ESBuild from "esbuild";
|
|
26
|
-
import { watch } from "fs";
|
|
27
26
|
import { resolve, dirname as dirname2, join } from "path";
|
|
28
27
|
import { readFileSync } from "fs";
|
|
29
28
|
import { mkdir } from "fs/promises";
|
|
@@ -36,8 +35,8 @@ import { pathToFileURL } from "url";
|
|
|
36
35
|
function importMetaPlugin() {
|
|
37
36
|
return {
|
|
38
37
|
name: "import-meta-transform",
|
|
39
|
-
setup(
|
|
40
|
-
|
|
38
|
+
setup(build2) {
|
|
39
|
+
build2.onLoad({ filter: /\.[jt]sx?$/, namespace: "file" }, async (args) => {
|
|
41
40
|
if (args.path.includes("node_modules")) {
|
|
42
41
|
return null;
|
|
43
42
|
}
|
|
@@ -82,115 +81,102 @@ function importMetaPlugin() {
|
|
|
82
81
|
import { getLogger } from "@logtape/logtape";
|
|
83
82
|
var logger = getLogger(["watcher"]);
|
|
84
83
|
var Watcher = class {
|
|
85
|
-
#watcher;
|
|
86
|
-
#building;
|
|
87
84
|
#options;
|
|
85
|
+
#ctx;
|
|
86
|
+
#initialBuildComplete = false;
|
|
87
|
+
#initialBuildSuccess = false;
|
|
88
|
+
#initialBuildResolve;
|
|
88
89
|
constructor(options) {
|
|
89
|
-
this.#building = false;
|
|
90
90
|
this.#options = options;
|
|
91
91
|
}
|
|
92
92
|
/**
|
|
93
93
|
* Start watching and building
|
|
94
|
+
* @returns true if initial build succeeded, false if it failed
|
|
94
95
|
*/
|
|
95
96
|
async start() {
|
|
96
97
|
const entryPath = resolve(this.#options.entrypoint);
|
|
97
|
-
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
98
|
+
const outputDir = resolve(this.#options.outDir);
|
|
99
|
+
const workspaceRoot = this.#findWorkspaceRoot();
|
|
100
|
+
await mkdir(join(outputDir, "server"), { recursive: true });
|
|
101
|
+
await mkdir(join(outputDir, "static"), { recursive: true });
|
|
102
|
+
const initialBuildPromise = new Promise((resolve3) => {
|
|
103
|
+
this.#initialBuildResolve = resolve3;
|
|
104
|
+
});
|
|
105
|
+
this.#ctx = await ESBuild.context({
|
|
106
|
+
entryPoints: [entryPath],
|
|
107
|
+
bundle: true,
|
|
108
|
+
format: "esm",
|
|
109
|
+
target: "es2022",
|
|
110
|
+
platform: "node",
|
|
111
|
+
outfile: `${outputDir}/server/app.js`,
|
|
112
|
+
// No packages: "external" - bundle everything for dev/prod parity
|
|
113
|
+
absWorkingDir: workspaceRoot,
|
|
114
|
+
plugins: [
|
|
115
|
+
importMetaPlugin(),
|
|
116
|
+
assetsPlugin({
|
|
117
|
+
outDir: outputDir
|
|
118
|
+
}),
|
|
119
|
+
// Plugin to detect build completion (works with watch mode)
|
|
120
|
+
{
|
|
121
|
+
name: "build-notify",
|
|
122
|
+
setup: (build2) => {
|
|
123
|
+
build2.onStart(() => {
|
|
124
|
+
logger.info("Building", {
|
|
125
|
+
entrypoint: this.#options.entrypoint
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
build2.onEnd((result) => {
|
|
129
|
+
const version = Date.now();
|
|
130
|
+
const success = result.errors.length === 0;
|
|
131
|
+
if (success) {
|
|
132
|
+
logger.info("Build complete", { version });
|
|
133
|
+
} else {
|
|
134
|
+
logger.error("Build errors", { errors: result.errors });
|
|
135
|
+
}
|
|
136
|
+
if (!this.#initialBuildComplete) {
|
|
137
|
+
this.#initialBuildComplete = true;
|
|
138
|
+
this.#initialBuildSuccess = success;
|
|
139
|
+
this.#initialBuildResolve?.(success);
|
|
140
|
+
} else {
|
|
141
|
+
this.#options.onBuild?.(success, version);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
108
144
|
}
|
|
109
|
-
this.#debouncedBuild();
|
|
110
145
|
}
|
|
111
|
-
|
|
112
|
-
|
|
146
|
+
],
|
|
147
|
+
sourcemap: "inline",
|
|
148
|
+
minify: false,
|
|
149
|
+
treeShaking: true
|
|
150
|
+
});
|
|
151
|
+
logger.info("Starting esbuild watch mode");
|
|
152
|
+
await this.#ctx.watch();
|
|
153
|
+
return initialBuildPromise;
|
|
113
154
|
}
|
|
114
155
|
/**
|
|
115
|
-
* Stop watching
|
|
156
|
+
* Stop watching and dispose of esbuild context
|
|
116
157
|
*/
|
|
117
158
|
async stop() {
|
|
118
|
-
if (this.#
|
|
119
|
-
this.#
|
|
120
|
-
this.#
|
|
159
|
+
if (this.#ctx) {
|
|
160
|
+
await this.#ctx.dispose();
|
|
161
|
+
this.#ctx = void 0;
|
|
121
162
|
}
|
|
122
163
|
}
|
|
123
|
-
#
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
if (this.#building)
|
|
134
|
-
return;
|
|
135
|
-
this.#building = true;
|
|
136
|
-
try {
|
|
137
|
-
const entryPath = resolve(this.#options.entrypoint);
|
|
138
|
-
const outputDir = resolve(this.#options.outDir);
|
|
139
|
-
const version = Date.now();
|
|
140
|
-
const initialCwd = process.cwd();
|
|
141
|
-
let workspaceRoot = initialCwd;
|
|
142
|
-
while (workspaceRoot !== dirname2(workspaceRoot)) {
|
|
143
|
-
try {
|
|
144
|
-
const packageJSON = JSON.parse(
|
|
145
|
-
readFileSync(resolve(workspaceRoot, "package.json"), "utf8")
|
|
146
|
-
);
|
|
147
|
-
if (packageJSON.workspaces) {
|
|
148
|
-
break;
|
|
149
|
-
}
|
|
150
|
-
} catch {
|
|
164
|
+
#findWorkspaceRoot() {
|
|
165
|
+
const initialCwd = process.cwd();
|
|
166
|
+
let workspaceRoot = initialCwd;
|
|
167
|
+
while (workspaceRoot !== dirname2(workspaceRoot)) {
|
|
168
|
+
try {
|
|
169
|
+
const packageJSON = JSON.parse(
|
|
170
|
+
readFileSync(resolve(workspaceRoot, "package.json"), "utf8")
|
|
171
|
+
);
|
|
172
|
+
if (packageJSON.workspaces) {
|
|
173
|
+
return workspaceRoot;
|
|
151
174
|
}
|
|
152
|
-
|
|
175
|
+
} catch {
|
|
153
176
|
}
|
|
154
|
-
|
|
155
|
-
workspaceRoot = initialCwd;
|
|
156
|
-
}
|
|
157
|
-
logger.info("Building", { entryPath });
|
|
158
|
-
logger.info("Workspace root", { workspaceRoot });
|
|
159
|
-
await mkdir(join(outputDir, "server"), { recursive: true });
|
|
160
|
-
await mkdir(join(outputDir, "assets"), { recursive: true });
|
|
161
|
-
const result = await ESBuild.build({
|
|
162
|
-
entryPoints: [entryPath],
|
|
163
|
-
bundle: true,
|
|
164
|
-
format: "esm",
|
|
165
|
-
target: "es2022",
|
|
166
|
-
platform: "node",
|
|
167
|
-
outfile: `${outputDir}/server/app.js`,
|
|
168
|
-
packages: "external",
|
|
169
|
-
absWorkingDir: workspaceRoot,
|
|
170
|
-
plugins: [
|
|
171
|
-
importMetaPlugin(),
|
|
172
|
-
assetsPlugin({
|
|
173
|
-
outputDir: `${outputDir}/assets`,
|
|
174
|
-
manifest: `${outputDir}/server/asset-manifest.json`
|
|
175
|
-
})
|
|
176
|
-
],
|
|
177
|
-
sourcemap: "inline",
|
|
178
|
-
minify: false,
|
|
179
|
-
treeShaking: true
|
|
180
|
-
});
|
|
181
|
-
if (result.errors.length > 0) {
|
|
182
|
-
logger.error("Build errors", { errors: result.errors });
|
|
183
|
-
this.#options.onBuild?.(false, version);
|
|
184
|
-
} else {
|
|
185
|
-
logger.info("Build complete", { version });
|
|
186
|
-
this.#options.onBuild?.(true, version);
|
|
187
|
-
}
|
|
188
|
-
} catch (error) {
|
|
189
|
-
logger.error("Build failed", { error });
|
|
190
|
-
this.#options.onBuild?.(false, Date.now());
|
|
191
|
-
} finally {
|
|
192
|
-
this.#building = false;
|
|
177
|
+
workspaceRoot = dirname2(workspaceRoot);
|
|
193
178
|
}
|
|
179
|
+
return initialCwd;
|
|
194
180
|
}
|
|
195
181
|
};
|
|
196
182
|
|
|
@@ -248,9 +234,10 @@ async function developCommand(entrypoint, options) {
|
|
|
248
234
|
}
|
|
249
235
|
}
|
|
250
236
|
});
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
237
|
+
const buildSuccess = await watcher.start();
|
|
238
|
+
if (!buildSuccess) {
|
|
239
|
+
logger2.error("Initial build failed, watching for changes to retry", {});
|
|
240
|
+
}
|
|
254
241
|
const builtEntrypoint = `${outDir}/server/app.js`;
|
|
255
242
|
serviceWorker = await platformInstance.loadServiceWorker(builtEntrypoint, {
|
|
256
243
|
hotReload: true,
|
|
@@ -277,8 +264,7 @@ async function developCommand(entrypoint, options) {
|
|
|
277
264
|
process.on("SIGINT", () => shutdown("SIGINT"));
|
|
278
265
|
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
|
279
266
|
} catch (error) {
|
|
280
|
-
logger2.error("Failed to start development server", {
|
|
281
|
-
error: error.message,
|
|
267
|
+
logger2.error("Failed to start development server:\n{stack}", {
|
|
282
268
|
stack: error.stack
|
|
283
269
|
});
|
|
284
270
|
process.exit(1);
|
|
@@ -385,8 +371,7 @@ var BUILD_DEFAULTS = {
|
|
|
385
371
|
};
|
|
386
372
|
var BUILD_STRUCTURE = {
|
|
387
373
|
serverDir: "server",
|
|
388
|
-
staticDir: "static"
|
|
389
|
-
assetsDir: "static/assets"
|
|
374
|
+
staticDir: "static"
|
|
390
375
|
};
|
|
391
376
|
async function buildForProduction({
|
|
392
377
|
entrypoint,
|
|
@@ -414,7 +399,7 @@ async function buildForProduction({
|
|
|
414
399
|
if (verbose) {
|
|
415
400
|
logger5.info("Built app to", { outputDir: buildContext.outputDir });
|
|
416
401
|
logger5.info("Server files", { dir: buildContext.serverDir });
|
|
417
|
-
logger5.info("
|
|
402
|
+
logger5.info("Static files", { dir: join2(buildContext.outputDir, "static") });
|
|
418
403
|
}
|
|
419
404
|
}
|
|
420
405
|
async function initializeBuild({
|
|
@@ -462,7 +447,6 @@ async function initializeBuild({
|
|
|
462
447
|
await mkdir2(outputDir, { recursive: true });
|
|
463
448
|
await mkdir2(join2(outputDir, BUILD_STRUCTURE.serverDir), { recursive: true });
|
|
464
449
|
await mkdir2(join2(outputDir, BUILD_STRUCTURE.staticDir), { recursive: true });
|
|
465
|
-
await mkdir2(join2(outputDir, BUILD_STRUCTURE.assetsDir), { recursive: true });
|
|
466
450
|
} catch (error) {
|
|
467
451
|
throw new Error(
|
|
468
452
|
`Failed to create output directory structure: ${error.message}`
|
|
@@ -472,7 +456,6 @@ async function initializeBuild({
|
|
|
472
456
|
entryPath,
|
|
473
457
|
outputDir,
|
|
474
458
|
serverDir: join2(outputDir, BUILD_STRUCTURE.serverDir),
|
|
475
|
-
assetsDir: join2(outputDir, BUILD_STRUCTURE.assetsDir),
|
|
476
459
|
workspaceRoot,
|
|
477
460
|
platform,
|
|
478
461
|
verbose,
|
|
@@ -517,8 +500,8 @@ async function findShovelPackageRoot() {
|
|
|
517
500
|
}
|
|
518
501
|
async function createBuildConfig({
|
|
519
502
|
entryPath,
|
|
503
|
+
outputDir,
|
|
520
504
|
serverDir,
|
|
521
|
-
assetsDir,
|
|
522
505
|
workspaceRoot,
|
|
523
506
|
platform,
|
|
524
507
|
workerCount
|
|
@@ -546,8 +529,7 @@ async function createBuildConfig({
|
|
|
546
529
|
plugins: [
|
|
547
530
|
importMetaPlugin(),
|
|
548
531
|
assetsPlugin2({
|
|
549
|
-
|
|
550
|
-
manifest: join2(serverDir, "asset-manifest.json")
|
|
532
|
+
outDir: outputDir
|
|
551
533
|
})
|
|
552
534
|
],
|
|
553
535
|
metafile: true,
|
|
@@ -614,8 +596,7 @@ async function createBuildConfig({
|
|
|
614
596
|
plugins: isCloudflare ? [
|
|
615
597
|
importMetaPlugin(),
|
|
616
598
|
assetsPlugin2({
|
|
617
|
-
|
|
618
|
-
manifest: join2(serverDir, "asset-manifest.json")
|
|
599
|
+
outDir: outputDir
|
|
619
600
|
})
|
|
620
601
|
] : [],
|
|
621
602
|
// Assets already handled in user code build
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@b9g/shovel",
|
|
3
|
-
"version": "0.2.0-beta.
|
|
3
|
+
"version": "0.2.0-beta.4",
|
|
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
|
"bin": {
|
|
@@ -21,13 +21,13 @@
|
|
|
21
21
|
"source-map": "^0.7.4"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@b9g/assets": "^0.1.
|
|
24
|
+
"@b9g/assets": "^0.1.9",
|
|
25
25
|
"@b9g/cache": "^0.1.4",
|
|
26
26
|
"@b9g/crank": "^0.7.2",
|
|
27
27
|
"@b9g/filesystem": "^0.1.5",
|
|
28
28
|
"@b9g/http-errors": "^0.1.4",
|
|
29
29
|
"@b9g/libuild": "^0.1.17",
|
|
30
|
-
"@b9g/platform": "^0.1.
|
|
30
|
+
"@b9g/platform": "^0.1.7",
|
|
31
31
|
"@b9g/platform-bun": "^0.1.6",
|
|
32
32
|
"@b9g/platform-cloudflare": "^0.1.5",
|
|
33
33
|
"@b9g/platform-node": "^0.1.8",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"@b9g/node-webworker": "^0.1.3",
|
|
41
|
-
"@b9g/platform": "^0.1.
|
|
41
|
+
"@b9g/platform": "^0.1.7",
|
|
42
42
|
"@b9g/platform-node": "^0.1.8",
|
|
43
43
|
"@b9g/platform-cloudflare": "^0.1.5",
|
|
44
44
|
"@b9g/platform-bun": "^0.1.6",
|