@whatalo/cli-kit 1.1.0 → 1.1.1

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.
@@ -105,6 +105,7 @@ var BundleBuilder = class {
105
105
  `Build output directory "${absoluteOutputDir}" is empty after build.`
106
106
  );
107
107
  }
108
+ await this.validateIndexHtmlForCdn(files);
108
109
  const totalSize = files.reduce((sum, f) => sum + f.size, 0);
109
110
  if (totalSize > MAX_BUNDLE_SIZE_BYTES) {
110
111
  throw new Error(
@@ -114,6 +115,23 @@ var BundleBuilder = class {
114
115
  const duration = Date.now() - startTime;
115
116
  return { files, totalSize, duration };
116
117
  }
118
+ /**
119
+ * Ensures index.html uses relative asset URLs so bundles work under
120
+ * session-scoped CDN paths like /dev-bundles/{sessionId}/.
121
+ */
122
+ async validateIndexHtmlForCdn(files) {
123
+ const indexFile = files.find((file) => file.relativePath === "index.html");
124
+ if (!indexFile) {
125
+ return;
126
+ }
127
+ const html = await (0, import_promises.readFile)(indexFile.absolutePath, "utf-8");
128
+ const hasRootAbsoluteAssetRefs = /(?:src|href)=["']\/assets\//i.test(html) || /(?:src|href)=["']\/[a-z0-9._-]+\//i.test(html);
129
+ if (hasRootAbsoluteAssetRefs) {
130
+ throw new Error(
131
+ "Build output uses root-absolute asset paths in index.html. CDN dev bundles are served from a subpath, so assets must be relative. If you use Vite, set `base: './'` in vite.config.ts and rebuild."
132
+ );
133
+ }
134
+ }
117
135
  /**
118
136
  * Spawns the build process and waits for it to finish.
119
137
  * Captures stderr for error reporting on non-zero exit.
@@ -40,6 +40,11 @@ declare class BundleBuilder {
40
40
  * @throws If the build exits with a non-zero code or if total size exceeds 10 MB
41
41
  */
42
42
  build(buildCommand: string, outputDir: string, cwd?: string): Promise<BuildResult>;
43
+ /**
44
+ * Ensures index.html uses relative asset URLs so bundles work under
45
+ * session-scoped CDN paths like /dev-bundles/{sessionId}/.
46
+ */
47
+ private validateIndexHtmlForCdn;
43
48
  /**
44
49
  * Spawns the build process and waits for it to finish.
45
50
  * Captures stderr for error reporting on non-zero exit.
@@ -40,6 +40,11 @@ declare class BundleBuilder {
40
40
  * @throws If the build exits with a non-zero code or if total size exceeds 10 MB
41
41
  */
42
42
  build(buildCommand: string, outputDir: string, cwd?: string): Promise<BuildResult>;
43
+ /**
44
+ * Ensures index.html uses relative asset URLs so bundles work under
45
+ * session-scoped CDN paths like /dev-bundles/{sessionId}/.
46
+ */
47
+ private validateIndexHtmlForCdn;
43
48
  /**
44
49
  * Spawns the build process and waits for it to finish.
45
50
  * Captures stderr for error reporting on non-zero exit.
@@ -1,6 +1,6 @@
1
1
  // src/bundle/builder.ts
2
2
  import { spawn } from "child_process";
3
- import { readdir, stat } from "fs/promises";
3
+ import { readFile, readdir, stat } from "fs/promises";
4
4
  import path from "path";
5
5
  var MAX_BUNDLE_SIZE_BYTES = 10 * 1024 * 1024;
6
6
  async function collectFiles(dir, rootDir) {
@@ -66,6 +66,7 @@ var BundleBuilder = class {
66
66
  `Build output directory "${absoluteOutputDir}" is empty after build.`
67
67
  );
68
68
  }
69
+ await this.validateIndexHtmlForCdn(files);
69
70
  const totalSize = files.reduce((sum, f) => sum + f.size, 0);
70
71
  if (totalSize > MAX_BUNDLE_SIZE_BYTES) {
71
72
  throw new Error(
@@ -75,6 +76,23 @@ var BundleBuilder = class {
75
76
  const duration = Date.now() - startTime;
76
77
  return { files, totalSize, duration };
77
78
  }
79
+ /**
80
+ * Ensures index.html uses relative asset URLs so bundles work under
81
+ * session-scoped CDN paths like /dev-bundles/{sessionId}/.
82
+ */
83
+ async validateIndexHtmlForCdn(files) {
84
+ const indexFile = files.find((file) => file.relativePath === "index.html");
85
+ if (!indexFile) {
86
+ return;
87
+ }
88
+ const html = await readFile(indexFile.absolutePath, "utf-8");
89
+ const hasRootAbsoluteAssetRefs = /(?:src|href)=["']\/assets\//i.test(html) || /(?:src|href)=["']\/[a-z0-9._-]+\//i.test(html);
90
+ if (hasRootAbsoluteAssetRefs) {
91
+ throw new Error(
92
+ "Build output uses root-absolute asset paths in index.html. CDN dev bundles are served from a subpath, so assets must be relative. If you use Vite, set `base: './'` in vite.config.ts and rebuild."
93
+ );
94
+ }
95
+ }
78
96
  /**
79
97
  * Spawns the build process and waits for it to finish.
80
98
  * Captures stderr for error reporting on non-zero exit.
@@ -125,7 +143,7 @@ ${output}` : "")
125
143
  };
126
144
 
127
145
  // src/bundle/uploader.ts
128
- import { readFile } from "fs/promises";
146
+ import { readFile as readFile2 } from "fs/promises";
129
147
  var UPLOAD_TIMEOUT_MS = 6e4;
130
148
  var CONTENT_TYPE_MAP = {
131
149
  ".html": "text/html",
@@ -224,7 +242,7 @@ var BundleUploader = class {
224
242
  };
225
243
  }
226
244
  try {
227
- const body = await readFile(file.absolutePath);
245
+ const body = await readFile2(file.absolutePath);
228
246
  const contentType = getContentType(file.relativePath);
229
247
  const response = await fetch(presignedUrl, {
230
248
  method: "PUT",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whatalo/cli-kit",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Shared CLI utilities for Whatalo plugin development tools",
@@ -76,14 +76,6 @@
76
76
  "README.md",
77
77
  "LICENSE"
78
78
  ],
79
- "scripts": {
80
- "build": "tsup",
81
- "dev": "tsup --watch",
82
- "test": "vitest run",
83
- "test:watch": "vitest",
84
- "type-check": "tsc --noEmit",
85
- "clean": "rm -rf dist"
86
- },
87
79
  "dependencies": {
88
80
  "@iarna/toml": "^2.2.5",
89
81
  "chalk": "^5.4.1",
@@ -96,5 +88,13 @@
96
88
  "tsup": "^8.5.0",
97
89
  "typescript": "^5.9.3",
98
90
  "vitest": "^3.2.4"
91
+ },
92
+ "scripts": {
93
+ "build": "tsup",
94
+ "dev": "tsup --watch",
95
+ "test": "vitest run",
96
+ "test:watch": "vitest",
97
+ "type-check": "tsc --noEmit",
98
+ "clean": "rm -rf dist"
99
99
  }
100
- }
100
+ }