akanjs 2.3.1-rc.2 → 2.3.1-rc.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akanjs",
3
- "version": "2.3.1-rc.2",
3
+ "version": "2.3.1-rc.4",
4
4
  "sourceType": "module",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -1,5 +1,4 @@
1
1
  import { createElement, type ReactNode, startTransition, type Usable, use, useLayoutEffect, useState } from "react";
2
- import { flushSync } from "react-dom";
3
2
  import { hydrateRoot } from "react-dom/client";
4
3
  import { createFromReadableStream } from "react-server-dom-webpack/client.browser";
5
4
  import {
@@ -81,7 +80,6 @@ type RscFetchResult =
81
80
  }
82
81
  | { type: "redirected"; status?: number };
83
82
  const MAX_RSC_CACHE_ENTRIES = 32;
84
- const AKAN_RSC_NAVIGATION_COMMITTED_EVENT = "akan:rsc-navigation-committed";
85
83
  let documentNavigationFallbackInFlight = false;
86
84
 
87
85
  class RscRedirectNavigationStarted extends Error {
@@ -152,10 +150,6 @@ function hardNavigateAfterRscFailure(target: string, replace = false, error?: un
152
150
  else window.location.assign(target);
153
151
  }
154
152
 
155
- function dispatchRscNavigationCommitted(href: string): void {
156
- window.dispatchEvent(new CustomEvent(AKAN_RSC_NAVIGATION_COMMITTED_EVENT, { detail: { href } }));
157
- }
158
-
159
153
  function navigateAfterRscRedirect(target: string, replace = true): void {
160
154
  const error = new RscRedirectNavigationStarted(target);
161
155
  const navigate = globalThis.__AKAN_RSC_NAVIGATE__;
@@ -174,14 +168,12 @@ function commitRscPatchNavigation({
174
168
  replace,
175
169
  scrollToTop,
176
170
  bumpScrollToTop,
177
- onCommitted,
178
171
  }: {
179
172
  target: string;
180
173
  patch: Extract<RscFetchResult, { type: "patched" }>;
181
174
  replace?: boolean;
182
175
  scrollToTop?: boolean;
183
176
  bumpScrollToTop?: () => void;
184
- onCommitted?: () => void;
185
177
  }): boolean {
186
178
  const patchThenable = patch.patchedNode.thenable;
187
179
  if (!patchThenable) throw new Error("[rscClient] validated RSC patch is missing a thenable");
@@ -190,7 +182,7 @@ function commitRscPatchNavigation({
190
182
 
191
183
  let outletCommitted = false;
192
184
  let headApplied = false;
193
- flushSync(() => {
185
+ startTransition(() => {
194
186
  try {
195
187
  headApplied = commitPreparedAkanHeadSnapshotPatch(preparedHeadPatch);
196
188
  if (!headApplied) {
@@ -211,7 +203,6 @@ function commitRscPatchNavigation({
211
203
  outletCommitted = false;
212
204
  }
213
205
  });
214
- if (outletCommitted && headApplied) onCommitted?.();
215
206
  return outletCommitted && headApplied;
216
207
  }
217
208
 
@@ -384,12 +375,9 @@ function Root(): ReactNode {
384
375
  maxEntries: MAX_RSC_CACHE_ENTRIES,
385
376
  startTransition,
386
377
  commitThenable: (node) => {
387
- flushSync(() => {
388
- resetAkanSegmentOutletPatches();
389
- setThenable(node.thenable);
390
- });
378
+ resetAkanSegmentOutletPatches();
379
+ setThenable(node.thenable);
391
380
  },
392
- onCommitted: () => dispatchRscNavigationCommitted(target),
393
381
  navId,
394
382
  getCurrentNavId: () => navigationSeq,
395
383
  });
@@ -432,7 +420,6 @@ function Root(): ReactNode {
432
420
  replace: options.replace,
433
421
  scrollToTop,
434
422
  bumpScrollToTop: () => setScrollToTopTick((tick) => tick + 1),
435
- onCommitted: () => dispatchRscNavigationCommitted(target),
436
423
  })
437
424
  ) {
438
425
  rememberPatchedRouteState(patchResult.tree, patchResult.patchedNode);
@@ -457,7 +444,6 @@ function Root(): ReactNode {
457
444
  replace: options.replace,
458
445
  scrollToTop,
459
446
  bumpScrollToTop: () => setScrollToTopTick((tick) => tick + 1),
460
- onCommitted: () => dispatchRscNavigationCommitted(target),
461
447
  })
462
448
  ) {
463
449
  rememberPatchedRouteState(fetched.tree, fetched.patchedNode);
@@ -504,10 +490,8 @@ function Root(): ReactNode {
504
490
  maxEntries: MAX_RSC_CACHE_ENTRIES,
505
491
  startTransition,
506
492
  commitThenable: (node) => {
507
- flushSync(() => {
508
- resetAkanSegmentOutletPatches();
509
- setThenable(node.thenable);
510
- });
493
+ resetAkanSegmentOutletPatches();
494
+ setThenable(node.thenable);
511
495
  },
512
496
  updateHistory: () => {
513
497
  if (options.replace) window.history.replaceState(null, "", target);
@@ -515,7 +499,6 @@ function Root(): ReactNode {
515
499
  },
516
500
  scrollToTop,
517
501
  bumpScrollToTop: () => setScrollToTopTick((tick) => tick + 1),
518
- onCommitted: () => dispatchRscNavigationCommitted(target),
519
502
  navId,
520
503
  getCurrentNavId: () => navigationSeq,
521
504
  });
@@ -329,7 +329,6 @@ interface CommitRscNavigationInput<T> {
329
329
  updateHistory?: () => void;
330
330
  scrollToTop?: boolean;
331
331
  bumpScrollToTop?: () => void;
332
- onCommitted?: () => void;
333
332
  }
334
333
 
335
334
  export function commitRscNavigation<T>({
@@ -342,7 +341,6 @@ export function commitRscNavigation<T>({
342
341
  updateHistory,
343
342
  scrollToTop,
344
343
  bumpScrollToTop,
345
- onCommitted,
346
344
  }: CommitRscNavigationInput<T>): void {
347
345
  rememberRscCacheEntry(cache, href, thenable, maxEntries);
348
346
  startTransition(() => {
@@ -350,7 +348,6 @@ export function commitRscNavigation<T>({
350
348
  updateHistory?.();
351
349
  if (scrollToTop) bumpScrollToTop?.();
352
350
  });
353
- onCommitted?.();
354
351
  }
355
352
 
356
353
  export function commitLatestRscNavigation<T>({
@@ -3,7 +3,7 @@ import { AsyncLocalStorage } from "node:async_hooks";
3
3
  import { mkdir } from "node:fs/promises";
4
4
  import path from "node:path";
5
5
  import type { InArgs, InValue, Client as LibsqlClient } from "@libsql/client";
6
- import { type BaseEnv, dayjs, FIELD_META, type PromiseOrObject } from "akanjs/base";
6
+ import { type BaseEnv, dayjs, FIELD_META, PRIMITIVE_DEFAULT_VALUE, type PromiseOrObject } from "akanjs/base";
7
7
  import { type ConstantModel, getDefault } from "akanjs/constant";
8
8
  import {
9
9
  createDocumentId,
@@ -951,9 +951,16 @@ export class SqliteDocumentStore {
951
951
  for (const [idx, field] of jsonFields.entries()) {
952
952
  const value = this.parseProjectedValue(row[this.projectionAlias(idx)]);
953
953
  const props = (this.database.doc[FIELD_META] as unknown as FieldMap)[field]?.getProps?.();
954
- if (value === null && props?.default !== undefined && props.default !== null && !props.nullable) {
955
- doc[field] =
956
- typeof props.default === "function" ? (props.default as (data: unknown) => unknown)(doc) : props.default;
954
+ if (value === null && !props?.nullable) {
955
+ if (props?.default != null) {
956
+ doc[field] =
957
+ typeof props.default === "function" ? (props.default as (data: unknown) => unknown)(doc) : props.default;
958
+ } else {
959
+ doc[field] =
960
+ ((props as Record<string, unknown>).modelRef as { [PRIMITIVE_DEFAULT_VALUE]?: unknown })?.[
961
+ PRIMITIVE_DEFAULT_VALUE
962
+ ] ?? null;
963
+ }
957
964
  } else {
958
965
  doc[field] = props ? this.decodeFieldValue(value, props) : value;
959
966
  }
@@ -1022,10 +1029,15 @@ export class SqliteDocumentStore {
1022
1029
  const value = payload[key];
1023
1030
  if (value === undefined) {
1024
1031
  const def = props.default;
1025
- if (def !== undefined && def !== null) {
1032
+ if (def != null) {
1026
1033
  result[key] = typeof def === "function" ? (def as (data: unknown) => unknown)(payload) : def;
1027
1034
  } else if (props.nullable) {
1028
1035
  result[key] = null;
1036
+ } else {
1037
+ result[key] =
1038
+ ((props as Record<string, unknown>).modelRef as { [PRIMITIVE_DEFAULT_VALUE]?: unknown })?.[
1039
+ PRIMITIVE_DEFAULT_VALUE
1040
+ ] ?? null;
1029
1041
  }
1030
1042
  } else {
1031
1043
  result[key] = this.decodeFieldValue(value, props);
@@ -87,9 +87,8 @@ interface CommitRscNavigationInput<T> {
87
87
  updateHistory?: () => void;
88
88
  scrollToTop?: boolean;
89
89
  bumpScrollToTop?: () => void;
90
- onCommitted?: () => void;
91
90
  }
92
- export declare function commitRscNavigation<T>({ cache, href, thenable, maxEntries, startTransition, commitThenable, updateHistory, scrollToTop, bumpScrollToTop, onCommitted, }: CommitRscNavigationInput<T>): void;
91
+ export declare function commitRscNavigation<T>({ cache, href, thenable, maxEntries, startTransition, commitThenable, updateHistory, scrollToTop, bumpScrollToTop, }: CommitRscNavigationInput<T>): void;
93
92
  export declare function commitLatestRscNavigation<T>({ navId, getCurrentNavId, ...input }: CommitRscNavigationInput<T> & {
94
93
  navId: number;
95
94
  getCurrentNavId: () => number;
@@ -244,8 +244,6 @@ function buildSearchParams(entries: Iterable<[string, string]>): Record<string,
244
244
  return params;
245
245
  }
246
246
 
247
- const AKAN_RSC_NAVIGATION_COMMITTED_EVENT = "akan:rsc-navigation-committed";
248
-
249
247
  export const ClientInner = () => {
250
248
  const uiOperation = st.use.uiOperation();
251
249
  return (
@@ -292,9 +290,11 @@ export const ClientSsrBridge = ({ lang, prefix = "" }: ClientSsrBridgeProps) =>
292
290
  prefix,
293
291
  router: {
294
292
  push: (href, routeOptions) => {
293
+ syncHref(href);
295
294
  navigateRscWithFallback(href, routeOptions, () => window.location.assign(href));
296
295
  },
297
296
  replace: (href, routeOptions) => {
297
+ syncHref(href);
298
298
  navigateRscWithFallback(href, { ...routeOptions, replace: true }, () => window.location.replace(href));
299
299
  },
300
300
  back: () => {
@@ -302,6 +302,7 @@ export const ClientSsrBridge = ({ lang, prefix = "" }: ClientSsrBridgeProps) =>
302
302
  },
303
303
  refresh: () => {
304
304
  clearRscNavigationCache();
305
+ syncHref(window.location.href);
305
306
  void navigateRsc(window.location.href, {
306
307
  replace: true,
307
308
  scrollToTop: false,
@@ -309,13 +310,7 @@ export const ClientSsrBridge = ({ lang, prefix = "" }: ClientSsrBridgeProps) =>
309
310
  },
310
311
  },
311
312
  });
312
- const syncCommittedNavigation = (event: Event) => {
313
- const detail = (event as CustomEvent<{ href?: string }>).detail;
314
- syncHref(detail?.href ?? window.location.href);
315
- };
316
- window.addEventListener(AKAN_RSC_NAVIGATION_COMMITTED_EVENT, syncCommittedNavigation);
317
313
  void Device.load({ lang });
318
- return () => window.removeEventListener(AKAN_RSC_NAVIGATION_COMMITTED_EVENT, syncCommittedNavigation);
319
314
  }, [lang, prefix]);
320
315
 
321
316
  useEffect(() => {
@@ -327,6 +322,8 @@ export const ClientSsrBridge = ({ lang, prefix = "" }: ClientSsrBridgeProps) =>
327
322
  st.set({ pathname: window.location.pathname, path, searchParams });
328
323
  };
329
324
  sync();
325
+ window.addEventListener("popstate", sync);
326
+ return () => window.removeEventListener("popstate", sync);
330
327
  }, [lang, prefix]);
331
328
  return null;
332
329
  };