heliumts 0.7.4 → 0.7.6

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.
File without changes
@@ -1 +1 @@
1
- {"version":3,"file":"staleRecovery.d.ts","sourceRoot":"","sources":["../../src/client/staleRecovery.ts"],"names":[],"mappings":"AAeA,KAAK,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,SAAS,GAAG,SAAS,GAAG,YAAY,CAAC,CAAC;AAEvE,KAAK,iCAAiC,GAAG;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,QAAQ,CAAC;IAC1B,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AA+DF;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAWzD;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,GAAE,iCAAsC,GAAG,IAAI,CAyGhG"}
1
+ {"version":3,"file":"staleRecovery.d.ts","sourceRoot":"","sources":["../../src/client/staleRecovery.ts"],"names":[],"mappings":"AAeA,KAAK,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,SAAS,GAAG,SAAS,GAAG,YAAY,CAAC,CAAC;AAEvE,KAAK,iCAAiC,GAAG;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,QAAQ,CAAC;IAC1B,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AA2EF;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAWzD;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,GAAE,iCAAsC,GAAG,IAAI,CA+HhG"}
@@ -10,6 +10,17 @@ const CHUNK_ERROR_PATTERNS = [
10
10
  /Importing a module script failed/i,
11
11
  /dynamically imported module/i,
12
12
  ];
13
+ function resolveStorage(windowObject, override) {
14
+ if (override !== undefined) {
15
+ return override;
16
+ }
17
+ try {
18
+ return windowObject.sessionStorage;
19
+ }
20
+ catch {
21
+ return null;
22
+ }
23
+ }
13
24
  function readStoredNumber(storage, key) {
14
25
  if (!storage) {
15
26
  return null;
@@ -90,12 +101,14 @@ export function installStaleClientRecovery(options = {}) {
90
101
  }
91
102
  trackedWindow[INSTALL_FLAG] = true;
92
103
  const now = options.now ?? (() => Date.now());
93
- const storage = options.storage ?? windowObject.sessionStorage;
104
+ const storage = resolveStorage(windowObject, options.storage);
94
105
  const staleThresholdMs = options.staleThresholdMs ?? STALE_RESUME_THRESHOLD_MS;
95
106
  const reloadCooldownMs = options.reloadCooldownMs ?? RELOAD_COOLDOWN_MS;
96
107
  const reload = options.reload ?? (() => windowObject.location.reload());
97
108
  let isReloading = false;
109
+ let hasPendingReload = false;
98
110
  let hiddenAt = readStoredNumber(storage, HIDDEN_AT_STORAGE_KEY);
111
+ const isVisible = () => !documentObject.hidden;
99
112
  const markHidden = () => {
100
113
  hiddenAt = now();
101
114
  writeStoredNumber(storage, HIDDEN_AT_STORAGE_KEY, hiddenAt);
@@ -104,7 +117,11 @@ export function installStaleClientRecovery(options = {}) {
104
117
  hiddenAt = null;
105
118
  writeStoredNumber(storage, HIDDEN_AT_STORAGE_KEY, null);
106
119
  };
107
- const attemptReload = () => {
120
+ const executeReload = () => {
121
+ if (!isVisible()) {
122
+ hasPendingReload = true;
123
+ return;
124
+ }
108
125
  if (isReloading) {
109
126
  return;
110
127
  }
@@ -114,9 +131,19 @@ export function installStaleClientRecovery(options = {}) {
114
131
  return;
115
132
  }
116
133
  isReloading = true;
134
+ hasPendingReload = false;
117
135
  writeStoredNumber(storage, LAST_RELOAD_STORAGE_KEY, current);
118
136
  reload();
119
137
  };
138
+ const flushPendingReload = () => {
139
+ if (!hasPendingReload) {
140
+ return;
141
+ }
142
+ executeReload();
143
+ };
144
+ const attemptReload = () => {
145
+ executeReload();
146
+ };
120
147
  const maybeRecoverFromStaleResume = () => {
121
148
  const hiddenTimestamp = hiddenAt ?? readStoredNumber(storage, HIDDEN_AT_STORAGE_KEY);
122
149
  if (hiddenTimestamp === null) {
@@ -133,6 +160,7 @@ export function installStaleClientRecovery(options = {}) {
133
160
  markHidden();
134
161
  return;
135
162
  }
163
+ flushPendingReload();
136
164
  maybeRecoverFromStaleResume();
137
165
  }, { passive: true });
138
166
  windowObject.addEventListener("pagehide", () => {
@@ -140,6 +168,7 @@ export function installStaleClientRecovery(options = {}) {
140
168
  }, { passive: true });
141
169
  windowObject.addEventListener("pageshow", (event) => {
142
170
  if (event.persisted) {
171
+ flushPendingReload();
143
172
  maybeRecoverFromStaleResume();
144
173
  }
145
174
  }, { passive: true });
@@ -1 +1 @@
1
- {"version":3,"file":"staleRecovery.js","sourceRoot":"","sources":["../../src/client/staleRecovery.ts"],"names":[],"mappings":"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","sourcesContent":["const STALE_RESUME_THRESHOLD_MS = 30 * 60 * 1000;\nconst RELOAD_COOLDOWN_MS = 30 * 1000;\n\nconst INSTALL_FLAG = \"__helium_stale_client_recovery_installed__\";\nconst HIDDEN_AT_STORAGE_KEY = \"__helium_stale_client_hidden_at__\";\nconst LAST_RELOAD_STORAGE_KEY = \"__helium_stale_client_last_reload_at__\";\n\nconst CHUNK_ERROR_PATTERNS: RegExp[] = [\n /ChunkLoadError/i,\n /Loading chunk\\s+\\d+\\s+failed/i,\n /Failed to fetch dynamically imported module/i,\n /Importing a module script failed/i,\n /dynamically imported module/i,\n];\n\ntype StorageLike = Pick<Storage, \"getItem\" | \"setItem\" | \"removeItem\">;\n\ntype InstallStaleClientRecoveryOptions = {\n windowObject?: Window;\n documentObject?: Document;\n storage?: StorageLike | null;\n now?: () => number;\n reload?: () => void;\n staleThresholdMs?: number;\n reloadCooldownMs?: number;\n disableDedupe?: boolean;\n};\n\ntype WindowWithInstallFlag = Window & {\n [INSTALL_FLAG]?: boolean;\n};\n\nfunction readStoredNumber(storage: StorageLike | null, key: string): number | null {\n if (!storage) {\n return null;\n }\n\n try {\n const raw = storage.getItem(key);\n if (!raw) {\n return null;\n }\n const parsed = Number(raw);\n return Number.isFinite(parsed) ? parsed : null;\n } catch {\n return null;\n }\n}\n\nfunction writeStoredNumber(storage: StorageLike | null, key: string, value: number | null): void {\n if (!storage) {\n return;\n }\n\n try {\n if (value === null) {\n storage.removeItem(key);\n return;\n }\n storage.setItem(key, String(value));\n } catch {\n // Ignore storage write failures (private mode, quota exceeded, etc.)\n }\n}\n\nfunction extractErrorText(reason: unknown): string {\n if (typeof reason === \"string\") {\n return reason;\n }\n\n if (reason instanceof Error) {\n return `${reason.name}: ${reason.message}`;\n }\n\n if (typeof reason === \"object\" && reason !== null) {\n const maybeMessage = Reflect.get(reason, \"message\");\n if (typeof maybeMessage === \"string\") {\n return maybeMessage;\n }\n\n const maybeName = Reflect.get(reason, \"name\");\n if (typeof maybeName === \"string\") {\n return maybeName;\n }\n }\n\n return \"\";\n}\n\n/**\n * @internal Exported for testing\n */\nexport function isChunkLoadError(reason: unknown): boolean {\n if (reason instanceof Error && reason.name === \"ChunkLoadError\") {\n return true;\n }\n\n const text = extractErrorText(reason);\n if (!text) {\n return false;\n }\n\n return CHUNK_ERROR_PATTERNS.some((pattern) => pattern.test(text));\n}\n\n/**\n * Installs default stale-client recovery for mobile suspend/resume and stale chunks.\n *\n * @internal Exported for testing\n */\nexport function installStaleClientRecovery(options: InstallStaleClientRecoveryOptions = {}): void {\n const windowObject = options.windowObject ?? (typeof window !== \"undefined\" ? window : undefined);\n const documentObject = options.documentObject ?? (typeof document !== \"undefined\" ? document : undefined);\n\n if (!windowObject || !documentObject) {\n return;\n }\n\n const trackedWindow = windowObject as WindowWithInstallFlag;\n if (!options.disableDedupe && trackedWindow[INSTALL_FLAG]) {\n return;\n }\n trackedWindow[INSTALL_FLAG] = true;\n\n const now = options.now ?? (() => Date.now());\n const storage = options.storage ?? windowObject.sessionStorage;\n const staleThresholdMs = options.staleThresholdMs ?? STALE_RESUME_THRESHOLD_MS;\n const reloadCooldownMs = options.reloadCooldownMs ?? RELOAD_COOLDOWN_MS;\n const reload = options.reload ?? (() => windowObject.location.reload());\n\n let isReloading = false;\n let hiddenAt = readStoredNumber(storage, HIDDEN_AT_STORAGE_KEY);\n\n const markHidden = () => {\n hiddenAt = now();\n writeStoredNumber(storage, HIDDEN_AT_STORAGE_KEY, hiddenAt);\n };\n\n const clearHidden = () => {\n hiddenAt = null;\n writeStoredNumber(storage, HIDDEN_AT_STORAGE_KEY, null);\n };\n\n const attemptReload = () => {\n if (isReloading) {\n return;\n }\n\n const current = now();\n const lastReloadAt = readStoredNumber(storage, LAST_RELOAD_STORAGE_KEY) ?? 0;\n if (current - lastReloadAt < reloadCooldownMs) {\n return;\n }\n\n isReloading = true;\n writeStoredNumber(storage, LAST_RELOAD_STORAGE_KEY, current);\n reload();\n };\n\n const maybeRecoverFromStaleResume = () => {\n const hiddenTimestamp = hiddenAt ?? readStoredNumber(storage, HIDDEN_AT_STORAGE_KEY);\n if (hiddenTimestamp === null) {\n return;\n }\n\n const hiddenDuration = now() - hiddenTimestamp;\n clearHidden();\n if (hiddenDuration >= staleThresholdMs) {\n attemptReload();\n }\n };\n\n documentObject.addEventListener(\n \"visibilitychange\",\n () => {\n if (documentObject.hidden) {\n markHidden();\n return;\n }\n maybeRecoverFromStaleResume();\n },\n { passive: true }\n );\n\n windowObject.addEventListener(\n \"pagehide\",\n () => {\n markHidden();\n },\n { passive: true }\n );\n\n windowObject.addEventListener(\n \"pageshow\",\n (event) => {\n if ((event as PageTransitionEvent).persisted) {\n maybeRecoverFromStaleResume();\n }\n },\n { passive: true }\n );\n\n windowObject.addEventListener(\"error\", (event) => {\n const errorEvent = event as ErrorEvent;\n if (isChunkLoadError(errorEvent.error ?? errorEvent.message)) {\n attemptReload();\n }\n });\n\n windowObject.addEventListener(\"unhandledrejection\", (event) => {\n const rejectionEvent = event as PromiseRejectionEvent;\n if (isChunkLoadError(rejectionEvent.reason)) {\n attemptReload();\n }\n });\n}\n"]}
1
+ {"version":3,"file":"staleRecovery.js","sourceRoot":"","sources":["../../src/client/staleRecovery.ts"],"names":[],"mappings":"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","sourcesContent":["const STALE_RESUME_THRESHOLD_MS = 30 * 60 * 1000;\nconst RELOAD_COOLDOWN_MS = 30 * 1000;\n\nconst INSTALL_FLAG = \"__helium_stale_client_recovery_installed__\";\nconst HIDDEN_AT_STORAGE_KEY = \"__helium_stale_client_hidden_at__\";\nconst LAST_RELOAD_STORAGE_KEY = \"__helium_stale_client_last_reload_at__\";\n\nconst CHUNK_ERROR_PATTERNS: RegExp[] = [\n /ChunkLoadError/i,\n /Loading chunk\\s+\\d+\\s+failed/i,\n /Failed to fetch dynamically imported module/i,\n /Importing a module script failed/i,\n /dynamically imported module/i,\n];\n\ntype StorageLike = Pick<Storage, \"getItem\" | \"setItem\" | \"removeItem\">;\n\ntype InstallStaleClientRecoveryOptions = {\n windowObject?: Window;\n documentObject?: Document;\n storage?: StorageLike | null;\n now?: () => number;\n reload?: () => void;\n staleThresholdMs?: number;\n reloadCooldownMs?: number;\n disableDedupe?: boolean;\n};\n\ntype WindowWithInstallFlag = Window & {\n [INSTALL_FLAG]?: boolean;\n};\n\nfunction resolveStorage(windowObject: Window, override?: StorageLike | null): StorageLike | null {\n if (override !== undefined) {\n return override;\n }\n\n try {\n return windowObject.sessionStorage;\n } catch {\n return null;\n }\n}\n\nfunction readStoredNumber(storage: StorageLike | null, key: string): number | null {\n if (!storage) {\n return null;\n }\n\n try {\n const raw = storage.getItem(key);\n if (!raw) {\n return null;\n }\n const parsed = Number(raw);\n return Number.isFinite(parsed) ? parsed : null;\n } catch {\n return null;\n }\n}\n\nfunction writeStoredNumber(storage: StorageLike | null, key: string, value: number | null): void {\n if (!storage) {\n return;\n }\n\n try {\n if (value === null) {\n storage.removeItem(key);\n return;\n }\n storage.setItem(key, String(value));\n } catch {\n // Ignore storage write failures (private mode, quota exceeded, etc.)\n }\n}\n\nfunction extractErrorText(reason: unknown): string {\n if (typeof reason === \"string\") {\n return reason;\n }\n\n if (reason instanceof Error) {\n return `${reason.name}: ${reason.message}`;\n }\n\n if (typeof reason === \"object\" && reason !== null) {\n const maybeMessage = Reflect.get(reason, \"message\");\n if (typeof maybeMessage === \"string\") {\n return maybeMessage;\n }\n\n const maybeName = Reflect.get(reason, \"name\");\n if (typeof maybeName === \"string\") {\n return maybeName;\n }\n }\n\n return \"\";\n}\n\n/**\n * @internal Exported for testing\n */\nexport function isChunkLoadError(reason: unknown): boolean {\n if (reason instanceof Error && reason.name === \"ChunkLoadError\") {\n return true;\n }\n\n const text = extractErrorText(reason);\n if (!text) {\n return false;\n }\n\n return CHUNK_ERROR_PATTERNS.some((pattern) => pattern.test(text));\n}\n\n/**\n * Installs default stale-client recovery for mobile suspend/resume and stale chunks.\n *\n * @internal Exported for testing\n */\nexport function installStaleClientRecovery(options: InstallStaleClientRecoveryOptions = {}): void {\n const windowObject = options.windowObject ?? (typeof window !== \"undefined\" ? window : undefined);\n const documentObject = options.documentObject ?? (typeof document !== \"undefined\" ? document : undefined);\n\n if (!windowObject || !documentObject) {\n return;\n }\n\n const trackedWindow = windowObject as WindowWithInstallFlag;\n if (!options.disableDedupe && trackedWindow[INSTALL_FLAG]) {\n return;\n }\n trackedWindow[INSTALL_FLAG] = true;\n\n const now = options.now ?? (() => Date.now());\n const storage = resolveStorage(windowObject, options.storage);\n const staleThresholdMs = options.staleThresholdMs ?? STALE_RESUME_THRESHOLD_MS;\n const reloadCooldownMs = options.reloadCooldownMs ?? RELOAD_COOLDOWN_MS;\n const reload = options.reload ?? (() => windowObject.location.reload());\n\n let isReloading = false;\n let hasPendingReload = false;\n let hiddenAt = readStoredNumber(storage, HIDDEN_AT_STORAGE_KEY);\n\n const isVisible = () => !documentObject.hidden;\n\n const markHidden = () => {\n hiddenAt = now();\n writeStoredNumber(storage, HIDDEN_AT_STORAGE_KEY, hiddenAt);\n };\n\n const clearHidden = () => {\n hiddenAt = null;\n writeStoredNumber(storage, HIDDEN_AT_STORAGE_KEY, null);\n };\n\n const executeReload = () => {\n if (!isVisible()) {\n hasPendingReload = true;\n return;\n }\n\n if (isReloading) {\n return;\n }\n\n const current = now();\n const lastReloadAt = readStoredNumber(storage, LAST_RELOAD_STORAGE_KEY) ?? 0;\n if (current - lastReloadAt < reloadCooldownMs) {\n return;\n }\n\n isReloading = true;\n hasPendingReload = false;\n writeStoredNumber(storage, LAST_RELOAD_STORAGE_KEY, current);\n reload();\n };\n\n const flushPendingReload = () => {\n if (!hasPendingReload) {\n return;\n }\n executeReload();\n };\n\n const attemptReload = () => {\n executeReload();\n };\n\n const maybeRecoverFromStaleResume = () => {\n const hiddenTimestamp = hiddenAt ?? readStoredNumber(storage, HIDDEN_AT_STORAGE_KEY);\n if (hiddenTimestamp === null) {\n return;\n }\n\n const hiddenDuration = now() - hiddenTimestamp;\n clearHidden();\n if (hiddenDuration >= staleThresholdMs) {\n attemptReload();\n }\n };\n\n documentObject.addEventListener(\n \"visibilitychange\",\n () => {\n if (documentObject.hidden) {\n markHidden();\n return;\n }\n flushPendingReload();\n maybeRecoverFromStaleResume();\n },\n { passive: true }\n );\n\n windowObject.addEventListener(\n \"pagehide\",\n () => {\n markHidden();\n },\n { passive: true }\n );\n\n windowObject.addEventListener(\n \"pageshow\",\n (event) => {\n if ((event as PageTransitionEvent).persisted) {\n flushPendingReload();\n maybeRecoverFromStaleResume();\n }\n },\n { passive: true }\n );\n\n windowObject.addEventListener(\"error\", (event) => {\n const errorEvent = event as ErrorEvent;\n if (isChunkLoadError(errorEvent.error ?? errorEvent.message)) {\n attemptReload();\n }\n });\n\n windowObject.addEventListener(\"unhandledrejection\", (event) => {\n const rejectionEvent = event as PromiseRejectionEvent;\n if (isChunkLoadError(rejectionEvent.reason)) {\n attemptReload();\n }\n });\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"virtualServerModule.d.ts","sourceRoot":"","sources":["../../src/vite/virtualServerModule.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAElH,wBAAgB,sBAAsB,CAClC,OAAO,EAAE,YAAY,EAAE,EACvB,YAAY,EAAE,iBAAiB,EAAE,EACjC,WAAW,GAAE,iBAAiB,EAAO,EACrC,iBAAiB,GAAE,MAAM,EAAO,EAChC,UAAU,CAAC,EAAE,gBAAgB,EAC7B,OAAO,GAAE,YAAY,EAAO,GAC7B,MAAM,CAyCR;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAIpE;AAkBD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CA+DrF;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAkB5C"}
1
+ {"version":3,"file":"virtualServerModule.d.ts","sourceRoot":"","sources":["../../src/vite/virtualServerModule.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAElH,wBAAgB,sBAAsB,CAClC,OAAO,EAAE,YAAY,EAAE,EACvB,YAAY,EAAE,iBAAiB,EAAE,EACjC,WAAW,GAAE,iBAAiB,EAAO,EACrC,iBAAiB,GAAE,MAAM,EAAO,EAChC,UAAU,CAAC,EAAE,gBAAgB,EAC7B,OAAO,GAAE,YAAY,EAAO,GAC7B,MAAM,CAyCR;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAIpE;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAiErF;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAkB5C"}
@@ -41,44 +41,31 @@ export function generateClientModule(methods) {
41
41
  const exports = methods.map((m) => `export const ${m.name} = { __id: '${m.name}' };`).join("\n");
42
42
  return exports;
43
43
  }
44
- /**
45
- * Generate a deterministic suffix from a string.
46
- * Uses only file path and method name (NOT index) so that adding/removing
47
- * other methods does not change existing aliases.
48
- */
49
- function stableAlias(filePath, name) {
50
- const input = `${filePath}:${name}`;
51
- let hash = 0;
52
- for (let i = 0; i < input.length; i++) {
53
- const char = input.charCodeAt(i);
54
- hash = (hash << 5) - hash + char;
55
- hash = hash & hash; // Convert to 32bit integer
56
- }
57
- return `${name}_${Math.abs(hash).toString(36)}`;
58
- }
59
44
  export function generateTypeDefinitions(methods, root) {
60
45
  // Sort methods by name for a stable output regardless of file-system walk order
61
46
  const sorted = [...methods].sort((a, b) => a.name.localeCompare(b.name));
62
- const methodsWithAlias = sorted.map((m) => ({
63
- ...m,
64
- alias: stableAlias(m.filePath, m.name),
65
- }));
66
- const imports = methodsWithAlias
67
- .map((m) => {
47
+ const methodsWithRelativePath = sorted.map((m) => {
68
48
  let relPath = path.relative(path.join(root, "src"), m.filePath);
69
49
  if (!relPath.startsWith(".")) {
70
50
  relPath = "../" + relPath;
71
51
  }
72
52
  // Normalize to posix separators for import paths
73
53
  relPath = relPath.replace(/\\/g, "/").replace(/\.ts$/, "");
74
- return `import type { ${m.name} as ${m.alias} } from '${relPath}';`;
54
+ return {
55
+ ...m,
56
+ relPath,
57
+ };
58
+ });
59
+ const imports = methodsWithRelativePath
60
+ .map((m, index) => {
61
+ return `import type { ${m.name} as __helium_method_${index} } from '${m.relPath}';`;
75
62
  })
76
63
  .join("\n");
77
- const methodExports = methodsWithAlias
78
- .map((m) => {
64
+ const methodExports = methodsWithRelativePath
65
+ .map((m, index) => {
79
66
  return ` export const ${m.name}: import('heliumts/client').MethodStub<
80
- Parameters<typeof ${m.alias}['handler']>[0],
81
- Awaited<ReturnType<typeof ${m.alias}['handler']>>
67
+ Parameters<typeof __helium_method_${index}['handler']>[0],
68
+ Awaited<ReturnType<typeof __helium_method_${index}['handler']>>
82
69
  >;`;
83
70
  })
84
71
  .join("\n");
@@ -98,7 +85,7 @@ export function generateTypeDefinitions(methods, root) {
98
85
  export {};
99
86
  `;
100
87
  }
101
- const methodSignature = methodsWithAlias.map((m) => m.name).join(", ");
88
+ const methodSignature = methodsWithRelativePath.map((m) => m.name).join(", ");
102
89
  return `/* eslint-disable */
103
90
  /**
104
91
  * Auto generated file - DO NOT EDIT!
@@ -1 +1 @@
1
- {"version":3,"file":"virtualServerModule.js","sourceRoot":"","sources":["../../src/vite/virtualServerModule.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"path\";\n\nimport { HTTPHandlerExport, MethodExport, MiddlewareExport, SEOMetadataExport, WorkerExport } from \"./scanner.js\";\n\nexport function generateServerManifest(\n methods: MethodExport[],\n httpHandlers: HTTPHandlerExport[],\n seoMetadata: SEOMetadataExport[] = [],\n pageRoutePatterns: string[] = [],\n middleware?: MiddlewareExport,\n workers: WorkerExport[] = []\n): string {\n const methodImports = methods.map((m, i) => `import { ${m.name} as method_${i} } from '${m.filePath}';`).join(\"\\n\");\n const httpImports = httpHandlers.map((h, i) => `import { ${h.name} as http_${i} } from '${h.filePath}';`).join(\"\\n\");\n const seoImports = seoMetadata.map((s, i) => `import { ${s.name} as seo_${i} } from '${s.filePath}';`).join(\"\\n\");\n const workerImports = workers.map((w, i) => `import { ${w.name} as worker_${i} } from '${w.filePath}';`).join(\"\\n\");\n const middlewareImport = middleware ? `import ${middleware.name === \"default\" ? \"middleware\" : `{ ${middleware.name} as middleware }`} from '${middleware.filePath}';` : \"\";\n\n const methodRegistrations = methods.map((m, i) => ` registry.register('${m.name}', method_${i});`).join(\"\\n\");\n\n const httpExports = httpHandlers.map((h, i) => ` { name: '${h.name}', handler: http_${i} },`).join(\"\\n\");\n const seoExports = seoMetadata.map((s, i) => ` { name: '${s.name}', handler: seo_${i} },`).join(\"\\n\");\n\n const workerExports = workers.map((w, i) => ` { name: '${w.name}', worker: worker_${i} },`).join(\"\\n\");\n\n return `\n${methodImports}\n${httpImports}\n${seoImports}\n${workerImports}\n${middlewareImport}\n\nexport function registerAll(registry) {\n${methodRegistrations}\n}\n\nexport const httpHandlers = [\n${httpExports}\n];\n\nexport const seoMetadataHandlers = [\n${seoExports}\n];\n\nexport const pageRoutePatterns = ${JSON.stringify(pageRoutePatterns)};\n\nexport const workers = [\n${workerExports}\n];\n\nexport const middlewareHandler = ${middleware ? \"middleware\" : \"null\"};\n`;\n}\n\nexport function generateClientModule(methods: MethodExport[]): string {\n const exports = methods.map((m) => `export const ${m.name} = { __id: '${m.name}' };`).join(\"\\n\");\n\n return exports;\n}\n\n/**\n * Generate a deterministic suffix from a string.\n * Uses only file path and method name (NOT index) so that adding/removing\n * other methods does not change existing aliases.\n */\nfunction stableAlias(filePath: string, name: string): string {\n const input = `${filePath}:${name}`;\n let hash = 0;\n for (let i = 0; i < input.length; i++) {\n const char = input.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash; // Convert to 32bit integer\n }\n return `${name}_${Math.abs(hash).toString(36)}`;\n}\n\nexport function generateTypeDefinitions(methods: MethodExport[], root: string): string {\n // Sort methods by name for a stable output regardless of file-system walk order\n const sorted = [...methods].sort((a, b) => a.name.localeCompare(b.name));\n\n const methodsWithAlias = sorted.map((m) => ({\n ...m,\n alias: stableAlias(m.filePath, m.name),\n }));\n\n const imports = methodsWithAlias\n .map((m) => {\n let relPath = path.relative(path.join(root, \"src\"), m.filePath);\n if (!relPath.startsWith(\".\")) {\n relPath = \"../\" + relPath;\n }\n // Normalize to posix separators for import paths\n relPath = relPath.replace(/\\\\/g, \"/\").replace(/\\.ts$/, \"\");\n return `import type { ${m.name} as ${m.alias} } from '${relPath}';`;\n })\n .join(\"\\n\");\n\n const methodExports = methodsWithAlias\n .map((m) => {\n return ` export const ${m.name}: import('heliumts/client').MethodStub<\n Parameters<typeof ${m.alias}['handler']>[0],\n Awaited<ReturnType<typeof ${m.alias}['handler']>>\n >;`;\n })\n .join(\"\\n\");\n\n // If there are no methods, we don't need to generate any augmentation\n // This prevents shadowing the actual heliumts/server exports\n if (methods.length === 0) {\n return `/* eslint-disable */\n/**\n* Auto generated file - DO NOT EDIT!\n* # Helium Server Type Definitions\n* \n* This file is empty because no methods have been defined yet.\n* Once you create a method using defineMethod(), type stubs will be generated here.\n*\n* @helium-methods (none)\n**/\nexport {};\n`;\n }\n\n const methodSignature = methodsWithAlias.map((m) => m.name).join(\", \");\n\n return `/* eslint-disable */\n/**\n* Auto generated file - DO NOT EDIT!\n* # Helium Server Type Definitions\n*\n* @helium-methods ${methodSignature}\n**/\n${imports}\n\ndeclare module 'heliumts/server' {\n // Method stubs for client-side type inference\n${methodExports}\n}\n`;\n}\n\nexport function generateEntryModule(): string {\n return `\nimport React from 'react';\nimport { createRoot } from 'react-dom/client';\nimport { AppRouter } from 'heliumts/client';\nimport App from '/src/App';\n\nconst rootEl = document.getElementById('root');\nif (!rootEl) {\n throw new Error('Root element not found. Helium requires a <div id=\\\"root\\\"></div> in your HTML.');\n}\n\ncreateRoot(rootEl).render(\n <React.StrictMode>\n <AppRouter AppShell={App} />\n </React.StrictMode>\n);\n`;\n}\n"]}
1
+ {"version":3,"file":"virtualServerModule.js","sourceRoot":"","sources":["../../src/vite/virtualServerModule.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"path\";\n\nimport { HTTPHandlerExport, MethodExport, MiddlewareExport, SEOMetadataExport, WorkerExport } from \"./scanner.js\";\n\nexport function generateServerManifest(\n methods: MethodExport[],\n httpHandlers: HTTPHandlerExport[],\n seoMetadata: SEOMetadataExport[] = [],\n pageRoutePatterns: string[] = [],\n middleware?: MiddlewareExport,\n workers: WorkerExport[] = []\n): string {\n const methodImports = methods.map((m, i) => `import { ${m.name} as method_${i} } from '${m.filePath}';`).join(\"\\n\");\n const httpImports = httpHandlers.map((h, i) => `import { ${h.name} as http_${i} } from '${h.filePath}';`).join(\"\\n\");\n const seoImports = seoMetadata.map((s, i) => `import { ${s.name} as seo_${i} } from '${s.filePath}';`).join(\"\\n\");\n const workerImports = workers.map((w, i) => `import { ${w.name} as worker_${i} } from '${w.filePath}';`).join(\"\\n\");\n const middlewareImport = middleware ? `import ${middleware.name === \"default\" ? \"middleware\" : `{ ${middleware.name} as middleware }`} from '${middleware.filePath}';` : \"\";\n\n const methodRegistrations = methods.map((m, i) => ` registry.register('${m.name}', method_${i});`).join(\"\\n\");\n\n const httpExports = httpHandlers.map((h, i) => ` { name: '${h.name}', handler: http_${i} },`).join(\"\\n\");\n const seoExports = seoMetadata.map((s, i) => ` { name: '${s.name}', handler: seo_${i} },`).join(\"\\n\");\n\n const workerExports = workers.map((w, i) => ` { name: '${w.name}', worker: worker_${i} },`).join(\"\\n\");\n\n return `\n${methodImports}\n${httpImports}\n${seoImports}\n${workerImports}\n${middlewareImport}\n\nexport function registerAll(registry) {\n${methodRegistrations}\n}\n\nexport const httpHandlers = [\n${httpExports}\n];\n\nexport const seoMetadataHandlers = [\n${seoExports}\n];\n\nexport const pageRoutePatterns = ${JSON.stringify(pageRoutePatterns)};\n\nexport const workers = [\n${workerExports}\n];\n\nexport const middlewareHandler = ${middleware ? \"middleware\" : \"null\"};\n`;\n}\n\nexport function generateClientModule(methods: MethodExport[]): string {\n const exports = methods.map((m) => `export const ${m.name} = { __id: '${m.name}' };`).join(\"\\n\");\n\n return exports;\n}\n\nexport function generateTypeDefinitions(methods: MethodExport[], root: string): string {\n // Sort methods by name for a stable output regardless of file-system walk order\n const sorted = [...methods].sort((a, b) => a.name.localeCompare(b.name));\n\n const methodsWithRelativePath = sorted.map((m) => {\n let relPath = path.relative(path.join(root, \"src\"), m.filePath);\n if (!relPath.startsWith(\".\")) {\n relPath = \"../\" + relPath;\n }\n // Normalize to posix separators for import paths\n relPath = relPath.replace(/\\\\/g, \"/\").replace(/\\.ts$/, \"\");\n return {\n ...m,\n relPath,\n };\n });\n\n const imports = methodsWithRelativePath\n .map((m, index) => {\n return `import type { ${m.name} as __helium_method_${index} } from '${m.relPath}';`;\n })\n .join(\"\\n\");\n\n const methodExports = methodsWithRelativePath\n .map((m, index) => {\n return ` export const ${m.name}: import('heliumts/client').MethodStub<\n Parameters<typeof __helium_method_${index}['handler']>[0],\n Awaited<ReturnType<typeof __helium_method_${index}['handler']>>\n >;`;\n })\n .join(\"\\n\");\n\n // If there are no methods, we don't need to generate any augmentation\n // This prevents shadowing the actual heliumts/server exports\n if (methods.length === 0) {\n return `/* eslint-disable */\n/**\n* Auto generated file - DO NOT EDIT!\n* # Helium Server Type Definitions\n* \n* This file is empty because no methods have been defined yet.\n* Once you create a method using defineMethod(), type stubs will be generated here.\n*\n* @helium-methods (none)\n**/\nexport {};\n`;\n }\n\n const methodSignature = methodsWithRelativePath.map((m) => m.name).join(\", \");\n\n return `/* eslint-disable */\n/**\n* Auto generated file - DO NOT EDIT!\n* # Helium Server Type Definitions\n*\n* @helium-methods ${methodSignature}\n**/\n${imports}\n\ndeclare module 'heliumts/server' {\n // Method stubs for client-side type inference\n${methodExports}\n}\n`;\n}\n\nexport function generateEntryModule(): string {\n return `\nimport React from 'react';\nimport { createRoot } from 'react-dom/client';\nimport { AppRouter } from 'heliumts/client';\nimport App from '/src/App';\n\nconst rootEl = document.getElementById('root');\nif (!rootEl) {\n throw new Error('Root element not found. Helium requires a <div id=\\\"root\\\"></div> in your HTML.');\n}\n\ncreateRoot(rootEl).render(\n <React.StrictMode>\n <AppRouter AppShell={App} />\n </React.StrictMode>\n);\n`;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "heliumts",
3
- "version": "0.7.4",
3
+ "version": "0.7.6",
4
4
  "description": "A lightweight full-stack React framework with file-based routing, RPC, and SSG support",
5
5
  "keywords": [
6
6
  "react",
@@ -1,48 +0,0 @@
1
- import type http from "http";
2
- /**
3
- * Extracts the client IP address from an HTTP request, taking into account proxy configurations.
4
- *
5
- * When behind proxies (like Vercel, Cloudflare, AWS ALB, etc.), the X-Forwarded-For header
6
- * contains a chain of IP addresses. The format is: "client, proxy1, proxy2, ..."
7
- *
8
- * @param req - The HTTP request object
9
- * @param trustProxyDepth - Number of proxy levels to trust
10
- * - 0: Only use req.socket.remoteAddress (no proxy trust)
11
- * - 1: Trust 1 proxy level (get the last IP before your server)
12
- * - 2+: Trust multiple proxy levels (for complex setups)
13
- *
14
- * Examples:
15
- * - trustProxyDepth=0: Direct connection, no proxies
16
- * X-Forwarded-For: ignored
17
- * Result: req.socket.remoteAddress
18
- *
19
- * - trustProxyDepth=1: Behind one proxy (e.g., Vercel, Netlify)
20
- * X-Forwarded-For: "203.0.113.1, 198.51.100.1"
21
- * Result: "203.0.113.1" (client IP)
22
- *
23
- * - trustProxyDepth=2: Behind two proxies (e.g., Cloudflare -> Load Balancer)
24
- * X-Forwarded-For: "203.0.113.1, 198.51.100.1, 192.0.2.1"
25
- * Result: "203.0.113.1" (client IP)
26
- *
27
- * Common configurations:
28
- * - Vercel/Netlify/Railway: trustProxyDepth=1
29
- * - Cloudflare -> Origin: trustProxyDepth=1 or 2 (depending on your setup)
30
- * - AWS ALB -> EC2: trustProxyDepth=1
31
- * - Nginx -> Node: trustProxyDepth=1
32
- * - Cloudflare -> Nginx -> Node: trustProxyDepth=2
33
- */
34
- export declare function extractClientIP(req: http.IncomingMessage, trustProxyDepth?: number): string;
35
- /**
36
- * Alternative extraction method that works from the right (trusts the rightmost IPs).
37
- * This is useful when you want to trust the last N proxies in the chain.
38
- *
39
- * @param req - The HTTP request object
40
- * @param trustProxyDepth - Number of proxy levels to trust from the right
41
- *
42
- * Example:
43
- * X-Forwarded-For: "203.0.113.1, 198.51.100.1, 192.0.2.1"
44
- * trustProxyDepth=1: Result is "198.51.100.1" (skip the last trusted proxy)
45
- * trustProxyDepth=2: Result is "203.0.113.1" (skip the last 2 trusted proxies)
46
- */
47
- export declare function extractClientIPFromRight(req: http.IncomingMessage, trustProxyDepth?: number): string;
48
- //# sourceMappingURL=ipExtractor.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ipExtractor.d.ts","sourceRoot":"","sources":["../../src/server/ipExtractor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,eAAe,GAAE,MAAU,GAAG,MAAM,CAqC9F;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,IAAI,CAAC,eAAe,EAAE,eAAe,GAAE,MAAU,GAAG,MAAM,CAsBvG"}
@@ -1,96 +0,0 @@
1
- /**
2
- * Extracts the client IP address from an HTTP request, taking into account proxy configurations.
3
- *
4
- * When behind proxies (like Vercel, Cloudflare, AWS ALB, etc.), the X-Forwarded-For header
5
- * contains a chain of IP addresses. The format is: "client, proxy1, proxy2, ..."
6
- *
7
- * @param req - The HTTP request object
8
- * @param trustProxyDepth - Number of proxy levels to trust
9
- * - 0: Only use req.socket.remoteAddress (no proxy trust)
10
- * - 1: Trust 1 proxy level (get the last IP before your server)
11
- * - 2+: Trust multiple proxy levels (for complex setups)
12
- *
13
- * Examples:
14
- * - trustProxyDepth=0: Direct connection, no proxies
15
- * X-Forwarded-For: ignored
16
- * Result: req.socket.remoteAddress
17
- *
18
- * - trustProxyDepth=1: Behind one proxy (e.g., Vercel, Netlify)
19
- * X-Forwarded-For: "203.0.113.1, 198.51.100.1"
20
- * Result: "203.0.113.1" (client IP)
21
- *
22
- * - trustProxyDepth=2: Behind two proxies (e.g., Cloudflare -> Load Balancer)
23
- * X-Forwarded-For: "203.0.113.1, 198.51.100.1, 192.0.2.1"
24
- * Result: "203.0.113.1" (client IP)
25
- *
26
- * Common configurations:
27
- * - Vercel/Netlify/Railway: trustProxyDepth=1
28
- * - Cloudflare -> Origin: trustProxyDepth=1 or 2 (depending on your setup)
29
- * - AWS ALB -> EC2: trustProxyDepth=1
30
- * - Nginx -> Node: trustProxyDepth=1
31
- * - Cloudflare -> Nginx -> Node: trustProxyDepth=2
32
- */
33
- export function extractClientIP(req, trustProxyDepth = 0) {
34
- // If not trusting any proxies, return the direct connection IP
35
- if (trustProxyDepth === 0) {
36
- return req.socket.remoteAddress || "unknown";
37
- }
38
- // Get X-Forwarded-For header
39
- const forwardedFor = req.headers["x-forwarded-for"];
40
- if (!forwardedFor) {
41
- // No X-Forwarded-For header, fall back to direct connection
42
- return req.socket.remoteAddress || "unknown";
43
- }
44
- // Parse X-Forwarded-For header (can be a string or array of strings)
45
- const forwardedIPs = (Array.isArray(forwardedFor) ? forwardedFor.join(",") : forwardedFor)
46
- .split(",")
47
- .map((ip) => ip.trim())
48
- .filter((ip) => ip.length > 0);
49
- if (forwardedIPs.length === 0) {
50
- // Empty X-Forwarded-For, fall back to direct connection
51
- return req.socket.remoteAddress || "unknown";
52
- }
53
- // The client IP is at the beginning of the chain
54
- // We trust the chain up to trustProxyDepth levels
55
- // Format: [clientIP, proxy1, proxy2, ..., lastProxy]
56
- // We want the clientIP, but we need to verify we have enough trusted proxies
57
- if (forwardedIPs.length < trustProxyDepth) {
58
- // Not enough IPs in the chain, the chain might be incomplete or spoofed
59
- // Fall back to direct connection for safety
60
- return req.socket.remoteAddress || "unknown";
61
- }
62
- // Return the client IP (first in the chain)
63
- return forwardedIPs[0];
64
- }
65
- /**
66
- * Alternative extraction method that works from the right (trusts the rightmost IPs).
67
- * This is useful when you want to trust the last N proxies in the chain.
68
- *
69
- * @param req - The HTTP request object
70
- * @param trustProxyDepth - Number of proxy levels to trust from the right
71
- *
72
- * Example:
73
- * X-Forwarded-For: "203.0.113.1, 198.51.100.1, 192.0.2.1"
74
- * trustProxyDepth=1: Result is "198.51.100.1" (skip the last trusted proxy)
75
- * trustProxyDepth=2: Result is "203.0.113.1" (skip the last 2 trusted proxies)
76
- */
77
- export function extractClientIPFromRight(req, trustProxyDepth = 0) {
78
- if (trustProxyDepth === 0) {
79
- return req.socket.remoteAddress || "unknown";
80
- }
81
- const forwardedFor = req.headers["x-forwarded-for"];
82
- if (!forwardedFor) {
83
- return req.socket.remoteAddress || "unknown";
84
- }
85
- const forwardedIPs = (Array.isArray(forwardedFor) ? forwardedFor.join(",") : forwardedFor)
86
- .split(",")
87
- .map((ip) => ip.trim())
88
- .filter((ip) => ip.length > 0);
89
- if (forwardedIPs.length === 0) {
90
- return req.socket.remoteAddress || "unknown";
91
- }
92
- // Calculate which IP to trust by skipping the rightmost N trusted proxies
93
- const clientIPIndex = Math.max(0, forwardedIPs.length - trustProxyDepth - 1);
94
- return forwardedIPs[clientIPIndex];
95
- }
96
- //# sourceMappingURL=ipExtractor.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ipExtractor.js","sourceRoot":"","sources":["../../src/server/ipExtractor.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,UAAU,eAAe,CAAC,GAAyB,EAAE,kBAA0B,CAAC;IAClF,+DAA+D;IAC/D,IAAI,eAAe,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,GAAG,CAAC,MAAM,CAAC,aAAa,IAAI,SAAS,CAAC;IACjD,CAAC;IAED,6BAA6B;IAC7B,MAAM,YAAY,GAAG,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACpD,IAAI,CAAC,YAAY,EAAE,CAAC;QAChB,4DAA4D;QAC5D,OAAO,GAAG,CAAC,MAAM,CAAC,aAAa,IAAI,SAAS,CAAC;IACjD,CAAC;IAED,qEAAqE;IACrE,MAAM,YAAY,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;SACrF,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;SACtB,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAEnC,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,wDAAwD;QACxD,OAAO,GAAG,CAAC,MAAM,CAAC,aAAa,IAAI,SAAS,CAAC;IACjD,CAAC;IAED,iDAAiD;IACjD,kDAAkD;IAClD,qDAAqD;IACrD,6EAA6E;IAE7E,IAAI,YAAY,CAAC,MAAM,GAAG,eAAe,EAAE,CAAC;QACxC,wEAAwE;QACxE,4CAA4C;QAC5C,OAAO,GAAG,CAAC,MAAM,CAAC,aAAa,IAAI,SAAS,CAAC;IACjD,CAAC;IAED,4CAA4C;IAC5C,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC;AAC3B,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,wBAAwB,CAAC,GAAyB,EAAE,kBAA0B,CAAC;IAC3F,IAAI,eAAe,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,GAAG,CAAC,MAAM,CAAC,aAAa,IAAI,SAAS,CAAC;IACjD,CAAC;IAED,MAAM,YAAY,GAAG,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACpD,IAAI,CAAC,YAAY,EAAE,CAAC;QAChB,OAAO,GAAG,CAAC,MAAM,CAAC,aAAa,IAAI,SAAS,CAAC;IACjD,CAAC;IAED,MAAM,YAAY,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;SACrF,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;SACtB,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAEnC,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,GAAG,CAAC,MAAM,CAAC,aAAa,IAAI,SAAS,CAAC;IACjD,CAAC;IAED,0EAA0E;IAC1E,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,CAAC,MAAM,GAAG,eAAe,GAAG,CAAC,CAAC,CAAC;IAC7E,OAAO,YAAY,CAAC,aAAa,CAAC,CAAC;AACvC,CAAC"}
@@ -1,4 +0,0 @@
1
- export declare function getRequestPath(url: string | undefined): string;
2
- export declare function isDevInternalOrAssetRequest(url: string | undefined): boolean;
3
- export declare function resolveDirectStaticAssetPath(staticDir: string, url: string | undefined): string | null;
4
- //# sourceMappingURL=requestRouting.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"requestRouting.d.ts","sourceRoot":"","sources":["../../src/server/requestRouting.ts"],"names":[],"mappings":"AAsCA,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAE9D;AAED,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAS5E;AAED,wBAAgB,4BAA4B,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAwBtG"}
@@ -1,67 +0,0 @@
1
- import fs from "fs";
2
- import path from "path";
3
- const STATIC_ASSET_EXTENSIONS = new Set([
4
- ".js",
5
- ".mjs",
6
- ".cjs",
7
- ".ts",
8
- ".tsx",
9
- ".jsx",
10
- ".css",
11
- ".map",
12
- ".json",
13
- ".png",
14
- ".jpg",
15
- ".jpeg",
16
- ".gif",
17
- ".svg",
18
- ".ico",
19
- ".webp",
20
- ".avif",
21
- ".woff",
22
- ".woff2",
23
- ".ttf",
24
- ".eot",
25
- ".otf",
26
- ".mp4",
27
- ".webm",
28
- ".ogg",
29
- ".mp3",
30
- ".wav",
31
- ".txt",
32
- ".xml",
33
- ".wasm",
34
- ]);
35
- const DEV_INTERNAL_PREFIXES = ["/@vite", "/@fs/", "/@id/", "/__vite", "/src/", "/node_modules/"];
36
- export function getRequestPath(url) {
37
- return (url || "/").split("?")[0] || "/";
38
- }
39
- export function isDevInternalOrAssetRequest(url) {
40
- const requestPath = getRequestPath(url);
41
- if (DEV_INTERNAL_PREFIXES.some((prefix) => requestPath.startsWith(prefix))) {
42
- return true;
43
- }
44
- const extension = path.extname(requestPath).toLowerCase();
45
- return extension.length > 0 && STATIC_ASSET_EXTENSIONS.has(extension);
46
- }
47
- export function resolveDirectStaticAssetPath(staticDir, url) {
48
- const requestPath = getRequestPath(url);
49
- const extension = path.extname(requestPath).toLowerCase();
50
- if (!extension) {
51
- return null;
52
- }
53
- const resolvedStaticDir = path.resolve(staticDir);
54
- const candidatePath = path.resolve(staticDir, "." + requestPath);
55
- if (!candidatePath.startsWith(resolvedStaticDir + path.sep) && candidatePath !== resolvedStaticDir) {
56
- return null;
57
- }
58
- if (!fs.existsSync(candidatePath)) {
59
- return null;
60
- }
61
- const stat = fs.statSync(candidatePath);
62
- if (!stat.isFile()) {
63
- return null;
64
- }
65
- return candidatePath;
66
- }
67
- //# sourceMappingURL=requestRouting.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"requestRouting.js","sourceRoot":"","sources":["../../src/server/requestRouting.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,uBAAuB,GAAG,IAAI,GAAG,CAAC;IACpC,KAAK;IACL,MAAM;IACN,MAAM;IACN,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,OAAO;IACP,OAAO;IACP,QAAQ;IACR,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;CACV,CAAC,CAAC;AAEH,MAAM,qBAAqB,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC;AAEjG,MAAM,UAAU,cAAc,CAAC,GAAuB;IAClD,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,GAAuB;IAC/D,MAAM,WAAW,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IAExC,IAAI,qBAAqB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QACzE,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,CAAC;IAC1D,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,uBAAuB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,SAAiB,EAAE,GAAuB;IACnF,MAAM,WAAW,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACxC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,CAAC;IAE1D,IAAI,CAAC,SAAS,EAAE,CAAC;QACb,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,MAAM,iBAAiB,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAClD,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,GAAG,WAAW,CAAC,CAAC;IACjE,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,aAAa,KAAK,iBAAiB,EAAE,CAAC;QACjG,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;IACxC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;QACjB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,OAAO,aAAa,CAAC;AACzB,CAAC","sourcesContent":["import fs from \"fs\";\nimport path from \"path\";\n\nconst STATIC_ASSET_EXTENSIONS = new Set([\n \".js\",\n \".mjs\",\n \".cjs\",\n \".ts\",\n \".tsx\",\n \".jsx\",\n \".css\",\n \".map\",\n \".json\",\n \".png\",\n \".jpg\",\n \".jpeg\",\n \".gif\",\n \".svg\",\n \".ico\",\n \".webp\",\n \".avif\",\n \".woff\",\n \".woff2\",\n \".ttf\",\n \".eot\",\n \".otf\",\n \".mp4\",\n \".webm\",\n \".ogg\",\n \".mp3\",\n \".wav\",\n \".txt\",\n \".xml\",\n \".wasm\",\n]);\n\nconst DEV_INTERNAL_PREFIXES = [\"/@vite\", \"/@fs/\", \"/@id/\", \"/__vite\", \"/src/\", \"/node_modules/\"];\n\nexport function getRequestPath(url: string | undefined): string {\n return (url || \"/\").split(\"?\")[0] || \"/\";\n}\n\nexport function isDevInternalOrAssetRequest(url: string | undefined): boolean {\n const requestPath = getRequestPath(url);\n\n if (DEV_INTERNAL_PREFIXES.some((prefix) => requestPath.startsWith(prefix))) {\n return true;\n }\n\n const extension = path.extname(requestPath).toLowerCase();\n return extension.length > 0 && STATIC_ASSET_EXTENSIONS.has(extension);\n}\n\nexport function resolveDirectStaticAssetPath(staticDir: string, url: string | undefined): string | null {\n const requestPath = getRequestPath(url);\n const extension = path.extname(requestPath).toLowerCase();\n\n if (!extension) {\n return null;\n }\n\n const resolvedStaticDir = path.resolve(staticDir);\n const candidatePath = path.resolve(staticDir, \".\" + requestPath);\n if (!candidatePath.startsWith(resolvedStaticDir + path.sep) && candidatePath !== resolvedStaticDir) {\n return null;\n }\n\n if (!fs.existsSync(candidatePath)) {\n return null;\n }\n\n const stat = fs.statSync(candidatePath);\n if (!stat.isFile()) {\n return null;\n }\n\n return candidatePath;\n}\n"]}
@@ -1 +0,0 @@
1
- //# sourceMappingURL=deepEqual.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"deepEqual.d.ts","sourceRoot":"","sources":["../../src/utils/deepEqual.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- "use strict";
2
- //# sourceMappingURL=deepEqual.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"deepEqual.js","sourceRoot":"","sources":["../../src/utils/deepEqual.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export declare function formatError(err: unknown): string;
2
- //# sourceMappingURL=formatError.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"formatError.d.ts","sourceRoot":"","sources":["../../src/utils/formatError.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAgBhD"}
@@ -1,18 +0,0 @@
1
- export function formatError(err) {
2
- console.log("🚀 ~ formatError ~ err:", err);
3
- if (err instanceof Error) {
4
- return err.message;
5
- }
6
- if (typeof err === "object" && err !== null) {
7
- if ("message" in err) {
8
- return String(err.message);
9
- }
10
- // Format Record<string, string> errors
11
- return JSON.stringify(err, null, 2);
12
- }
13
- if (typeof err === "string") {
14
- return err;
15
- }
16
- return String(err);
17
- }
18
- //# sourceMappingURL=formatError.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"formatError.js","sourceRoot":"","sources":["../../src/utils/formatError.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,WAAW,CAAC,GAAY;IACpC,OAAO,CAAC,GAAG,CAAC,yBAAyB,EAAE,GAAG,CAAC,CAAC;IAC5C,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;QACvB,OAAO,GAAG,CAAC,OAAO,CAAC;IACvB,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QAC1C,IAAI,SAAS,IAAI,GAAG,EAAE,CAAC;YACnB,OAAO,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC;QACD,uCAAuC;QACvC,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACxC,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC1B,OAAO,GAAG,CAAC;IACf,CAAC;IACD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;AACvB,CAAC"}