@abide/abide 0.47.0 → 0.49.0

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 (84) hide show
  1. package/AGENTS.md +26 -13
  2. package/CHANGELOG.md +53 -0
  3. package/README.md +9 -3
  4. package/package.json +3 -1
  5. package/src/buildCli.ts +3 -5
  6. package/src/buildDisconnected.ts +2 -3
  7. package/src/bundleApp.ts +2 -3
  8. package/src/compile.ts +2 -4
  9. package/src/lib/bundle/installDownloads.ts +13 -3
  10. package/src/lib/bundle/installMacMenu.ts +13 -3
  11. package/src/lib/cli/parseArgvForRpc.ts +36 -9
  12. package/src/lib/cli/tokenizeArgvFlags.ts +4 -2
  13. package/src/lib/mcp/createMcpResourceServer.ts +13 -2
  14. package/src/lib/mcp/toolResultFromResponse.ts +40 -12
  15. package/src/lib/server/rpc/parseArgs.ts +15 -1
  16. package/src/lib/server/rpc/runWithRpcTimeout.ts +12 -1
  17. package/src/lib/server/runtime/buildCacheSnapshot.ts +6 -6
  18. package/src/lib/server/runtime/finalizeResponse.ts +11 -1
  19. package/src/lib/server/runtime/snapshotEntryFromCache.ts +10 -2
  20. package/src/lib/server/runtime/types/InspectorCacheEntry.ts +1 -1
  21. package/src/lib/server/runtime/types/InspectorCacheSnapshot.ts +4 -4
  22. package/src/lib/server/runtime/types/InspectorContext.ts +1 -1
  23. package/src/lib/shared/buildArtifact.ts +17 -0
  24. package/src/lib/shared/buildRpcRequest.ts +6 -2
  25. package/src/lib/shared/cache.ts +66 -28
  26. package/src/lib/shared/cacheStores.ts +3 -3
  27. package/src/lib/shared/canonicalJson.ts +24 -1
  28. package/src/lib/shared/createChannelLog.ts +24 -0
  29. package/src/lib/shared/exitOnBuildFailure.ts +4 -3
  30. package/src/lib/shared/parseEnv.ts +17 -6
  31. package/src/lib/shared/refresh.ts +3 -3
  32. package/src/lib/shared/serializeEnv.ts +18 -6
  33. package/src/lib/shared/sharedCacheStore.ts +14 -0
  34. package/src/lib/shared/sharedCacheStoreSlot.ts +10 -0
  35. package/src/lib/shared/snippet.ts +11 -6
  36. package/src/lib/shared/types/CacheOptions.ts +15 -11
  37. package/src/lib/shared/types/CacheStats.ts +1 -1
  38. package/src/lib/shared/types/SmartReadOptions.ts +15 -11
  39. package/src/lib/shared/url.ts +5 -0
  40. package/src/lib/test/createTestApp.ts +6 -6
  41. package/src/lib/ui/compile/UI_RUNTIME_IMPORTS.ts +1 -0
  42. package/src/lib/ui/compile/bindListenEvent.ts +5 -6
  43. package/src/lib/ui/compile/compileSSR.ts +1 -1
  44. package/src/lib/ui/compile/compileShadow.ts +121 -25
  45. package/src/lib/ui/compile/composeProps.ts +3 -2
  46. package/src/lib/ui/compile/desugarSignals.ts +1 -1
  47. package/src/lib/ui/compile/generateBuild.ts +23 -9
  48. package/src/lib/ui/compile/generateSSR.ts +49 -37
  49. package/src/lib/ui/compile/isWhitespaceText.ts +10 -2
  50. package/src/lib/ui/compile/lowerDocAccess.ts +39 -1
  51. package/src/lib/ui/compile/parseTemplate.ts +3 -1
  52. package/src/lib/ui/compile/renameSignalRefs.ts +5 -18
  53. package/src/lib/ui/compile/resolveReactiveExport.ts +4 -7
  54. package/src/lib/ui/compile/scopeCss.ts +27 -4
  55. package/src/lib/ui/dom/awaitBlock.ts +67 -29
  56. package/src/lib/ui/dom/discardBoundary.ts +24 -6
  57. package/src/lib/ui/dom/each.ts +15 -8
  58. package/src/lib/ui/dom/fillBefore.ts +6 -7
  59. package/src/lib/ui/dom/mergeProps.ts +1 -1
  60. package/src/lib/ui/dom/mountSlot.ts +1 -1
  61. package/src/lib/ui/dom/mutateDocArray.ts +38 -0
  62. package/src/lib/ui/dom/restProps.ts +2 -2
  63. package/src/lib/ui/dom/spreadProps.ts +3 -4
  64. package/src/lib/ui/dom/tryBlock.ts +10 -11
  65. package/src/lib/ui/dom/withScope.ts +7 -0
  66. package/src/lib/ui/history.ts +14 -7
  67. package/src/lib/ui/installHotBridge.ts +2 -0
  68. package/src/lib/ui/props.ts +17 -0
  69. package/src/lib/ui/renderChain.ts +7 -3
  70. package/src/lib/ui/router.ts +23 -17
  71. package/src/lib/ui/runtime/CHILD_PRESENT.ts +2 -2
  72. package/src/lib/ui/runtime/applyPatchToTree.ts +16 -3
  73. package/src/lib/ui/runtime/captureModelDoc.ts +22 -7
  74. package/src/lib/ui/runtime/createDoc.ts +28 -12
  75. package/src/lib/ui/runtime/flushEffects.ts +23 -1
  76. package/src/lib/ui/runtime/scope.ts +11 -0
  77. package/src/lib/ui/runtime/toTeardown.ts +10 -3
  78. package/src/lib/ui/runtime/types/UiProps.ts +6 -5
  79. package/src/lib/ui/runtime/withoutHydration.ts +22 -0
  80. package/src/lib/ui/startClient.ts +3 -3
  81. package/src/lib/ui/state.ts +9 -3
  82. package/src/serverEntry.ts +11 -9
  83. package/src/lib/shared/globalCacheStore.ts +0 -15
  84. package/src/lib/shared/globalCacheStoreSlot.ts +0 -12
@@ -0,0 +1,22 @@
1
+ import { RENDER } from './RENDER.ts'
2
+
3
+ /*
4
+ Runs `build` with the hydration claim cursor cleared, restoring it after. The
5
+ control-flow blocks route FRESH builds through here — a pending/resolved await
6
+ branch, a try's catch branch, a fillBefore insert — so their build helpers
7
+ create nodes instead of trying to claim server DOM that isn't there. A rebuild
8
+ that fires while an outer hydrate pass is still active (e.g. a synchronous write
9
+ that flips a `when`/`switch` mid-hydrate) would otherwise make `cloneStatic` /
10
+ text claim discarded or nonexistent nodes and silently render nothing. The
11
+ `finally` restore lets a fresh build sit inside an ongoing hydrate pass without
12
+ ending it early.
13
+ */
14
+ export function withoutHydration<T>(build: () => T): T {
15
+ const previous = RENDER.hydration
16
+ RENDER.hydration = undefined
17
+ try {
18
+ return build()
19
+ } finally {
20
+ RENDER.hydration = previous
21
+ }
22
+ }
@@ -1,7 +1,7 @@
1
1
  import { cacheStoreSlot } from '../shared/cacheStoreSlot.ts'
2
2
  import { createCacheStore } from '../shared/createCacheStore.ts'
3
- import { globalCacheStoreSlot } from '../shared/globalCacheStoreSlot.ts'
4
3
  import { pageSlot } from '../shared/pageSlot.ts'
4
+ import { sharedCacheStoreSlot } from '../shared/sharedCacheStoreSlot.ts'
5
5
  import type { SsrPayload } from '../shared/types/SsrPayload.ts'
6
6
  import type { StreamedResolution } from '../shared/types/StreamedResolution.ts'
7
7
  import { probeNavigation } from './probeNavigation.ts'
@@ -68,8 +68,8 @@ export function startClient(
68
68
 
69
69
  const store = createCacheStore()
70
70
  cacheStoreSlot.resolver = () => store
71
- /* One tab store: cache(fn, { global: true }) shares it, so global is a no-op here. */
72
- globalCacheStoreSlot.resolver = () => store
71
+ /* One tab store: cache(fn, { shared: true }) shares it, so shared is a no-op here. */
72
+ sharedCacheStoreSlot.resolver = () => store
73
73
  /* Seed both SSR cache partitions through the one streamed-resolution sink: `ssr.cache`
74
74
  (inline — reads settled at render-return, in __SSR__) and `__abideResumeCache` (pending
75
75
  {#await} reads whose `__abideResolve(...)` chunks the stream pushed during parse, before
@@ -14,11 +14,17 @@ import { scope } from './scope.ts'
14
14
  reached ambiently so a component can pass a named value down its subtree. */
15
15
  type StateFn = {
16
16
  /* No-arg form for an undefined initial with a declared type: `state<Foo>()` is
17
- `State<Foo | undefined>`. Without it `state<Foo>(undefined)` is an arity/assign
18
- error and `state(undefined)` infers `T = undefined` (every `.value` access then
19
- narrows to `never`). */
17
+ `State<Foo | undefined>`. Without it `state(undefined)` infers `T = undefined`
18
+ (every `.value` access then narrows to `never`). */
20
19
  <T>(): State<T | undefined>
21
20
  <T>(initial: T, transform?: (next: T, previous: T) => T): State<T>
21
+ /* The no-arg form spelled out: `state<Foo>(undefined)` is `State<Foo | undefined>`
22
+ too. Kept a distinct overload (not `initial?: T`) BELOW the general form — a real
23
+ initial still binds `T` from the value; only an explicit `undefined` (which the
24
+ general form rejects as "not assignable to T") falls through to here. A bare
25
+ `state(undefined)` still resolves against the general form (`T = undefined`), so
26
+ this overload changes nothing for it. */
27
+ <T>(initial: undefined): State<T | undefined>
22
28
  /* A writable cell reseeded from a reactive thunk (`state.linked(() => src())`). */
23
29
  linked: typeof linked
24
30
  /* A read-only cell computed from other cells (`state.computed(() => a() + b())`). */
@@ -31,10 +31,10 @@ import { requestContext } from './lib/server/runtime/requestContext.ts'
31
31
  import { resolvePageSnapshot } from './lib/server/runtime/resolvePageSnapshot.ts'
32
32
  import { cacheStoreSlot } from './lib/shared/cacheStoreSlot.ts'
33
33
  import { createCacheStore } from './lib/shared/createCacheStore.ts'
34
- import { globalCacheStoreSlot } from './lib/shared/globalCacheStoreSlot.ts'
35
34
  import { loadEnvFromDataDir } from './lib/shared/loadEnvFromDataDir.ts'
36
35
  import { pageSlot } from './lib/shared/pageSlot.ts'
37
36
  import { runningAsStandaloneBinary } from './lib/shared/runningAsStandaloneBinary.ts'
37
+ import { sharedCacheStoreSlot } from './lib/shared/sharedCacheStoreSlot.ts'
38
38
 
39
39
  /*
40
40
  Resolve config into process.env before anything reads it (createServer reads
@@ -65,16 +65,18 @@ await import('./_virtual/config.ts')
65
65
  // In a bundle, tie this server's life to the launcher's (no-op standalone).
66
66
  exitWithParent()
67
67
 
68
- cacheStoreSlot.resolver = () => requestContext.getStore()?.cache
69
-
70
- pageSlot.resolver = resolvePageSnapshot
71
-
72
68
  /*
73
- Process-level store for cache(fn, { global: true }) — one per server process,
74
- outlives every request so memoised external calls are shared across them.
69
+ Process-level ("shared") store for cache(fn, { shared: true }) — one per server
70
+ process, outlives every request so memoised external calls are shared across them.
71
+ It is also the store a read with no request in flight resolves to, so boot/cron/
72
+ socket-handler reads coalesce into a real store instead of an orphan fallback.
75
73
  */
76
- const globalCacheStore = createCacheStore()
77
- globalCacheStoreSlot.resolver = () => globalCacheStore
74
+ const sharedCacheStore = createCacheStore()
75
+ sharedCacheStoreSlot.resolver = () => sharedCacheStore
76
+
77
+ cacheStoreSlot.resolver = () => requestContext.getStore()?.cache ?? sharedCacheStore
78
+
79
+ pageSlot.resolver = resolvePageSnapshot
78
80
 
79
81
  await createServer({
80
82
  pages,
@@ -1,15 +0,0 @@
1
- import { activeCacheStore } from './activeCacheStore.ts'
2
- import { globalCacheStoreSlot } from './globalCacheStoreSlot.ts'
3
- import type { CacheStore } from './types/CacheStore.ts'
4
-
5
- /*
6
- Resolves the process-level CacheStore that `cache(fn, { global: true })` entries
7
- live in. The server entry registers a module-singleton resolver so the store
8
- survives across requests; the client points it at the active tab store. When no
9
- resolver is registered (isolated tests, or a client that never set one) it falls
10
- back to the active store, so `global` degrades to request/tab-scoped rather than
11
- throwing.
12
- */
13
- export function globalCacheStore(): CacheStore {
14
- return globalCacheStoreSlot.resolver?.() ?? activeCacheStore()
15
- }
@@ -1,12 +0,0 @@
1
- import { createResolverSlot } from './createResolverSlot.ts'
2
- import type { CacheStore } from './types/CacheStore.ts'
3
-
4
- /*
5
- Slot for the process-level cache store used by cache() entries opting into
6
- `global: true`. The server entry registers a module-singleton store outliving
7
- any one request; the client entry points it at its single tab store so
8
- `global` is a no-op there. No fallback creator — unset means no global store
9
- is registered, in which case globalCacheStore() falls back to the active
10
- (request/tab) store. Test helpers snapshot/poke `.resolver` directly.
11
- */
12
- export const globalCacheStoreSlot = createResolverSlot<CacheStore>()