@b9g/shovel 0.2.0-beta.4 → 0.2.0-beta.5

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.
Files changed (2) hide show
  1. package/bin/cli.js +47 -17
  2. package/package.json +15 -15
package/bin/cli.js CHANGED
@@ -25,7 +25,7 @@ import * as Platform from "@b9g/platform";
25
25
  import * as ESBuild from "esbuild";
26
26
  import { resolve, dirname as dirname2, join } from "path";
27
27
  import { readFileSync } from "fs";
28
- import { mkdir } from "fs/promises";
28
+ import { mkdir, unlink } from "fs/promises";
29
29
  import { assetsPlugin } from "@b9g/assets/plugin";
30
30
 
31
31
  // src/esbuild/import-meta-plugin.ts
@@ -83,15 +83,19 @@ var logger = getLogger(["watcher"]);
83
83
  var Watcher = class {
84
84
  #options;
85
85
  #ctx;
86
- #initialBuildComplete = false;
87
- #initialBuildSuccess = false;
86
+ #initialBuildComplete;
88
87
  #initialBuildResolve;
88
+ #currentEntrypoint;
89
+ #previousEntrypoint;
89
90
  constructor(options) {
90
91
  this.#options = options;
92
+ this.#initialBuildComplete = false;
93
+ this.#currentEntrypoint = "";
94
+ this.#previousEntrypoint = "";
91
95
  }
92
96
  /**
93
97
  * Start watching and building
94
- * @returns true if initial build succeeded, false if it failed
98
+ * @returns Result with success status and the hashed entrypoint path
95
99
  */
96
100
  async start() {
97
101
  const entryPath = resolve(this.#options.entrypoint);
@@ -108,8 +112,9 @@ var Watcher = class {
108
112
  format: "esm",
109
113
  target: "es2022",
110
114
  platform: "node",
111
- outfile: `${outputDir}/server/app.js`,
112
- // No packages: "external" - bundle everything for dev/prod parity
115
+ outdir: `${outputDir}/server`,
116
+ entryNames: "[name]-[hash]",
117
+ metafile: true,
113
118
  absWorkingDir: workspaceRoot,
114
119
  plugins: [
115
120
  importMetaPlugin(),
@@ -125,20 +130,41 @@ var Watcher = class {
125
130
  entrypoint: this.#options.entrypoint
126
131
  });
127
132
  });
128
- build2.onEnd((result) => {
129
- const version = Date.now();
133
+ build2.onEnd(async (result) => {
130
134
  const success = result.errors.length === 0;
135
+ let outputPath = "";
136
+ if (result.metafile) {
137
+ const outputs = Object.keys(result.metafile.outputs);
138
+ const jsOutput = outputs.find((p) => p.endsWith(".js"));
139
+ if (jsOutput) {
140
+ outputPath = resolve(jsOutput);
141
+ }
142
+ }
131
143
  if (success) {
132
- logger.info("Build complete", { version });
144
+ logger.info("Build complete", { entrypoint: outputPath });
145
+ if (this.#currentEntrypoint && this.#currentEntrypoint !== outputPath) {
146
+ try {
147
+ await unlink(this.#currentEntrypoint);
148
+ await unlink(this.#currentEntrypoint + ".map").catch(
149
+ () => {
150
+ }
151
+ );
152
+ logger.debug("Cleaned up old build", {
153
+ oldEntrypoint: this.#currentEntrypoint
154
+ });
155
+ } catch {
156
+ }
157
+ }
133
158
  } else {
134
159
  logger.error("Build errors", { errors: result.errors });
135
160
  }
161
+ this.#previousEntrypoint = this.#currentEntrypoint;
162
+ this.#currentEntrypoint = outputPath;
136
163
  if (!this.#initialBuildComplete) {
137
164
  this.#initialBuildComplete = true;
138
- this.#initialBuildSuccess = success;
139
- this.#initialBuildResolve?.(success);
165
+ this.#initialBuildResolve?.({ success, entrypoint: outputPath });
140
166
  } else {
141
- this.#options.onBuild?.(success, version);
167
+ this.#options.onBuild?.(success, outputPath);
142
168
  }
143
169
  });
144
170
  }
@@ -224,21 +250,20 @@ async function developCommand(entrypoint, options) {
224
250
  const watcher = new Watcher({
225
251
  entrypoint,
226
252
  outDir,
227
- onBuild: async (success, version) => {
253
+ onBuild: async (success, builtEntrypoint2) => {
228
254
  if (success && serviceWorker) {
229
- logger2.info("Reloading Workers", { version });
255
+ logger2.info("Reloading Workers", { entrypoint: builtEntrypoint2 });
230
256
  if (platformInstance && typeof platformInstance.reloadWorkers === "function") {
231
- await platformInstance.reloadWorkers(version);
257
+ await platformInstance.reloadWorkers(builtEntrypoint2);
232
258
  }
233
259
  logger2.info("Workers reloaded", {});
234
260
  }
235
261
  }
236
262
  });
237
- const buildSuccess = await watcher.start();
263
+ const { success: buildSuccess, entrypoint: builtEntrypoint } = await watcher.start();
238
264
  if (!buildSuccess) {
239
265
  logger2.error("Initial build failed, watching for changes to retry", {});
240
266
  }
241
- const builtEntrypoint = `${outDir}/server/app.js`;
242
267
  serviceWorker = await platformInstance.loadServiceWorker(builtEntrypoint, {
243
268
  hotReload: true,
244
269
  workerCount
@@ -526,6 +551,11 @@ async function createBuildConfig({
526
551
  absWorkingDir: workspaceRoot || dirname3(entryPath),
527
552
  mainFields: ["module", "main"],
528
553
  conditions: ["import", "module"],
554
+ // Allow user code to import @b9g packages from shovel's packages directory
555
+ nodePaths: [
556
+ join2(shovelRoot, "packages"),
557
+ join2(shovelRoot, "node_modules")
558
+ ],
529
559
  plugins: [
530
560
  importMetaPlugin(),
531
561
  assetsPlugin2({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@b9g/shovel",
3
- "version": "0.2.0-beta.4",
3
+ "version": "0.2.0-beta.5",
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,30 +21,30 @@
21
21
  "source-map": "^0.7.4"
22
22
  },
23
23
  "devDependencies": {
24
- "@b9g/assets": "^0.1.9",
24
+ "@b9g/assets": "^0.1.12",
25
25
  "@b9g/cache": "^0.1.4",
26
26
  "@b9g/crank": "^0.7.2",
27
- "@b9g/filesystem": "^0.1.5",
28
- "@b9g/http-errors": "^0.1.4",
27
+ "@b9g/filesystem": "^0.1.6",
28
+ "@b9g/http-errors": "^0.1.5",
29
29
  "@b9g/libuild": "^0.1.17",
30
- "@b9g/platform": "^0.1.7",
31
- "@b9g/platform-bun": "^0.1.6",
32
- "@b9g/platform-cloudflare": "^0.1.5",
33
- "@b9g/platform-node": "^0.1.8",
34
- "@b9g/router": "^0.1.6",
30
+ "@b9g/platform": "^0.1.9",
31
+ "@b9g/platform-bun": "^0.1.7",
32
+ "@b9g/platform-cloudflare": "^0.1.6",
33
+ "@b9g/platform-node": "^0.1.9",
34
+ "@b9g/router": "^0.1.7",
35
35
  "@types/bun": "^1.2.2",
36
36
  "mitata": "^1.0.34",
37
37
  "typescript": "^5.7.3"
38
38
  },
39
39
  "peerDependencies": {
40
40
  "@b9g/node-webworker": "^0.1.3",
41
- "@b9g/platform": "^0.1.7",
42
- "@b9g/platform-node": "^0.1.8",
43
- "@b9g/platform-cloudflare": "^0.1.5",
44
- "@b9g/platform-bun": "^0.1.6",
41
+ "@b9g/platform": "^0.1.9",
42
+ "@b9g/platform-node": "^0.1.9",
43
+ "@b9g/platform-cloudflare": "^0.1.6",
44
+ "@b9g/platform-bun": "^0.1.7",
45
45
  "@b9g/cache": "^0.1.4",
46
- "@b9g/filesystem": "^0.1.5",
47
- "@b9g/http-errors": "^0.1.4"
46
+ "@b9g/filesystem": "^0.1.6",
47
+ "@b9g/http-errors": "^0.1.5"
48
48
  },
49
49
  "peerDependenciesMeta": {
50
50
  "@b9g/platform": {