@veryfront/ext-content-mdx 0.1.1190 → 0.1.1192

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 (66) hide show
  1. package/esm/deno.d.ts +6 -0
  2. package/esm/deno.js +13 -7
  3. package/esm/src/errors/error-registry/module.d.ts +4 -0
  4. package/esm/src/errors/error-registry/module.d.ts.map +1 -1
  5. package/esm/src/errors/error-registry/module.js +16 -0
  6. package/esm/src/errors/error-registry.d.ts +2 -0
  7. package/esm/src/errors/error-registry.d.ts.map +1 -1
  8. package/esm/src/errors/types.d.ts.map +1 -1
  9. package/esm/src/errors/types.js +5 -2
  10. package/esm/src/platform/compat/error-introspection.d.ts +12 -1
  11. package/esm/src/platform/compat/error-introspection.d.ts.map +1 -1
  12. package/esm/src/platform/compat/error-introspection.js +40 -5
  13. package/esm/src/platform/compat/path/basic-operations.d.ts.map +1 -1
  14. package/esm/src/platform/compat/path/basic-operations.js +6 -2
  15. package/esm/src/platform/compat/path/portable.d.ts.map +1 -1
  16. package/esm/src/platform/compat/path/portable.js +98 -54
  17. package/esm/src/platform/compat/path/resolution.d.ts.map +1 -1
  18. package/esm/src/platform/compat/path/resolution.js +14 -5
  19. package/esm/src/platform/compat/primordials/array.d.ts +8 -0
  20. package/esm/src/platform/compat/primordials/array.d.ts.map +1 -0
  21. package/esm/src/platform/compat/primordials/array.js +33 -0
  22. package/esm/src/transforms/import-rewriter/url-builder.d.ts +6 -0
  23. package/esm/src/transforms/import-rewriter/url-builder.d.ts.map +1 -1
  24. package/esm/src/transforms/import-rewriter/url-builder.js +96 -29
  25. package/esm/src/utils/base64url.d.ts.map +1 -1
  26. package/esm/src/utils/base64url.js +10 -4
  27. package/esm/src/utils/bundle-manifest.d.ts +19 -1
  28. package/esm/src/utils/bundle-manifest.d.ts.map +1 -1
  29. package/esm/src/utils/bundle-manifest.js +124 -27
  30. package/esm/src/utils/constants/limits.d.ts +1 -1
  31. package/esm/src/utils/constants/limits.d.ts.map +1 -1
  32. package/esm/src/utils/constants/limits.js +1 -1
  33. package/esm/src/utils/hash-utils.d.ts.map +1 -1
  34. package/esm/src/utils/hash-utils.js +32 -6
  35. package/esm/src/utils/id.d.ts +16 -0
  36. package/esm/src/utils/id.d.ts.map +1 -0
  37. package/esm/src/utils/id.js +69 -0
  38. package/esm/src/utils/import-lockfile.d.ts +52 -1
  39. package/esm/src/utils/import-lockfile.d.ts.map +1 -1
  40. package/esm/src/utils/import-lockfile.js +1042 -58
  41. package/esm/src/utils/index.d.ts +1 -1
  42. package/esm/src/utils/index.d.ts.map +1 -1
  43. package/esm/src/utils/index.js +1 -1
  44. package/esm/src/utils/logger/logger.d.ts +1 -0
  45. package/esm/src/utils/logger/logger.d.ts.map +1 -1
  46. package/esm/src/utils/logger/logger.js +359 -78
  47. package/esm/src/utils/logger/redact.d.ts +4 -2
  48. package/esm/src/utils/logger/redact.d.ts.map +1 -1
  49. package/esm/src/utils/logger/redact.js +300 -112
  50. package/esm/src/utils/logger/serialization.d.ts +3 -0
  51. package/esm/src/utils/logger/serialization.d.ts.map +1 -0
  52. package/esm/src/utils/logger/serialization.js +81 -0
  53. package/esm/src/utils/memoize.d.ts +1 -1
  54. package/esm/src/utils/memoize.d.ts.map +1 -1
  55. package/esm/src/utils/memoize.js +16 -5
  56. package/esm/src/utils/path-utils.d.ts.map +1 -1
  57. package/esm/src/utils/path-utils.js +4 -2
  58. package/esm/src/utils/sleep.d.ts +8 -0
  59. package/esm/src/utils/sleep.d.ts.map +1 -1
  60. package/esm/src/utils/sleep.js +11 -2
  61. package/esm/src/utils/timer.d.ts +10 -0
  62. package/esm/src/utils/timer.d.ts.map +1 -0
  63. package/esm/src/utils/timer.js +19 -0
  64. package/esm/src/utils/version-constant.d.ts +1 -1
  65. package/esm/src/utils/version-constant.js +1 -1
  66. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"base64url.d.ts","sourceRoot":"","sources":["../../../src/src/utils/base64url.ts"],"names":[],"mappings":"AAYA;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAelD;AAED,2CAA2C;AAC3C,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAa3D;AAED,6CAA6C;AAC7C,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,8CAA8C;AAC9C,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAE9D"}
1
+ {"version":3,"file":"base64url.d.ts","sourceRoot":"","sources":["../../../src/src/utils/base64url.ts"],"names":[],"mappings":"AAYA;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAelD;AAED,2CAA2C;AAC3C,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAoB3D;AAED,6CAA6C;AAC7C,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,8CAA8C;AAC9C,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAE9D"}
@@ -36,10 +36,16 @@ export function encodeBase64Bytes(bytes) {
36
36
  if (bufferCtor)
37
37
  return bufferCtor.from(bytes).toString("base64");
38
38
  if (typeof globalThis.btoa === "function") {
39
- let binary = "";
40
- for (const byte of bytes)
41
- binary += String.fromCharCode(byte);
42
- return globalThis.btoa(binary);
39
+ // Bound the peak temporary binary string to 24 KiB. The chunk size is
40
+ // divisible by three, so only the final base64 chunk can contain padding.
41
+ const chunkSize = 24 * 1024;
42
+ const encodedChunks = [];
43
+ for (let offset = 0; offset < bytes.length; offset += chunkSize) {
44
+ const end = Math.min(offset + chunkSize, bytes.length);
45
+ const binaryChunk = String.fromCharCode(...bytes.subarray(offset, end));
46
+ encodedChunks.push(globalThis.btoa(binaryChunk));
47
+ }
48
+ return encodedChunks.join("");
43
49
  }
44
50
  throw new Error("Base64 encoding is not supported in this runtime");
45
51
  }
@@ -41,11 +41,14 @@ export interface BundleManifestStore {
41
41
  isAvailable(): Promise<boolean>;
42
42
  getStats(): Promise<BundleManifestStats>;
43
43
  }
44
+ /** Minimum interval between full expired-metadata sweeps (amortized on writes). */
45
+ export declare const BUNDLE_MANIFEST_SWEEP_INTERVAL_MS = 30000;
44
46
  export declare class InMemoryBundleManifestStore implements BundleManifestStore {
45
47
  private metadata;
46
48
  private code;
47
49
  private sourceIndex;
48
- private getIfNotExpired;
50
+ private codeReferences;
51
+ private lastExpiredSweepAt;
49
52
  getBundleMetadata(key: string): Promise<BundleMetadata | undefined>;
50
53
  setBundleMetadata(key: string, metadata: BundleMetadata, ttlMs?: number): Promise<void>;
51
54
  getBundleCode(hash: string): Promise<BundleCode | undefined>;
@@ -55,6 +58,21 @@ export declare class InMemoryBundleManifestStore implements BundleManifestStore
55
58
  clear(): Promise<void>;
56
59
  isAvailable(): Promise<boolean>;
57
60
  getStats(): Promise<BundleManifestStats>;
61
+ private addCodeReference;
62
+ /**
63
+ * Drop expired metadata entries referencing one code hash so the reference
64
+ * check in getBundleCode stays trustworthy without a full-map sweep.
65
+ */
66
+ private pruneExpiredReferencesTo;
67
+ /**
68
+ * Full expired-metadata sweep, amortized: runs on writes at most once per
69
+ * BUNDLE_MANIFEST_SWEEP_INTERVAL_MS so unread expired entries cannot pin
70
+ * memory forever while per-render reads stay off the O(all-metadata) path.
71
+ */
72
+ private sweepExpiredMetadataIfDue;
73
+ private removeCodeReference;
74
+ private removeMetadata;
75
+ private removeSourceReference;
58
76
  }
59
77
  export declare function setBundleManifestStore(store: BundleManifestStore): void;
60
78
  /** Return bundle manifest store. */
@@ -1 +1 @@
1
- {"version":3,"file":"bundle-manifest.d.ts","sourceRoot":"","sources":["../../../src/src/utils/bundle-manifest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bundle-manifest.d.ts","sourceRoot":"","sources":["../../../src/src/utils/bundle-manifest.ts"],"names":[],"mappings":"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"}
@@ -1,55 +1,79 @@
1
1
  import { serverLogger } from "./logger/index.js";
2
2
  const logger = serverLogger.component("bundle-manifest");
3
+ /** Minimum interval between full expired-metadata sweeps (amortized on writes). */
4
+ export const BUNDLE_MANIFEST_SWEEP_INTERVAL_MS = 30_000;
3
5
  export class InMemoryBundleManifestStore {
4
6
  metadata = new Map();
5
7
  code = new Map();
6
8
  sourceIndex = new Map();
7
- getIfNotExpired(map, key) {
8
- const entry = map.get(key);
9
+ // codeHash → metadata keys holding a reference. Each key holds at most one
10
+ // reference per hash, so set size is the reference count and the members
11
+ // let reads prune only the metadata entries relevant to one hash.
12
+ codeReferences = new Map();
13
+ lastExpiredSweepAt = Date.now();
14
+ async getBundleMetadata(key) {
15
+ const entry = this.metadata.get(key);
9
16
  if (!entry)
10
17
  return undefined;
11
- if (entry.expiry != null && Date.now() > entry.expiry) {
12
- map.delete(key);
18
+ if (entry.expiry != null && Date.now() >= entry.expiry) {
19
+ this.removeMetadata(key);
13
20
  return undefined;
14
21
  }
15
- return entry.value;
16
- }
17
- async getBundleMetadata(key) {
18
- return this.getIfNotExpired(this.metadata, key);
22
+ return structuredClone(entry.value);
19
23
  }
20
24
  async setBundleMetadata(key, metadata, ttlMs) {
25
+ this.sweepExpiredMetadataIfDue();
21
26
  const expiry = ttlMs != null ? Date.now() + ttlMs : undefined;
22
- this.metadata.set(key, { value: metadata, expiry });
23
- const keys = this.sourceIndex.get(metadata.source) ?? new Set();
27
+ const snapshot = structuredClone(metadata);
28
+ const previous = this.metadata.get(key)?.value;
29
+ if (!previous) {
30
+ this.addCodeReference(snapshot.codeHash, key);
31
+ }
32
+ else if (previous.codeHash !== snapshot.codeHash) {
33
+ this.removeCodeReference(previous.codeHash, key);
34
+ this.addCodeReference(snapshot.codeHash, key);
35
+ }
36
+ if (previous && previous.source !== snapshot.source) {
37
+ this.removeSourceReference(key, previous.source);
38
+ }
39
+ this.metadata.set(key, { value: snapshot, expiry });
40
+ const keys = this.sourceIndex.get(snapshot.source) ?? new Set();
24
41
  keys.add(key);
25
- this.sourceIndex.set(metadata.source, keys);
42
+ this.sourceIndex.set(snapshot.source, keys);
26
43
  }
27
44
  async getBundleCode(hash) {
28
- return this.getIfNotExpired(this.code, hash);
45
+ // Only the metadata entries referencing this hash decide its liveness, so
46
+ // prune those lazily instead of sweeping the entire metadata map on every
47
+ // per-render read. Full sweeps are amortized onto writes.
48
+ this.pruneExpiredReferencesTo(hash);
49
+ const entry = this.code.get(hash);
50
+ if (!entry)
51
+ return undefined;
52
+ // Metadata references own code liveness. A shorter code TTL must not turn
53
+ // a still-valid manifest into a pointer to a missing content blob.
54
+ if (entry.expiry != null &&
55
+ Date.now() >= entry.expiry &&
56
+ !this.codeReferences.has(hash)) {
57
+ this.code.delete(hash);
58
+ return undefined;
59
+ }
60
+ return structuredClone(entry.value);
29
61
  }
30
62
  async setBundleCode(hash, code, ttlMs) {
63
+ this.sweepExpiredMetadataIfDue();
31
64
  const expiry = ttlMs != null ? Date.now() + ttlMs : undefined;
32
- this.code.set(hash, { value: code, expiry });
65
+ this.code.set(hash, { value: structuredClone(code), expiry });
33
66
  }
34
67
  async deleteBundle(key) {
35
- const metadata = await this.getBundleMetadata(key);
36
- this.metadata.delete(key);
37
- if (!metadata)
38
- return;
39
- this.code.delete(metadata.codeHash);
40
- const sourceKeys = this.sourceIndex.get(metadata.source);
41
- if (!sourceKeys)
42
- return;
43
- sourceKeys.delete(key);
44
- if (sourceKeys.size === 0)
45
- this.sourceIndex.delete(metadata.source);
68
+ this.removeMetadata(key);
46
69
  }
47
70
  async invalidateSource(source) {
48
71
  const keys = this.sourceIndex.get(source);
49
72
  if (!keys)
50
73
  return 0;
51
74
  const keysArray = [...keys];
52
- await Promise.all(keysArray.map((key) => this.deleteBundle(key)));
75
+ for (const key of keysArray)
76
+ this.removeMetadata(key);
53
77
  this.sourceIndex.delete(source);
54
78
  return keysArray.length;
55
79
  }
@@ -57,15 +81,23 @@ export class InMemoryBundleManifestStore {
57
81
  this.metadata.clear();
58
82
  this.code.clear();
59
83
  this.sourceIndex.clear();
84
+ this.codeReferences.clear();
60
85
  }
61
86
  async isAvailable() {
62
87
  return true;
63
88
  }
64
89
  async getStats() {
90
+ // Non-mutating expiry view: expired entries are excluded from the
91
+ // aggregate without paying a pruning sweep on this read path.
92
+ const now = Date.now();
93
+ let totalBundles = 0;
65
94
  let totalSize = 0;
66
95
  let oldestBundle;
67
96
  let newestBundle;
68
- for (const { value } of this.metadata.values()) {
97
+ for (const { value, expiry } of this.metadata.values()) {
98
+ if (expiry != null && now >= expiry)
99
+ continue;
100
+ totalBundles++;
69
101
  totalSize += value.size;
70
102
  oldestBundle = oldestBundle == null
71
103
  ? value.compiledAt
@@ -75,12 +107,77 @@ export class InMemoryBundleManifestStore {
75
107
  : Math.max(newestBundle, value.compiledAt);
76
108
  }
77
109
  return {
78
- totalBundles: this.metadata.size,
110
+ totalBundles,
79
111
  totalSize,
80
112
  oldestBundle,
81
113
  newestBundle,
82
114
  };
83
115
  }
116
+ addCodeReference(codeHash, key) {
117
+ const refs = this.codeReferences.get(codeHash) ?? new Set();
118
+ refs.add(key);
119
+ this.codeReferences.set(codeHash, refs);
120
+ }
121
+ /**
122
+ * Drop expired metadata entries referencing one code hash so the reference
123
+ * check in getBundleCode stays trustworthy without a full-map sweep.
124
+ */
125
+ pruneExpiredReferencesTo(hash, now = Date.now()) {
126
+ const refs = this.codeReferences.get(hash);
127
+ if (!refs)
128
+ return;
129
+ for (const key of [...refs]) {
130
+ const entry = this.metadata.get(key);
131
+ if (!entry) {
132
+ // Defensive: a reference without metadata is stale bookkeeping.
133
+ this.removeCodeReference(hash, key);
134
+ continue;
135
+ }
136
+ if (entry.expiry != null && now >= entry.expiry)
137
+ this.removeMetadata(key);
138
+ }
139
+ }
140
+ /**
141
+ * Full expired-metadata sweep, amortized: runs on writes at most once per
142
+ * BUNDLE_MANIFEST_SWEEP_INTERVAL_MS so unread expired entries cannot pin
143
+ * memory forever while per-render reads stay off the O(all-metadata) path.
144
+ */
145
+ sweepExpiredMetadataIfDue(now = Date.now()) {
146
+ if (now - this.lastExpiredSweepAt < BUNDLE_MANIFEST_SWEEP_INTERVAL_MS)
147
+ return;
148
+ this.lastExpiredSweepAt = now;
149
+ for (const [key, entry] of this.metadata) {
150
+ if (entry.expiry != null && now >= entry.expiry)
151
+ this.removeMetadata(key);
152
+ }
153
+ }
154
+ removeCodeReference(codeHash, key) {
155
+ const refs = this.codeReferences.get(codeHash);
156
+ if (refs) {
157
+ refs.delete(key);
158
+ if (refs.size > 0)
159
+ return;
160
+ this.codeReferences.delete(codeHash);
161
+ }
162
+ this.code.delete(codeHash);
163
+ }
164
+ removeMetadata(key) {
165
+ const metadata = this.metadata.get(key)?.value;
166
+ if (!metadata)
167
+ return undefined;
168
+ this.metadata.delete(key);
169
+ this.removeSourceReference(key, metadata.source);
170
+ this.removeCodeReference(metadata.codeHash, key);
171
+ return metadata;
172
+ }
173
+ removeSourceReference(key, source) {
174
+ const sourceKeys = this.sourceIndex.get(source);
175
+ if (!sourceKeys)
176
+ return;
177
+ sourceKeys.delete(key);
178
+ if (sourceKeys.size === 0)
179
+ this.sourceIndex.delete(source);
180
+ }
84
181
  }
85
182
  let manifestStore = new InMemoryBundleManifestStore();
86
183
  export function setBundleManifestStore(store) {
@@ -26,7 +26,7 @@ export declare const MAX_ROUTE_SEGMENTS = 64;
26
26
  export declare const MAX_PORT_NUMBER = 65535;
27
27
  export declare const MIN_PORT_NUMBER = 1;
28
28
  export declare const MAX_URL_LENGTH_FOR_VALIDATION = 2048;
29
- /******** Batch limits ********/
29
+ /** Maximum batch size. */
30
30
  export declare const MAX_BATCH_SIZE = 100;
31
31
  /** Largest delay supported consistently by JavaScript timer implementations. */
32
32
  export declare const MAX_TIMER_DELAY_MS = 2147483647;
@@ -1 +1 @@
1
- {"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../../../../src/src/utils/constants/limits.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAClC,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAC9C,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAChD,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAClD,eAAO,MAAM,6BAA6B,MAAM,CAAC;AACjD,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC,gCAAgC;AAChC,eAAO,MAAM,oBAAoB,OAAO,CAAC;AACzC,eAAO,MAAM,8BAA8B,QAAQ,CAAC;AACpD,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAEtC,eAAO,MAAM,sBAAsB,KAAK,CAAC;AACzC,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC,qCAAqC;AACrC,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAC5C,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAC3C,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAC7C,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAC/C,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAC7C,yEAAyE;AACzE,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAE/C,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAC1C,6EAA6E;AAC7E,eAAO,MAAM,kBAAkB,KAAK,CAAC;AACrC,eAAO,MAAM,eAAe,QAAQ,CAAC;AACrC,eAAO,MAAM,eAAe,IAAI,CAAC;AACjC,eAAO,MAAM,6BAA6B,OAAO,CAAC;AAElD,gCAAgC;AAChC,eAAO,MAAM,cAAc,MAAM,CAAC;AAElC,gFAAgF;AAChF,eAAO,MAAM,kBAAkB,aAAgB,CAAC"}
1
+ {"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../../../../src/src/utils/constants/limits.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAClC,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAC9C,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAChD,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAClD,eAAO,MAAM,6BAA6B,MAAM,CAAC;AACjD,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC,gCAAgC;AAChC,eAAO,MAAM,oBAAoB,OAAO,CAAC;AACzC,eAAO,MAAM,8BAA8B,QAAQ,CAAC;AACpD,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAEtC,eAAO,MAAM,sBAAsB,KAAK,CAAC;AACzC,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC,qCAAqC;AACrC,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAC5C,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAC3C,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAC7C,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAC/C,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAC7C,yEAAyE;AACzE,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAE/C,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAC1C,6EAA6E;AAC7E,eAAO,MAAM,kBAAkB,KAAK,CAAC;AACrC,eAAO,MAAM,eAAe,QAAQ,CAAC;AACrC,eAAO,MAAM,eAAe,IAAI,CAAC;AACjC,eAAO,MAAM,6BAA6B,OAAO,CAAC;AAElD,0BAA0B;AAC1B,eAAO,MAAM,cAAc,MAAM,CAAC;AAElC,gFAAgF;AAChF,eAAO,MAAM,kBAAkB,aAAgB,CAAC"}
@@ -26,7 +26,7 @@ export const MAX_ROUTE_SEGMENTS = 64;
26
26
  export const MAX_PORT_NUMBER = 65535;
27
27
  export const MIN_PORT_NUMBER = 1;
28
28
  export const MAX_URL_LENGTH_FOR_VALIDATION = 2048;
29
- /******** Batch limits ********/
29
+ /** Maximum batch size. */
30
30
  export const MAX_BATCH_SIZE = 100;
31
31
  /** Largest delay supported consistently by JavaScript timer implementations. */
32
32
  export const MAX_TIMER_DELAY_MS = 2_147_483_647;
@@ -1 +1 @@
1
- {"version":3,"file":"hash-utils.d.ts","sourceRoot":"","sources":["../../../src/src/utils/hash-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAC;AAW/C,kEAAkE;AAClE,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGlE;AAED,6DAA6D;AAC7D,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAEnF;AACD,uDAAuD;AACvD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,yBAAyB;AACzB,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAEjE;AAED,0BAA0B;AAC1B,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAS9C;AAED,+DAA+D;AAC/D,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,yBAAyB;AACzB,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGhE;AAED,mDAAmD;AACnD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAS/C"}
1
+ {"version":3,"file":"hash-utils.d.ts","sourceRoot":"","sources":["../../../src/src/utils/hash-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAC;AA0C/C,kEAAkE;AAClE,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAalE;AAED,6DAA6D;AAC7D,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAQnF;AACD,uDAAuD;AACvD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,yBAAyB;AACzB,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAEjE;AAED,0BAA0B;AAC1B,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAS9C;AAED,+DAA+D;AAC/D,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,yBAAyB;AACzB,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGhE;AAED,mDAAmD;AACnD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAS/C"}
@@ -3,17 +3,43 @@ import { FNV1A_PRIME_32 } from "./constants/crypto.js";
3
3
  import { HASH_SEED_FNV1A } from "./constants/hash.js";
4
4
  /** Number of hex characters kept by shortHash (8 hex chars = 32 bits) */
5
5
  const SHORT_HASH_LENGTH = 8;
6
+ // Hashes participate in cache and request identities after project modules may
7
+ // have executed in the shared realm. Capture the small set of primordials used
8
+ // by that boundary before project code can replace their implementations.
9
+ const IntrinsicTextEncoder = TextEncoder;
10
+ const IntrinsicUint8Array = Uint8Array;
11
+ const NumberPrototypeToString = Number.prototype.toString;
12
+ const ObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
13
+ const ObjectGetPrototypeOf = Object.getPrototypeOf;
14
+ const ReflectApply = Reflect.apply;
15
+ const StringPrototypePadStart = String.prototype.padStart;
16
+ const SubtleCryptoDigest = dntShim.crypto.subtle.digest;
17
+ const TextEncoderPrototypeEncode = TextEncoder.prototype.encode;
18
+ const cryptoSubtle = dntShim.crypto.subtle;
19
+ const hashTextEncoder = new IntrinsicTextEncoder();
20
+ const TypedArrayPrototype = ObjectGetPrototypeOf(IntrinsicUint8Array.prototype);
21
+ const TypedArrayLengthGetter = ObjectGetOwnPropertyDescriptor(TypedArrayPrototype, "length").get;
22
+ function typedArrayLength(value) {
23
+ return ReflectApply(TypedArrayLengthGetter, value, []);
24
+ }
6
25
  function toHex(buffer) {
7
- return Array.from(new Uint8Array(buffer), (b) => b.toString(16).padStart(2, "0")).join("");
26
+ const bytes = new IntrinsicUint8Array(buffer);
27
+ let result = "";
28
+ const length = typedArrayLength(bytes);
29
+ for (let index = 0; index < length; index++) {
30
+ const hex = ReflectApply(NumberPrototypeToString, bytes[index], [16]);
31
+ result += ReflectApply(StringPrototypePadStart, hex, [2, "0"]);
32
+ }
33
+ return result;
8
34
  }
9
35
  /** Compute the lowercase hex SHA-256 digest of a UTF-8 string. */
10
36
  export async function computeHash(content) {
11
- const data = new TextEncoder().encode(content);
12
- return toHex(await dntShim.crypto.subtle.digest("SHA-256", data));
37
+ const data = ReflectApply(TextEncoderPrototypeEncode, hashTextEncoder, [content]);
38
+ return toHex(await ReflectApply(SubtleCryptoDigest, cryptoSubtle, ["SHA-256", data]));
13
39
  }
14
40
  /** Compute the lowercase hex SHA-256 digest of raw bytes. */
15
41
  export async function computeHashBytes(bytes) {
16
- return toHex(await dntShim.crypto.subtle.digest("SHA-256", bytes));
42
+ return toHex(await ReflectApply(SubtleCryptoDigest, cryptoSubtle, ["SHA-256", bytes]));
17
43
  }
18
44
  /** Compute code hash. */
19
45
  export function computeCodeHash(code) {
@@ -40,8 +66,8 @@ export async function shortHash(content) {
40
66
  /** FNV-1a hash for strings - returns hex string */
41
67
  export function fnv1aHash(input) {
42
68
  let hash = HASH_SEED_FNV1A >>> 0;
43
- for (const char of input) {
44
- hash ^= char.charCodeAt(0);
69
+ for (let index = 0; index < input.length; index++) {
70
+ hash ^= input.charCodeAt(index);
45
71
  hash = Math.imul(hash, FNV1A_PRIME_32);
46
72
  }
47
73
  return (hash >>> 0).toString(16);
@@ -0,0 +1,16 @@
1
+ interface CryptoUuidSource {
2
+ randomUUID?: () => string;
3
+ getRandomValues?: (bytes: Uint8Array) => Uint8Array;
4
+ }
5
+ /** Generate a secure RFC 4122 version 4 UUID across browser Crypto implementations. */
6
+ export declare function generateUuid(cryptoImpl?: CryptoUuidSource | null | undefined): string;
7
+ /** Generate a unique ID with optional prefix (e.g., "msg-a1B2c3D4e5F6g7H8") */
8
+ export declare function generateId(prefix?: string): string;
9
+ /** Create an ID generator with fixed prefix and optional configuration */
10
+ export declare function createIdGenerator(options: {
11
+ prefix?: string;
12
+ separator?: string;
13
+ size?: number;
14
+ }): () => string;
15
+ export {};
16
+ //# sourceMappingURL=id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"id.d.ts","sourceRoot":"","sources":["../../../src/src/utils/id.ts"],"names":[],"mappings":"AAyCA,UAAU,gBAAgB;IACxB,UAAU,CAAC,EAAE,MAAM,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,UAAU,CAAC;CACrD;AAED,uFAAuF;AACvF,wBAAgB,YAAY,CAC1B,UAAU,GAAE,gBAAgB,GAAG,IAAI,GAAG,SAEzB,GACZ,MAAM,CAmBR;AAED,+EAA+E;AAC/E,wBAAgB,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAGlD;AAED,0EAA0E;AAC1E,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,MAAM,MAAM,CAQf"}
@@ -0,0 +1,69 @@
1
+ /** ID generation utilities (16-char alphanumeric with optional prefix) */
2
+ import * as dntShim from "../../_dnt.shims.js";
3
+ const ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
4
+ const MAX_UNBIASED_BYTE = Math.floor(256 / ALPHABET.length) * ALPHABET.length;
5
+ const MAX_ID_SIZE = 1_024;
6
+ function requireIdSize(size) {
7
+ if (!Number.isSafeInteger(size) || size <= 0 || size > MAX_ID_SIZE) {
8
+ throw new RangeError(`ID size must be an integer between 1 and ${MAX_ID_SIZE}`);
9
+ }
10
+ return size;
11
+ }
12
+ function randomString(length) {
13
+ requireIdSize(length);
14
+ let result = "";
15
+ while (result.length < length) {
16
+ const remaining = length - result.length;
17
+ const batchSize = Math.min(65_536, Math.max(32, Math.ceil((remaining * 256) / MAX_UNBIASED_BYTE)));
18
+ const bytes = new Uint8Array(batchSize);
19
+ dntShim.crypto.getRandomValues(bytes);
20
+ // Iterate the allocated batch directly. A project can replace the ambient
21
+ // typed-array iterator after framework modules load; ID generation must not
22
+ // execute or depend on that mutable hook.
23
+ for (let index = 0; index < batchSize; index++) {
24
+ const byte = bytes[index] ?? 0;
25
+ if (byte >= MAX_UNBIASED_BYTE)
26
+ continue;
27
+ result += ALPHABET[byte % ALPHABET.length];
28
+ if (result.length === length)
29
+ break;
30
+ }
31
+ }
32
+ return result;
33
+ }
34
+ /** Generate a secure RFC 4122 version 4 UUID across browser Crypto implementations. */
35
+ export function generateUuid(cryptoImpl = typeof dntShim.crypto !== "undefined"
36
+ ? dntShim.crypto
37
+ : undefined) {
38
+ if (typeof cryptoImpl?.randomUUID === "function") {
39
+ return cryptoImpl.randomUUID();
40
+ }
41
+ if (typeof cryptoImpl?.getRandomValues !== "function") {
42
+ throw new Error("Web Crypto with getRandomValues is required to generate a secure UUID.");
43
+ }
44
+ const bytes = cryptoImpl.getRandomValues(new Uint8Array(16));
45
+ bytes[6] = ((bytes[6] ?? 0) & 0x0f) | 0x40;
46
+ bytes[8] = ((bytes[8] ?? 0) & 0x3f) | 0x80;
47
+ const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
48
+ return [
49
+ hex.slice(0, 8),
50
+ hex.slice(8, 12),
51
+ hex.slice(12, 16),
52
+ hex.slice(16, 20),
53
+ hex.slice(20),
54
+ ].join("-");
55
+ }
56
+ /** Generate a unique ID with optional prefix (e.g., "msg-a1B2c3D4e5F6g7H8") */
57
+ export function generateId(prefix) {
58
+ const id = randomString(16);
59
+ return prefix ? `${prefix}-${id}` : id;
60
+ }
61
+ /** Create an ID generator with fixed prefix and optional configuration */
62
+ export function createIdGenerator(options) {
63
+ const { prefix, separator = "-", size = 16 } = options;
64
+ requireIdSize(size);
65
+ return function generate() {
66
+ const id = randomString(size);
67
+ return prefix ? `${prefix}${separator}${id}` : id;
68
+ };
69
+ }
@@ -12,7 +12,15 @@ export declare function createEmptyLockfile(): LockfileData;
12
12
  /** Compute integrity. */
13
13
  export declare function computeIntegrity(content: string): Promise<string>;
14
14
  export declare function verifyIntegrity(content: string, integrity: string): Promise<boolean>;
15
- /** Public API contract for lockfile manager. */
15
+ /**
16
+ * Public API contract for lockfile manager.
17
+ *
18
+ * Reads and updates fail closed with `lockfile-format-mismatch` for an
19
+ * unsupported format and `lockfile-read-error` for unreadable or malformed
20
+ * data, so an older Veryfront build cannot overwrite unrecognized lockfile
21
+ * data. `clear()` is the explicit destructive recovery operation and does not
22
+ * parse the file before removing it.
23
+ */
16
24
  export interface LockfileManager {
17
25
  read(): Promise<LockfileData | null>;
18
26
  write(data: LockfileData): Promise<void>;
@@ -23,13 +31,56 @@ export interface LockfileManager {
23
31
  flush(): Promise<void>;
24
32
  }
25
33
  export type FSAdapter = {
34
+ /**
35
+ * Authoritative queue identity for adapters that access the same backing
36
+ * filesystem. Separate adapter objects must share this key to coordinate all
37
+ * lockfile access, regardless of their optional canonicalization support.
38
+ */
39
+ readonly coordinationKey?: string;
26
40
  readFile(path: string): Promise<string>;
27
41
  writeFile(path: string, content: string): Promise<void>;
42
+ /**
43
+ * Atomically replace `to` with the file at `from` (same-directory rename).
44
+ * When present, lockfile writes stage a temp file and rename it into place,
45
+ * so a crash mid-write can never leave a truncated lockfile behind.
46
+ */
47
+ rename?(from: string, to: string): Promise<void>;
28
48
  exists(path: string): Promise<boolean>;
29
49
  remove?(path: string): Promise<void>;
50
+ /**
51
+ * Resolve an existing project path to its stable backing identity.
52
+ * Coordination through realPath is per-adapter-instance (or per shared
53
+ * coordinationKey domain): two separate adapter instances without a shared
54
+ * coordinationKey never serialize with each other through realPath alone,
55
+ * even when both implementations agree on the canonical path.
56
+ */
57
+ realPath?(path: string): Promise<string>;
30
58
  };
31
59
  /** Create lockfile manager. */
32
60
  export declare function createLockfileManager(projectDir: string, fsAdapter?: FSAdapter): LockfileManager;
61
+ /**
62
+ * Read a lockfile entry on a build or dev-server hot path.
63
+ *
64
+ * A lockfile written by a newer Veryfront build (`lockfile-format-mismatch`)
65
+ * keeps failing loudly: proceeding around data the running build cannot
66
+ * understand is exactly the overwrite hazard this module guards against. An
67
+ * unreadable or malformed lockfile (`lockfile-read-error`) instead degrades to
68
+ * a cache miss so builds keep working from fresh fetches; a warning naming
69
+ * the lockfile and the `veryfront lock --clear` remedy is logged once per
70
+ * manager instead of once per import.
71
+ */
72
+ export declare function getLockfileEntryForBuild(lockfile: LockfileManager, url: string): Promise<LockfileEntry | null>;
73
+ /**
74
+ * Persist a lockfile entry from a build or dev-server hot path.
75
+ *
76
+ * Mirrors {@link getLockfileEntryForBuild}: when the on-disk lockfile is
77
+ * unreadable or malformed (`lockfile-read-error`), the file is left untouched
78
+ * for `veryfront lock --clear` and the entry is simply not recorded, so a
79
+ * successful refetch still serves the build. Returns whether the entry was
80
+ * staged; callers should only `flush()` after a `true` result. A newer-format
81
+ * lockfile (`lockfile-format-mismatch`) keeps failing loudly.
82
+ */
83
+ export declare function setLockfileEntryForBuild(lockfile: LockfileManager, url: string, entry: LockfileEntry): Promise<boolean>;
33
84
  export interface FetchWithLockOptions {
34
85
  lockfile: LockfileManager;
35
86
  url: string;
@@ -1 +1 @@
1
- {"version":3,"file":"import-lockfile.d.ts","sourceRoot":"","sources":["../../../src/src/utils/import-lockfile.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;CACxC;AAKD,wBAAgB,mBAAmB,IAAI,YAAY,CAElD;AAED,yBAAyB;AACzB,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGvE;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAG1F;AAED,gDAAgD;AAChD,MAAM,WAAW,eAAe;IAC9B,IAAI,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IACrC,KAAK,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IAChD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACnC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACxC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC,CAAC;AAqBF,+BAA+B;AAC/B,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,SAAS,GAAG,eAAe,CAkFhG;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,eAAe,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAID,wBAAsB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA2D/F;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAC;CAC5B;AAMD,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,EAAE,CAmB9D;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUlF"}
1
+ {"version":3,"file":"import-lockfile.d.ts","sourceRoot":"","sources":["../../../src/src/utils/import-lockfile.ts"],"names":[],"mappings":"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"}