veryfront 0.0.95 → 0.0.97

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/esm/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.0.95",
3
+ "version": "0.0.97",
4
4
  "nodeModulesDir": "auto",
5
5
  "exclude": [
6
6
  "npm/",
@@ -14,7 +14,7 @@ export async function createPackageJson(projectDir, projectName) {
14
14
  dependencies: {
15
15
  react: "^19.0.0",
16
16
  "react-dom": "^19.0.0",
17
- veryfront: "^0.0.88",
17
+ veryfront: "^0.0.97",
18
18
  zod: "^3.24.0",
19
19
  },
20
20
  };
@@ -1 +1 @@
1
- {"version":3,"file":"react-paths.d.ts","sourceRoot":"","sources":["../../../../src/src/platform/compat/react-paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAwEH,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAa3D;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAO3D;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}
1
+ {"version":3,"file":"react-paths.d.ts","sourceRoot":"","sources":["../../../../src/src/platform/compat/react-paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA+CH,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAa3D;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAO3D;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}
@@ -8,8 +8,8 @@
8
8
  *
9
9
  * @module
10
10
  */
11
- import { fileURLToPath, pathToFileURL } from "node:url";
12
- import { dirname } from "node:path";
11
+ import { pathToFileURL } from "node:url";
12
+ import { createRequire } from "node:module";
13
13
  import { isBun, isDeno, isNode } from "./runtime.js";
14
14
  import { cwd } from "./process.js";
15
15
  let localReactPathsCache = null;
@@ -24,21 +24,6 @@ const REACT_SPECIFIERS = [
24
24
  function hasBunResolveSync() {
25
25
  return typeof Bun !== "undefined" && typeof Bun?.resolveSync === "function";
26
26
  }
27
- const IMPORT_META_RESOLVE_ERROR = "ImportMetaResolveUnavailable";
28
- function resolveWithImportMeta(specifier, parentUrl) {
29
- const metaResolve = globalThis[Symbol.for("import-meta-ponyfill-esmodule")](import.meta).resolve;
30
- if (typeof metaResolve !== "function") {
31
- const error = new Error("import.meta.resolve is required for Node ESM resolution (Node >= 22).");
32
- error.name = IMPORT_META_RESOLVE_ERROR;
33
- throw error;
34
- }
35
- try {
36
- return metaResolve(specifier, parentUrl);
37
- }
38
- catch {
39
- return null;
40
- }
41
- }
42
27
  function resolveReactSpecifier(specifier) {
43
28
  try {
44
29
  if (isBun && hasBunResolveSync() && Bun?.resolveSync) {
@@ -46,18 +31,16 @@ function resolveReactSpecifier(specifier) {
46
31
  return `file://${resolved}`;
47
32
  }
48
33
  if (isNode) {
49
- // Use import.meta.url (this module's location) as the parent URL.
50
- // This ensures React is resolved from veryfront's node_modules,
51
- // not from the cwd which may not have React installed.
52
- const thisModuleDir = dirname(fileURLToPath(globalThis[Symbol.for("import-meta-ponyfill-esmodule")](import.meta).url));
53
- const parentUrl = pathToFileURL(`${thisModuleDir}/`).href;
54
- return resolveWithImportMeta(specifier, parentUrl) ?? undefined;
34
+ // Use createRequire to resolve React from veryfront's node_modules.
35
+ // import.meta.resolve's parentUrl argument doesn't work correctly in Node.js,
36
+ // so we use createRequire which properly resolves from the specified path.
37
+ const require = createRequire(globalThis[Symbol.for("import-meta-ponyfill-esmodule")](import.meta).url);
38
+ const resolved = require.resolve(specifier);
39
+ return pathToFileURL(resolved).href;
55
40
  }
56
41
  }
57
- catch (error) {
58
- if (error instanceof Error && error.name === IMPORT_META_RESOLVE_ERROR) {
59
- throw error;
60
- }
42
+ catch {
43
+ // Resolution failed, return undefined
61
44
  }
62
45
  return undefined;
63
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"http-cache.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/http-cache.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAezE,KAAK,YAAY,GAAG;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,eAAe,CAAC;IAC3B,uEAAuE;IACvE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAqVF;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,MAAM,CAAC,CAOjB;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAOvF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CA8D9F;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EAClD,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,EAAE,CAAC,CAiInB"}
1
+ {"version":3,"file":"http-cache.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/http-cache.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAezE,KAAK,YAAY,GAAG;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,eAAe,CAAC;IAC3B,uEAAuE;IACvE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAgWF;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,MAAM,CAAC,CAOjB;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAOvF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CA8D9F;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EAClD,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,EAAE,CAAC,CAiInB"}
@@ -158,6 +158,7 @@ async function cacheHttpModule(url, options) {
158
158
  try {
159
159
  const code = await fs.readTextFile(cachePath);
160
160
  await Promise.all([
161
+ distributed.set(`url:${hash}`, code, HTTP_MODULE_DISTRIBUTED_TTL_SEC),
161
162
  distributed.set(`code:${hash}`, code, HTTP_MODULE_DISTRIBUTED_TTL_SEC),
162
163
  distributed.set(`hash:${hash}`, normalizedUrl, HTTP_MODULE_DISTRIBUTED_TTL_SEC),
163
164
  ]);
@@ -178,11 +179,15 @@ async function cacheHttpModule(url, options) {
178
179
  return cachePath;
179
180
  }
180
181
  const distributed = await getDistributedCache();
182
+ const hash = simpleHash(normalizedUrl);
181
183
  if (distributed) {
182
184
  try {
183
- const cachedCode = await distributed.get(normalizedUrl);
185
+ // Use hash-based key instead of raw URL to comply with API cache key constraints.
186
+ // API cache keys only allow: alphanumeric, underscore, colon, dot, asterisk, hyphen, slash.
187
+ // URLs contain invalid characters like @, ?, =, &, etc.
188
+ const cachedCode = await distributed.get(`url:${hash}`);
184
189
  if (cachedCode) {
185
- logger.debug("[HTTP-CACHE] Distributed cache hit", { url: normalizedUrl });
190
+ logger.debug("[HTTP-CACHE] Distributed cache hit", { url: normalizedUrl, hash });
186
191
  await fs.mkdir(cacheDir, { recursive: true });
187
192
  await fs.writeTextFile(cachePath, cachedCode);
188
193
  cachedPaths.set(cacheKey, cachePath);
@@ -223,15 +228,21 @@ async function cacheHttpModule(url, options) {
223
228
  await fs.mkdir(cacheDir, { recursive: true });
224
229
  await fs.writeTextFile(cachePath, code);
225
230
  if (distributed) {
226
- // Store code by URL, by hash (for direct recovery), and URL mapping (for debugging).
227
- // Storing code by hash enables recovery without needing URL lookup.
231
+ // Store code by hash-based keys to comply with API cache key constraints.
232
+ // API cache keys only allow: alphanumeric, underscore, colon, dot, asterisk, hyphen, slash.
233
+ // URLs contain invalid characters (@, ?, =, &, etc.) so we use hashes instead.
234
+ //
235
+ // Keys stored:
236
+ // - url:{hash} - primary lookup key (replaces raw URL)
237
+ // - code:{hash} - direct code recovery by hash
238
+ // - hash:{hash} - URL mapping for debugging
239
+ //
228
240
  // IMPORTANT: await the writes so other pods can recover this bundle immediately.
229
241
  // Without await, a transform referencing this bundle could reach Redis before
230
242
  // the bundle code does, causing ensureHttpBundlesExist on another pod to miss.
231
- const hash = simpleHash(normalizedUrl);
232
243
  try {
233
244
  await Promise.all([
234
- distributed.set(normalizedUrl, code, HTTP_MODULE_DISTRIBUTED_TTL_SEC),
245
+ distributed.set(`url:${hash}`, code, HTTP_MODULE_DISTRIBUTED_TTL_SEC),
235
246
  distributed.set(`code:${hash}`, code, HTTP_MODULE_DISTRIBUTED_TTL_SEC),
236
247
  distributed.set(`hash:${hash}`, normalizedUrl, HTTP_MODULE_DISTRIBUTED_TTL_SEC),
237
248
  ]);
@@ -42,8 +42,9 @@ export declare const REACT_VERSION = "19.1.1";
42
42
  * v10: Fix import regex to match minified code (from"..." without whitespace)
43
43
  * v11: Add HTTP bundle hash→URL mapping for cross-pod recovery
44
44
  * v12: Store HTTP bundle code by hash for direct recovery (code:{hash})
45
+ * v13: Fix npm: specifiers for Node.js (convert to esm.sh or local React)
45
46
  */
46
- export declare const TRANSFORM_CACHE_VERSION = 12;
47
+ export declare const TRANSFORM_CACHE_VERSION = 13;
47
48
  /** csstype version - must match deno.json for type consistency */
48
49
  export declare const CSSTYPE_VERSION = "3.2.3";
49
50
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"package-registry.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/package-registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,wEAAwE;AACxE,eAAO,MAAM,qBAAqB,WAAW,CAAC;AAC9C,eAAO,MAAM,gBAAgB,UAAU,CAAC;AAExC;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAOzE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,iEAAiE;AACjE,eAAO,MAAM,aAAa,WAAwB,CAAC;AAEnD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAE1C,kEAAkE;AAClE,eAAO,MAAM,eAAe,UAAU,CAAC;AAEvC;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,SAAK,EAAE,QAAQ,UAAQ,GAAG,MAAM,CAK5F;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAI9F;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAUrE;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAO1E;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAU3E"}
1
+ {"version":3,"file":"package-registry.d.ts","sourceRoot":"","sources":["../../../../src/src/transforms/esm/package-registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,wEAAwE;AACxE,eAAO,MAAM,qBAAqB,WAAW,CAAC;AAC9C,eAAO,MAAM,gBAAgB,UAAU,CAAC;AAExC;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAOzE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,iEAAiE;AACjE,eAAO,MAAM,aAAa,WAAwB,CAAC;AAEnD;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAE1C,kEAAkE;AAClE,eAAO,MAAM,eAAe,UAAU,CAAC;AAEvC;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,SAAK,EAAE,QAAQ,UAAQ,GAAG,MAAM,CAK5F;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAI9F;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAUrE;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAO1E;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAU3E"}
@@ -53,8 +53,9 @@ export const REACT_VERSION = DEFAULT_REACT_VERSION;
53
53
  * v10: Fix import regex to match minified code (from"..." without whitespace)
54
54
  * v11: Add HTTP bundle hash→URL mapping for cross-pod recovery
55
55
  * v12: Store HTTP bundle code by hash for direct recovery (code:{hash})
56
+ * v13: Fix npm: specifiers for Node.js (convert to esm.sh or local React)
56
57
  */
57
- export const TRANSFORM_CACHE_VERSION = 12;
58
+ export const TRANSFORM_CACHE_VERSION = 13;
58
59
  /** csstype version - must match deno.json for type consistency */
59
60
  export const CSSTYPE_VERSION = "3.2.3";
60
61
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "veryfront",
3
- "version": "0.0.95",
3
+ "version": "0.0.97",
4
4
  "description": "The simplest way to build AI-powered apps",
5
5
  "keywords": [
6
6
  "react",
package/src/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.0.95",
3
+ "version": "0.0.97",
4
4
  "nodeModulesDir": "auto",
5
5
  "exclude": [
6
6
  "npm/",
@@ -18,7 +18,7 @@ export async function createPackageJson(
18
18
  dependencies: {
19
19
  react: "^19.0.0",
20
20
  "react-dom": "^19.0.0",
21
- veryfront: "^0.0.88",
21
+ veryfront: "^0.0.97",
22
22
  zod: "^3.24.0",
23
23
  },
24
24
  };
@@ -12,8 +12,8 @@
12
12
  // Bun global type declaration for cross-runtime compatibility
13
13
  declare const Bun: { resolveSync?: (specifier: string, dir: string) => string } | undefined;
14
14
 
15
- import { fileURLToPath, pathToFileURL } from "node:url";
16
- import { dirname } from "node:path";
15
+ import { pathToFileURL } from "node:url";
16
+ import { createRequire } from "node:module";
17
17
  import { isBun, isDeno, isNode } from "./runtime.js";
18
18
  import { cwd } from "./process.js";
19
19
 
@@ -32,29 +32,6 @@ function hasBunResolveSync(): boolean {
32
32
  return typeof Bun !== "undefined" && typeof Bun?.resolveSync === "function";
33
33
  }
34
34
 
35
- type ImportMetaWithResolve = ImportMeta & {
36
- resolve?: (specifier: string, parent?: string) => string;
37
- };
38
-
39
- const IMPORT_META_RESOLVE_ERROR = "ImportMetaResolveUnavailable";
40
-
41
- function resolveWithImportMeta(specifier: string, parentUrl: string): string | null {
42
- const metaResolve = (import.meta as ImportMetaWithResolve).resolve;
43
- if (typeof metaResolve !== "function") {
44
- const error = new Error(
45
- "import.meta.resolve is required for Node ESM resolution (Node >= 22).",
46
- );
47
- error.name = IMPORT_META_RESOLVE_ERROR;
48
- throw error;
49
- }
50
-
51
- try {
52
- return metaResolve(specifier, parentUrl);
53
- } catch {
54
- return null;
55
- }
56
- }
57
-
58
35
  function resolveReactSpecifier(specifier: string): string | undefined {
59
36
  try {
60
37
  if (isBun && hasBunResolveSync() && Bun?.resolveSync) {
@@ -63,17 +40,15 @@ function resolveReactSpecifier(specifier: string): string | undefined {
63
40
  }
64
41
 
65
42
  if (isNode) {
66
- // Use import.meta.url (this module's location) as the parent URL.
67
- // This ensures React is resolved from veryfront's node_modules,
68
- // not from the cwd which may not have React installed.
69
- const thisModuleDir = dirname(fileURLToPath(import.meta.url));
70
- const parentUrl = pathToFileURL(`${thisModuleDir}/`).href;
71
- return resolveWithImportMeta(specifier, parentUrl) ?? undefined;
72
- }
73
- } catch (error) {
74
- if (error instanceof Error && error.name === IMPORT_META_RESOLVE_ERROR) {
75
- throw error;
43
+ // Use createRequire to resolve React from veryfront's node_modules.
44
+ // import.meta.resolve's parentUrl argument doesn't work correctly in Node.js,
45
+ // so we use createRequire which properly resolves from the specified path.
46
+ const require = createRequire(import.meta.url);
47
+ const resolved = require.resolve(specifier);
48
+ return pathToFileURL(resolved).href;
76
49
  }
50
+ } catch {
51
+ // Resolution failed, return undefined
77
52
  }
78
53
 
79
54
  return undefined;
@@ -199,6 +199,7 @@ async function cacheHttpModule(url: string, options: CacheOptions): Promise<stri
199
199
  try {
200
200
  const code = await fs.readTextFile(cachePath);
201
201
  await Promise.all([
202
+ distributed.set(`url:${hash}`, code, HTTP_MODULE_DISTRIBUTED_TTL_SEC),
202
203
  distributed.set(`code:${hash}`, code, HTTP_MODULE_DISTRIBUTED_TTL_SEC),
203
204
  distributed.set(`hash:${hash}`, normalizedUrl, HTTP_MODULE_DISTRIBUTED_TTL_SEC),
204
205
  ]);
@@ -221,11 +222,15 @@ async function cacheHttpModule(url: string, options: CacheOptions): Promise<stri
221
222
  }
222
223
 
223
224
  const distributed = await getDistributedCache();
225
+ const hash = simpleHash(normalizedUrl);
224
226
  if (distributed) {
225
227
  try {
226
- const cachedCode = await distributed.get(normalizedUrl);
228
+ // Use hash-based key instead of raw URL to comply with API cache key constraints.
229
+ // API cache keys only allow: alphanumeric, underscore, colon, dot, asterisk, hyphen, slash.
230
+ // URLs contain invalid characters like @, ?, =, &, etc.
231
+ const cachedCode = await distributed.get(`url:${hash}`);
227
232
  if (cachedCode) {
228
- logger.debug("[HTTP-CACHE] Distributed cache hit", { url: normalizedUrl });
233
+ logger.debug("[HTTP-CACHE] Distributed cache hit", { url: normalizedUrl, hash });
229
234
  await fs.mkdir(cacheDir, { recursive: true });
230
235
  await fs.writeTextFile(cachePath, cachedCode);
231
236
  cachedPaths.set(cacheKey, cachePath);
@@ -277,15 +282,21 @@ async function cacheHttpModule(url: string, options: CacheOptions): Promise<stri
277
282
  await fs.writeTextFile(cachePath, code);
278
283
 
279
284
  if (distributed) {
280
- // Store code by URL, by hash (for direct recovery), and URL mapping (for debugging).
281
- // Storing code by hash enables recovery without needing URL lookup.
285
+ // Store code by hash-based keys to comply with API cache key constraints.
286
+ // API cache keys only allow: alphanumeric, underscore, colon, dot, asterisk, hyphen, slash.
287
+ // URLs contain invalid characters (@, ?, =, &, etc.) so we use hashes instead.
288
+ //
289
+ // Keys stored:
290
+ // - url:{hash} - primary lookup key (replaces raw URL)
291
+ // - code:{hash} - direct code recovery by hash
292
+ // - hash:{hash} - URL mapping for debugging
293
+ //
282
294
  // IMPORTANT: await the writes so other pods can recover this bundle immediately.
283
295
  // Without await, a transform referencing this bundle could reach Redis before
284
296
  // the bundle code does, causing ensureHttpBundlesExist on another pod to miss.
285
- const hash = simpleHash(normalizedUrl);
286
297
  try {
287
298
  await Promise.all([
288
- distributed.set(normalizedUrl, code, HTTP_MODULE_DISTRIBUTED_TTL_SEC),
299
+ distributed.set(`url:${hash}`, code, HTTP_MODULE_DISTRIBUTED_TTL_SEC),
289
300
  distributed.set(`code:${hash}`, code, HTTP_MODULE_DISTRIBUTED_TTL_SEC),
290
301
  distributed.set(`hash:${hash}`, normalizedUrl, HTTP_MODULE_DISTRIBUTED_TTL_SEC),
291
302
  ]);
@@ -59,8 +59,9 @@ export const REACT_VERSION = DEFAULT_REACT_VERSION;
59
59
  * v10: Fix import regex to match minified code (from"..." without whitespace)
60
60
  * v11: Add HTTP bundle hash→URL mapping for cross-pod recovery
61
61
  * v12: Store HTTP bundle code by hash for direct recovery (code:{hash})
62
+ * v13: Fix npm: specifiers for Node.js (convert to esm.sh or local React)
62
63
  */
63
- export const TRANSFORM_CACHE_VERSION = 12;
64
+ export const TRANSFORM_CACHE_VERSION = 13;
64
65
 
65
66
  /** csstype version - must match deno.json for type consistency */
66
67
  export const CSSTYPE_VERSION = "3.2.3";