@camstack/system 1.1.43 → 1.1.44

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.
@@ -43,8 +43,14 @@ export declare class AddonWidgetsAggregatorAddon extends BaseAddon {
43
43
  * just gets a fresh URL on each call instead of cache-friendly mtime.
44
44
  */
45
45
  private makeBundleUrl;
46
- /** sha1(content) 12-hex of a bundle entry file, memoised; `Date.now()` when absent. */
47
- private bundleVersionTag;
46
+ /**
47
+ * sha1 (12-hex) over EVERY file in the bundle's dist dir — content, not
48
+ * mtime (reproducible builds fix mtime, so mtime never busts). Memoised by
49
+ * the dir's (name:size:mtime) fingerprint; a redeploy that changes any
50
+ * file's content changes its size and re-hashes. `Date.now()` when the
51
+ * bundle has no local file (remote addon).
52
+ */
53
+ private bundleDirVersionTag;
48
54
  private resolveBundlePath;
49
55
  private resolvePaths;
50
56
  }
@@ -198,19 +198,34 @@ var AddonWidgetsAggregatorAddon = class extends require_dist.BaseAddon {
198
198
  */
199
199
  makeBundleUrl(addonId, bundle) {
200
200
  const bundlePath = this.resolveBundlePath(addonId, bundle);
201
- return `/api/addon-widgets/${addonId}/${bundle}?v=${this.bundleVersionTag(bundlePath)}`;
201
+ return `/api/addon-widgets/${addonId}/v${this.bundleDirVersionTag(bundlePath)}/${bundle}`;
202
202
  }
203
- /** sha1(content) 12-hex of a bundle entry file, memoised; `Date.now()` when absent. */
204
- bundleVersionTag(bundlePath) {
205
- if (bundlePath === null) return String(Math.floor(Date.now()));
203
+ /**
204
+ * sha1 (12-hex) over EVERY file in the bundle's dist dir — content, not
205
+ * mtime (reproducible builds fix mtime, so mtime never busts). Memoised by
206
+ * the dir's (name:size:mtime) fingerprint; a redeploy that changes any
207
+ * file's content changes its size and re-hashes. `Date.now()` when the
208
+ * bundle has no local file (remote addon).
209
+ */
210
+ bundleDirVersionTag(entryPath) {
211
+ if (entryPath === null) return String(Math.floor(Date.now()));
206
212
  try {
207
- const stat = node_fs.statSync(bundlePath);
208
- const cacheKey = `${bundlePath}:${stat.size}:${stat.mtimeMs}`;
213
+ const dir = node_path.dirname(entryPath);
214
+ const files = node_fs.readdirSync(dir).filter((f) => node_fs.statSync(node_path.join(dir, f)).isFile()).sort();
215
+ const cacheKey = `${dir}#${files.map((f) => {
216
+ const s = node_fs.statSync(node_path.join(dir, f));
217
+ return `${f}:${s.size}:${s.mtimeMs}`;
218
+ }).join("|")}`;
209
219
  const cached = this.bundleHashCache.get(cacheKey);
210
220
  if (cached !== void 0) return cached;
211
- const hash = (0, node_crypto.createHash)("sha1").update(node_fs.readFileSync(bundlePath)).digest("hex").slice(0, 12);
212
- this.bundleHashCache.set(cacheKey, hash);
213
- return hash;
221
+ const hash = (0, node_crypto.createHash)("sha1");
222
+ for (const f of files) {
223
+ hash.update(f);
224
+ hash.update(node_fs.readFileSync(node_path.join(dir, f)));
225
+ }
226
+ const digest = hash.digest("hex").slice(0, 12);
227
+ this.bundleHashCache.set(cacheKey, digest);
228
+ return digest;
214
229
  } catch {
215
230
  return String(Math.floor(Date.now()));
216
231
  }
@@ -191,19 +191,34 @@ var AddonWidgetsAggregatorAddon = class extends BaseAddon {
191
191
  */
192
192
  makeBundleUrl(addonId, bundle) {
193
193
  const bundlePath = this.resolveBundlePath(addonId, bundle);
194
- return `/api/addon-widgets/${addonId}/${bundle}?v=${this.bundleVersionTag(bundlePath)}`;
194
+ return `/api/addon-widgets/${addonId}/v${this.bundleDirVersionTag(bundlePath)}/${bundle}`;
195
195
  }
196
- /** sha1(content) 12-hex of a bundle entry file, memoised; `Date.now()` when absent. */
197
- bundleVersionTag(bundlePath) {
198
- if (bundlePath === null) return String(Math.floor(Date.now()));
196
+ /**
197
+ * sha1 (12-hex) over EVERY file in the bundle's dist dir — content, not
198
+ * mtime (reproducible builds fix mtime, so mtime never busts). Memoised by
199
+ * the dir's (name:size:mtime) fingerprint; a redeploy that changes any
200
+ * file's content changes its size and re-hashes. `Date.now()` when the
201
+ * bundle has no local file (remote addon).
202
+ */
203
+ bundleDirVersionTag(entryPath) {
204
+ if (entryPath === null) return String(Math.floor(Date.now()));
199
205
  try {
200
- const stat = fs.statSync(bundlePath);
201
- const cacheKey = `${bundlePath}:${stat.size}:${stat.mtimeMs}`;
206
+ const dir = path$1.dirname(entryPath);
207
+ const files = fs.readdirSync(dir).filter((f) => fs.statSync(path$1.join(dir, f)).isFile()).sort();
208
+ const cacheKey = `${dir}#${files.map((f) => {
209
+ const s = fs.statSync(path$1.join(dir, f));
210
+ return `${f}:${s.size}:${s.mtimeMs}`;
211
+ }).join("|")}`;
202
212
  const cached = this.bundleHashCache.get(cacheKey);
203
213
  if (cached !== void 0) return cached;
204
- const hash = createHash("sha1").update(fs.readFileSync(bundlePath)).digest("hex").slice(0, 12);
205
- this.bundleHashCache.set(cacheKey, hash);
206
- return hash;
214
+ const hash = createHash("sha1");
215
+ for (const f of files) {
216
+ hash.update(f);
217
+ hash.update(fs.readFileSync(path$1.join(dir, f)));
218
+ }
219
+ const digest = hash.digest("hex").slice(0, 12);
220
+ this.bundleHashCache.set(cacheKey, digest);
221
+ return digest;
207
222
  } catch {
208
223
  return String(Math.floor(Date.now()));
209
224
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/system",
3
- "version": "1.1.43",
3
+ "version": "1.1.44",
4
4
  "description": "Core addon for CamStack — builtins, pipeline, process management, auth, logging, events",
5
5
  "keywords": [
6
6
  "camstack",