akanjs 3.0.0-beta.23 → 3.0.0-beta.25

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 (111) hide show
  1. package/client/csrTypes.ts +27 -1
  2. package/client/native.ts +3 -0
  3. package/client/route/RouteDefinition.ts +41 -1
  4. package/package.json +16 -6
  5. package/server/SSR_MEMORY_DIAGNOSIS.md +2 -2
  6. package/server/akanApp.ts +3 -3
  7. package/server/akanServer.ts +7 -1
  8. package/server/artifact/builderRpc.ts +18 -2
  9. package/server/artifact/ipcTypes.ts +54 -3
  10. package/server/artifact/routeClientCache.ts +128 -29
  11. package/server/hmr/clientScript.ts +157 -79
  12. package/server/hmr/csrDevManifest.ts +42 -0
  13. package/server/hmr/csrDevRuntime.ts +690 -0
  14. package/server/hmr/csrDevShell.ts +170 -0
  15. package/server/hmr/csrDevSourceMap.ts +142 -0
  16. package/server/hmr/devHmrController.ts +217 -129
  17. package/server/hmr/runtimeMetadataFile.ts +17 -0
  18. package/server/hmr/ssrDevShim.ts +106 -0
  19. package/server/hmr/ssrUpdateQueue.ts +111 -0
  20. package/server/hmr/wsHub.ts +48 -7
  21. package/server/routing/apiRouter.ts +14 -0
  22. package/server/rscWorker.tsx +5 -1
  23. package/server/rscWorkerHost.ts +122 -44
  24. package/server/systemPageDocument.tsx +6 -0
  25. package/server/types.tsx +6 -0
  26. package/server/vendor/react-dom.ts +1 -0
  27. package/server/vendor/react-refresh-runtime.ts +13 -1
  28. package/server/vendor/react.ts +2 -0
  29. package/server/webRouter.ts +63 -4
  30. package/store/agent/ScreenTarget.ts +1 -2
  31. package/store/agent/StoreSurfaceSource.ts +3 -1
  32. package/store/storeInstance.ts +28 -21
  33. package/types/client/csrTypes.d.ts +22 -1
  34. package/types/client/native.d.ts +1 -0
  35. package/types/client/route/RouteDefinition.d.ts +14 -0
  36. package/types/server/artifact/builderRpc.d.ts +4 -2
  37. package/types/server/artifact/ipcTypes.d.ts +56 -2
  38. package/types/server/artifact/routeClientCache.d.ts +9 -2
  39. package/types/server/hmr/csrDevManifest.d.ts +33 -0
  40. package/types/server/hmr/csrDevRuntime.d.ts +105 -0
  41. package/types/server/hmr/csrDevShell.d.ts +22 -0
  42. package/types/server/hmr/csrDevSourceMap.d.ts +17 -0
  43. package/types/server/hmr/devHmrController.d.ts +10 -4
  44. package/types/server/hmr/runtimeMetadataFile.d.ts +1 -0
  45. package/types/server/hmr/ssrDevShim.d.ts +7 -0
  46. package/types/server/hmr/ssrUpdateQueue.d.ts +23 -0
  47. package/types/server/hmr/wsHub.d.ts +27 -7
  48. package/types/server/routing/apiRouter.d.ts +9 -0
  49. package/types/server/rscWorkerHost.d.ts +13 -2
  50. package/types/server/systemPageDocument.d.ts +2 -0
  51. package/types/server/types.d.ts +6 -0
  52. package/types/server/vendor/react-dom.d.ts +1 -1
  53. package/types/server/vendor/react-refresh-runtime.d.ts +1 -1
  54. package/types/server/vendor/react.d.ts +1 -1
  55. package/types/server/webRouter.d.ts +4 -0
  56. package/types/store/storeInstance.d.ts +4 -3
  57. package/types/ui/System/Client.d.ts +5 -3
  58. package/types/vendor/@akanjs/native/plugins/app/src/index.d.ts +17 -0
  59. package/types/vendor/@akanjs/native/plugins/app-state/src/index.d.ts +6 -0
  60. package/types/vendor/use-agentic/AgentActivity.d.ts +11 -0
  61. package/types/vendor/use-agentic/AgentGate.d.ts +10 -0
  62. package/types/vendor/use-agentic/AgenticSurface.d.ts +15 -5
  63. package/types/vendor/use-agentic/index.d.ts +2 -0
  64. package/types/vendor/use-agentic/surfaceContext.d.ts +3 -0
  65. package/types/webkit/CsrRouteTable.d.ts +32 -0
  66. package/types/webkit/CsrStack.d.ts +45 -0
  67. package/types/webkit/RenderLayer.d.ts +2 -2
  68. package/types/webkit/bootCsr.d.ts +7 -8
  69. package/types/webkit/index.d.ts +4 -1
  70. package/types/webkit/nativeNavigation.d.ts +13 -0
  71. package/types/webkit/useCsrValues.d.ts +6 -4
  72. package/types/webkit/useFetch.d.ts +3 -1
  73. package/types/webkit/useHistory.d.ts +5 -1
  74. package/types/webkit/usePageActivity.d.ts +2 -0
  75. package/types/webkit/usePageFocusEffect.d.ts +7 -0
  76. package/types/webkit/usePageLocation.d.ts +13 -0
  77. package/ui/Data/Dashboard.tsx +2 -2
  78. package/ui/Data/ListContainer.tsx +2 -2
  79. package/ui/Layout/BottomInset.tsx +1 -1
  80. package/ui/Layout/Navbar.tsx +1 -1
  81. package/ui/Layout/TopInset.tsx +4 -3
  82. package/ui/System/CSR.tsx +40 -79
  83. package/ui/System/Client.tsx +28 -13
  84. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeActivity.kt +53 -9
  85. package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativePlugin.kt +16 -0
  86. package/vendor/@akanjs/native/plugins/app/android/AppPlugin.kt +20 -0
  87. package/vendor/@akanjs/native/plugins/app/native-plugin.json +4 -4
  88. package/vendor/@akanjs/native/plugins/app/src/desktop.ts +3 -0
  89. package/vendor/@akanjs/native/plugins/app/src/index.ts +14 -2
  90. package/vendor/@akanjs/native/plugins/app-state/android/AppStatePlugin.kt +38 -2
  91. package/vendor/@akanjs/native/plugins/app-state/ios/AppStatePlugin.swift +19 -0
  92. package/vendor/@akanjs/native/plugins/app-state/native-plugin.json +1 -1
  93. package/vendor/@akanjs/native/plugins/app-state/src/index.ts +6 -1
  94. package/vendor/use-agentic/AgentActivity.tsx +26 -0
  95. package/vendor/use-agentic/AgentGate.ts +25 -0
  96. package/vendor/use-agentic/AgenticSurface.ts +92 -34
  97. package/vendor/use-agentic/index.ts +2 -0
  98. package/vendor/use-agentic/surfaceContext.ts +3 -0
  99. package/webkit/CsrRouteTable.ts +298 -0
  100. package/webkit/CsrStack.ts +98 -0
  101. package/webkit/RenderLayer.tsx +30 -8
  102. package/webkit/bootCsr.tsx +13 -217
  103. package/webkit/index.ts +4 -1
  104. package/webkit/nativeNavigation.ts +78 -5
  105. package/webkit/useCsrValues.ts +118 -22
  106. package/webkit/useFetch.ts +9 -2
  107. package/webkit/useHistory.ts +23 -6
  108. package/webkit/useLocation.ts +6 -3
  109. package/webkit/usePageActivity.ts +6 -0
  110. package/webkit/usePageFocusEffect.ts +13 -0
  111. package/webkit/usePageLocation.ts +17 -0
@@ -1,3 +1,4 @@
1
+ import { SSR_DEV_ROUTE_PREFIX } from "./csrDevManifest";
1
2
  import { isSyncNavigationEnabled } from "./wsHub";
2
3
 
3
4
  export const HMR_CLIENT_SCRIPT = `(function(){
@@ -5,15 +6,16 @@ export const HMR_CLIENT_SCRIPT = `(function(){
5
6
  self.__AKAN_HMR_INSTALLED__ = true;
6
7
  var syncNavigationEnabled = ${JSON.stringify(isSyncNavigationEnabled())};
7
8
  var syncNavigationClientId = Math.random().toString(36).slice(2) + Date.now().toString(36);
9
+ var clientKind = self.__AKAN_HMR_CLIENT__ === "csr" ? "csr" : "ssr";
10
+ var systemPage = !!self.__AKAN_HMR_SYSTEM_PAGE__;
8
11
  var proto = location.protocol === "https:" ? "wss:" : "ws:";
9
- var url = proto + "//" + location.host + "/_akan/hmr";
12
+ var url = proto + "//" + location.host + "/_akan/hmr" + (clientKind === "csr" ? "?client=csr" : "");
10
13
  var attempts = 0;
11
14
  var socket = null;
12
15
  var lastBuildId = null;
13
16
  var refreshRuntimePromise = null;
14
17
  var refreshRuntime = null;
15
18
  var pendingRefreshRegistrations = [];
16
- var refreshQueue = Promise.resolve();
17
19
  var overlayEl = null;
18
20
  var overlayLabelEl = null;
19
21
  var overlayDetailEl = null;
@@ -23,7 +25,7 @@ export const HMR_CLIENT_SCRIPT = `(function(){
23
25
  var overlayNextToken = 1;
24
26
  var overlayJobs = {};
25
27
  var buildErrorStates = {};
26
- self.__AKAN_HMR_PHASE__ = null;
28
+ var traces = self.__AKAN_HMR_TRACES__ = self.__AKAN_HMR_TRACES__ || [];
27
29
  self.__AKAN_DEV_SYNC_NAVIGATION__ = function(href, kind){
28
30
  if (self.__AKAN_DEV_SYNC_NAVIGATION_APPLYING__ || !syncNavigationEnabled || !socket || socket.readyState !== WebSocket.OPEN) return;
29
31
  try {
@@ -43,7 +45,7 @@ export const HMR_CLIENT_SCRIPT = `(function(){
43
45
  else pendingRefreshRegistrations.push([type, id]);
44
46
  };
45
47
  self.$RefreshSig$ = self.$RefreshSig$ || function(){ return function(type){ return type; }; };
46
- ensureRefreshRuntime().catch(function(err){
48
+ if (clientKind === "ssr" && !systemPage) ensureRefreshRuntime().catch(function(err){
47
49
  console.warn("[akan-hmr] React Refresh runtime preload failed", err);
48
50
  });
49
51
 
@@ -56,11 +58,41 @@ export const HMR_CLIENT_SCRIPT = `(function(){
56
58
  try { msg = JSON.parse(ev.data); } catch (e){ return; }
57
59
  if (!msg || typeof msg.type !== "string") return;
58
60
  if (msg.type === "hello") {
59
- if (lastBuildId !== null && msg.buildId !== lastBuildId) {
60
- location.reload();
61
+ var dropped = Array.isArray(msg.failingPhases) && dropBuildErrorsExcept(msg.failingPhases);
62
+ if (dropped && systemPage) {
63
+ reloadForUpdate("the build that failed to render this page recovered");
64
+ return;
65
+ }
66
+ if (clientKind === "csr") {
67
+ if (csrGenerationMoved(msg.csrGeneration)) reloadForUpdate("missed a CSR update while disconnected");
68
+ return;
69
+ }
70
+ if (systemPage) {
71
+ if (lastBuildId !== null && msg.buildId !== lastBuildId) location.reload();
72
+ lastBuildId = msg.buildId;
73
+ return;
74
+ }
75
+ if (ssrRegistryReplaced(msg.ssrEpoch)) {
76
+ reloadForUpdate("the dev server rebuilt the SSR registry while this tab held the previous one");
77
+ return;
78
+ }
79
+ if (ssrRegistryGone(msg.ssrEpoch)) {
80
+ reloadForUpdate("the dev server has no SSR registry yet: a new session or a config restart is building one");
61
81
  return;
62
82
  }
63
- lastBuildId = msg.buildId;
83
+ if (ssrBootFailedBefore(msg.ssrGeneration, msg.ssrEpoch)) {
84
+ reloadForUpdate("the SSR registry this tab failed to load was rebuilt");
85
+ return;
86
+ }
87
+ if (typeof msg.ssrGeneration === "number") self.__AKAN_SSR_HELLO_GENERATION__ = msg.ssrGeneration;
88
+ var sameRegistry = holdsSsrRegistry(msg.ssrEpoch);
89
+ if (sameRegistry) catchUpSsrRegistry(msg.ssrGeneration);
90
+ if (lastBuildId === null || msg.buildId === lastBuildId) {
91
+ lastBuildId = msg.buildId;
92
+ return;
93
+ }
94
+ if (sameRegistry) refreshRsc({ buildId: msg.buildId });
95
+ else location.reload();
64
96
  return;
65
97
  }
66
98
  if (msg.type === "reload") {
@@ -73,8 +105,12 @@ export const HMR_CLIENT_SCRIPT = `(function(){
73
105
  refreshRsc(msg);
74
106
  return;
75
107
  }
76
- if (msg.type === "client-refresh") {
77
- refreshClient(msg);
108
+ if (msg.type === "csr-update") {
109
+ applyCsrUpdate(msg);
110
+ return;
111
+ }
112
+ if (msg.type === "ssr-update") {
113
+ applySsrUpdate(msg);
78
114
  return;
79
115
  }
80
116
  if (msg.type === "css-update") {
@@ -112,6 +148,81 @@ export const HMR_CLIENT_SCRIPT = `(function(){
112
148
  socket.addEventListener("error", function(){ try { socket && socket.close(); } catch(e){} });
113
149
  }
114
150
 
151
+ function csrGenerationMoved(generation){
152
+ if (typeof generation !== "number") return false;
153
+ var current = self.__akan ? self.__akan.generation : self.__AKAN_CSR_GENERATION__;
154
+ return typeof current === "number" && current !== generation;
155
+ }
156
+
157
+ function reloadForUpdate(reason){
158
+ console.warn("[akan-hmr] reloading the page: " + reason);
159
+ beginHmrOverlay("Reloading...", true);
160
+ setTimeout(function(){ location.reload(); }, 30);
161
+ }
162
+
163
+ function recordTrace(kind, msg, receivedAt, appliedAt){
164
+ traces.push({ kind: kind, generation: msg.generation, trace: msg.trace || null, receivedAt: receivedAt, appliedAt: appliedAt });
165
+ if (traces.length > 64) traces.shift();
166
+ }
167
+
168
+ function applyCsrUpdate(msg){
169
+ recordTrace("csr", msg, Date.now(), null);
170
+ if (msg.reload || !self.__akan || typeof self.__akan.hot !== "function") {
171
+ reloadForUpdate(msg.reason || "the CSR bundle was rebuilt");
172
+ return;
173
+ }
174
+ self.__akan.hot(msg);
175
+ }
176
+
177
+ function ssrRegistryReplaced(epoch){
178
+ var own = self.__AKAN_SSR_EPOCH__;
179
+ return typeof epoch === "number" && typeof own === "number" && own !== epoch;
180
+ }
181
+
182
+ function holdsSsrRegistry(epoch){
183
+ return typeof epoch === "number" && self.__AKAN_SSR_EPOCH__ === epoch;
184
+ }
185
+
186
+ function ssrRegistryGone(epoch){
187
+ return typeof self.__AKAN_SSR_EPOCH__ === "number" && typeof epoch !== "number";
188
+ }
189
+
190
+ function catchUpSsrRegistry(generation){
191
+ var registry = self.__akan;
192
+ if (typeof generation !== "number" || !registry || typeof registry.catchUp !== "function") return;
193
+ if (registry.inspect().target < generation) registry.catchUp(generation, ${JSON.stringify(SSR_DEV_ROUTE_PREFIX)});
194
+ }
195
+
196
+ function ssrBootFailedBefore(generation, epoch){
197
+ var failed = self.__AKAN_SSR_BOOT_FAILED__;
198
+ if (!failed || typeof generation !== "number") return false;
199
+ return generation > failed.generation || (typeof epoch === "number" && typeof failed.epoch === "number" && epoch !== failed.epoch);
200
+ }
201
+
202
+ function applySsrUpdate(msg){
203
+ recordTrace("ssr", msg, Date.now(), null);
204
+ if (systemPage) {
205
+ reloadForUpdate("a save changed the client code of the page that failed to render");
206
+ return;
207
+ }
208
+ if (ssrBootFailedBefore(msg.generation)) {
209
+ reloadForUpdate("the SSR registry this tab failed to load was updated");
210
+ return;
211
+ }
212
+ var startFailed = !!(self.__akan && typeof self.__akan.inspect === "function" && self.__akan.inspect().failed);
213
+ if (msg.reload && self.__akan && (!(msg.generation <= self.__akan.generation) || (startFailed && msg.generation >= self.__akan.generation))) {
214
+ reloadForUpdate(msg.reason || "the SSR registry was rebuilt");
215
+ return;
216
+ }
217
+ if (self.__akan && typeof self.__akan.hot === "function") {
218
+ self.__akan.hot(msg);
219
+ return;
220
+ }
221
+ var early = self.__AKAN_SSR_EARLY_UPDATES__ = self.__AKAN_SSR_EARLY_UPDATES__ || [];
222
+ early.push(msg);
223
+ if (early.length > 64) early.shift();
224
+ }
225
+
115
226
  function schedule(){
116
227
  attempts = Math.min(attempts + 1, 6);
117
228
  var delay = Math.min(30000, 250 * Math.pow(2, attempts - 1));
@@ -230,6 +341,10 @@ export const HMR_CLIENT_SCRIPT = `(function(){
230
341
  showBuildErrorOverlay(msg);
231
342
  return;
232
343
  }
344
+ if (msg.status === "ok" && systemPage) {
345
+ reloadForUpdate("the build that failed to render this page recovered");
346
+ return;
347
+ }
233
348
  if (msg.status === "ok") clearBuildErrorOverlay(msg);
234
349
  }
235
350
 
@@ -272,9 +387,25 @@ export const HMR_CLIENT_SCRIPT = `(function(){
272
387
  var current = buildErrorStates[phase];
273
388
  if (!current) return;
274
389
  var generation = typeof msg.generation === "number" ? msg.generation : 0;
275
- var recovered = phase === "backend" ? generation >= current.generation : generation > current.generation;
390
+ var sameGeneration = phase === "backend" || phase === "scan" || phase === "route";
391
+ var recovered = sameGeneration ? generation >= current.generation : generation > current.generation;
276
392
  if (!recovered) return;
277
393
  delete buildErrorStates[phase];
394
+ showBuildRecovered(msg);
395
+ }
396
+
397
+ function dropBuildErrorsExcept(failing){
398
+ var dropped = false;
399
+ for (var phase in buildErrorStates) {
400
+ if (failing.indexOf(phase) >= 0) continue;
401
+ delete buildErrorStates[phase];
402
+ dropped = true;
403
+ }
404
+ if (dropped && !systemPage) showBuildRecovered({});
405
+ return dropped;
406
+ }
407
+
408
+ function showBuildRecovered(msg){
278
409
  if (hasBuildErrors()) {
279
410
  renderBuildErrorOverlay();
280
411
  return;
@@ -332,6 +463,21 @@ export const HMR_CLIENT_SCRIPT = `(function(){
332
463
  }
333
464
 
334
465
  function refreshRsc(msg){
466
+ var receivedAt = Date.now();
467
+ var refresh = function(){ doRefreshRsc(msg, receivedAt); };
468
+ var settle = function(){
469
+ return self.__akan && typeof self.__akan.whenSettled === "function" ? self.__akan.whenSettled() : null;
470
+ };
471
+ var booting = self.__AKAN_SSR_BOOT__;
472
+ var settled = booting ? Promise.resolve(booting).then(settle, function(){ return null; }) : settle();
473
+ if (!settled) {
474
+ refresh();
475
+ return;
476
+ }
477
+ settled.then(refresh, refresh);
478
+ }
479
+
480
+ function doRefreshRsc(msg, receivedAt){
335
481
  var started = performance.now();
336
482
  var overlayToken = beginHmrOverlay("Refreshing page...");
337
483
  try { self.__AKAN_RSC_CLEAR_CACHE__ && self.__AKAN_RSC_CLEAR_CACHE__(); } catch(e){}
@@ -343,6 +489,7 @@ export const HMR_CLIENT_SCRIPT = `(function(){
343
489
  }
344
490
  Promise.resolve(self.__AKAN_RSC_REFRESH__({ buildId: msg.buildId })).then(function(){
345
491
  lastBuildId = msg.buildId;
492
+ recordTrace("rsc-refresh", msg, receivedAt, Date.now());
346
493
  endHmrOverlay(overlayToken);
347
494
  console.debug && console.debug("[akan-hmr] RSC refreshed", {
348
495
  buildId: msg.buildId,
@@ -379,75 +526,6 @@ export const HMR_CLIENT_SCRIPT = `(function(){
379
526
  return refreshRuntimePromise;
380
527
  }
381
528
 
382
- function refreshClient(msg){
383
- refreshQueue = refreshQueue.then(function(){ return doRefreshClient(msg); }, function(){ return doRefreshClient(msg); });
384
- }
385
-
386
- function setHmrPhase(phase){
387
- self.__AKAN_HMR_PHASE__ = phase;
388
- }
389
-
390
- function doRefreshClient(msg){
391
- var started = performance.now();
392
- var metadataAt = started;
393
- var importAt = started;
394
- var refreshAt = started;
395
- var overlayToken = beginHmrOverlay("Updating...");
396
- var fallbackToRsc = false;
397
- return ensureRefreshRuntime().then(function(runtime){
398
- setHmrOverlayLabel(overlayToken, "Fetching update...");
399
- var endpoint = new URL("/_akan/hmr/client-refresh", location.origin);
400
- endpoint.searchParams.set("url", location.href);
401
- if (msg.buildId != null) endpoint.searchParams.set("buildId", String(msg.buildId));
402
- return fetch(endpoint, { credentials: "same-origin", cache: "no-store" })
403
- .then(function(res){
404
- if (!res.ok) throw new Error("client-refresh metadata failed " + res.status + " " + res.statusText);
405
- return res.json();
406
- })
407
- .then(function(info){
408
- metadataAt = performance.now();
409
- var chunks = Array.isArray(info.chunks) ? info.chunks : [];
410
- if (chunks.length === 0) throw new Error("no client chunks returned");
411
- setHmrPhase("refresh-import");
412
- setHmrOverlayLabel(overlayToken, "Importing update...");
413
- return Promise.all(chunks.map(function(chunk){ return import(chunk); })).then(function(){
414
- importAt = performance.now();
415
- setHmrPhase("react-refresh");
416
- setHmrOverlayLabel(overlayToken, "Applying update...");
417
- try {
418
- runtime.performReactRefresh();
419
- } finally {
420
- setHmrPhase(null);
421
- }
422
- refreshAt = performance.now();
423
- lastBuildId = msg.buildId;
424
- console.debug && console.debug("[akan-hmr] React Fast Refresh applied", {
425
- buildId: msg.buildId,
426
- generation: msg.generation,
427
- chunks: chunks.length,
428
- routeIds: info.routeIds || msg.routeIds,
429
- changedFiles: msg.changedFiles && msg.changedFiles.length,
430
- metadataMs: Math.round(metadataAt - started),
431
- importMs: Math.round(importAt - metadataAt),
432
- refreshMs: Math.round(refreshAt - importAt),
433
- durationMs: Math.round(refreshAt - started)
434
- });
435
- endHmrOverlay(overlayToken);
436
- }, function(err){
437
- setHmrPhase(null);
438
- throw err;
439
- });
440
- });
441
- }).catch(function(err){
442
- console.warn("[akan-hmr] React Fast Refresh failed, falling back to RSC refresh", err);
443
- fallbackToRsc = true;
444
- endHmrOverlay(overlayToken);
445
- refreshRsc(msg);
446
- }).finally(function(){
447
- if (!fallbackToRsc) endHmrOverlay(overlayToken);
448
- });
449
- }
450
-
451
529
  function swapCss(href){
452
530
  var overlayToken = beginHmrOverlay("Updating styles...");
453
531
  var link = document.createElement("link");
@@ -0,0 +1,42 @@
1
+ export const CSR_DEV_DIRNAME = "csr-dev";
2
+ export const CSR_DEV_ROUTE_PREFIX = "/_akan/csr-dev/";
3
+ export const CSR_DEV_APP_FILE = "app.js";
4
+ export const CSR_DEV_MANIFEST_FILE = "manifest.json";
5
+ /** Present only while the resident builder patches: a builder that dies holding it takes the patcher off. */
6
+ export const CSR_DEV_PATCHING_MARKER = ".patching";
7
+ /** Patches kept on disk behind the newest, and as many as a reconnecting tab catches up on before it reloads instead. */
8
+ export const CSR_DEV_KEPT_PATCHES = 40;
9
+
10
+ export const SSR_DEV_DIRNAME = "ssr-dev";
11
+ export const SSR_DEV_ROUTE_PREFIX = "/_akan/ssr-dev/";
12
+ /** The one chunk every SSR registry row names: loading it boots the registry in the tab. */
13
+ export const SSR_DEV_CHUNK = "ssr-dev";
14
+ /** Marks a row id as a registry module, so the dev shim tells it from the runtime rows that stay chunk URLs. */
15
+ export const SSR_DEV_ID_PREFIX = "ssr-dev:";
16
+
17
+ export type DevCsrMode = "registry" | "artifact";
18
+
19
+ export interface CsrDevManifest {
20
+ version: 1;
21
+ generation: number;
22
+ /** The generation `app.js` holds; a patch is announced before `app.js` catches up, so it may trail `generation`. */
23
+ appGeneration?: number;
24
+ vendorFile: string;
25
+ entries: Record<string, string>;
26
+ /** When the registry was last built whole: a tab from an earlier registry must reload, whatever its generation. */
27
+ epoch?: number;
28
+ }
29
+
30
+ export const appGenerationOf = (manifest: CsrDevManifest): number => manifest.appGeneration ?? manifest.generation;
31
+
32
+ /** Where each module's generated code starts in a combined file (`app.js`, a patch), for its source map. */
33
+ export interface CsrDevLayout {
34
+ lineCount: number;
35
+ modules: [id: string, line: number][];
36
+ }
37
+
38
+ export const csrDevModuleFile = (id: string, extension: ".js" | ".js.map") =>
39
+ `modules/${Bun.hash(id).toString(36)}${extension}`;
40
+
41
+ export const resolveDevCsrMode = (env: Record<string, string | undefined> = process.env): DevCsrMode =>
42
+ env.AKAN_DEV_CSR === "artifact" ? "artifact" : "registry";