@abide/abide 0.48.0 → 0.50.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.
- package/AGENTS.md +85 -59
- package/CHANGELOG.md +216 -0
- package/README.md +21 -10
- package/package.json +15 -4
- package/src/abideLsp.ts +5 -6
- package/src/abideResolverPlugin.ts +197 -169
- package/src/build.ts +79 -56
- package/src/buildCli.ts +3 -5
- package/src/buildDisconnected.ts +2 -5
- package/src/bundleApp.ts +2 -3
- package/src/checkAbide.ts +12 -2
- package/src/compile.ts +2 -4
- package/src/devEntry.ts +113 -28
- package/src/discoveryEntry.ts +3 -2
- package/src/lib/bundle/disconnected.abide +69 -73
- package/src/lib/bundle/infoPlist.ts +13 -7
- package/src/lib/bundle/installDownloads.ts +13 -3
- package/src/lib/bundle/installMacMenu.ts +13 -3
- package/src/lib/bundle/spawnEmbeddedServer.ts +13 -4
- package/src/lib/bundle/waitForServer.ts +6 -1
- package/src/lib/cli/parseArgvForRpc.ts +36 -9
- package/src/lib/cli/tokenizeArgvFlags.ts +4 -2
- package/src/lib/mcp/createMcpResourceServer.ts +13 -2
- package/src/lib/mcp/mcpTools.ts +15 -6
- package/src/lib/mcp/toolResultFromResponse.ts +40 -12
- package/src/lib/server/error.ts +6 -6
- package/src/lib/server/json.ts +17 -3
- package/src/lib/server/rpc/defineRpc.ts +58 -24
- package/src/lib/server/rpc/parseArgs.ts +113 -14
- package/src/lib/server/rpc/resolveRpcJsonSchema.ts +28 -0
- package/src/lib/server/rpc/runWithRpcTimeout.ts +12 -1
- package/src/lib/server/rpc/types/RpcHelper.ts +75 -105
- package/src/lib/server/rpc/types/RpcRegistryEntry.ts +24 -9
- package/src/lib/server/rpc/validationError.ts +1 -1
- package/src/lib/server/runtime/DEV_RELOAD_CLIENT_SCRIPT.ts +0 -15
- package/src/lib/server/runtime/buildCacheSnapshot.ts +10 -9
- package/src/lib/server/runtime/buildInspectorSurface.ts +6 -4
- package/src/lib/server/runtime/buildOpenApiSpec.ts +55 -11
- package/src/lib/server/runtime/buildPreloadManifest.ts +12 -10
- package/src/lib/server/runtime/createAppAssetServer.ts +18 -15
- package/src/lib/server/runtime/createAppRouteResolver.ts +145 -0
- package/src/lib/server/runtime/createPlumbingRouter.ts +212 -0
- package/src/lib/server/runtime/createRouteDispatcher.ts +4 -10
- package/src/lib/server/runtime/createServer.ts +120 -324
- package/src/lib/server/runtime/createUiPageRenderer.ts +137 -26
- package/src/lib/server/runtime/devClientFingerprint.ts +19 -34
- package/src/lib/server/runtime/finalizeResponse.ts +11 -1
- package/src/lib/server/runtime/installAmbientScopeStore.ts +30 -9
- package/src/lib/server/runtime/logExposedSurfaces.ts +8 -7
- package/src/lib/server/runtime/pathStore.ts +15 -0
- package/src/lib/server/runtime/registryManifests.ts +1 -1
- package/src/lib/server/runtime/renderCellBarrierStore.ts +15 -0
- package/src/lib/server/runtime/runWithRequestScope.ts +3 -0
- package/src/lib/server/runtime/serializeCacheSnapshot.ts +6 -4
- package/src/lib/server/runtime/snapshotEntryFromCache.ts +24 -16
- package/src/lib/server/runtime/streamCacheResolutions.ts +14 -7
- package/src/lib/server/runtime/streamFromIterator.ts +30 -2
- package/src/lib/server/runtime/textResponse.ts +23 -0
- package/src/lib/server/runtime/types/DevReloadStamp.ts +6 -10
- package/src/lib/server/runtime/types/InspectorCacheEntry.ts +1 -1
- package/src/lib/server/runtime/types/RequestStore.ts +27 -0
- package/src/lib/server/runtime/warnUnguardedMcp.ts +15 -5
- package/src/lib/server/sockets/createSocketDispatcher.ts +9 -11
- package/src/lib/server/sockets/defineSocket.ts +5 -4
- package/src/lib/server/sse.ts +5 -1
- package/src/lib/shared/ASYNC_CELL.ts +5 -0
- package/src/lib/shared/DEV_REBUILD_PATH.ts +6 -0
- package/src/lib/shared/HTTP_METHODS.ts +6 -0
- package/src/lib/shared/HttpError.ts +1 -5
- package/src/lib/shared/MCP_PATH.ts +6 -0
- package/src/lib/shared/PROXIED_SERVER_SUBDIRS.ts +15 -0
- package/src/lib/shared/REF_JSON_TAGS.ts +13 -1
- package/src/lib/shared/RPC_SHIM_GLOBALS.ts +9 -0
- package/src/lib/shared/activeCacheStore.ts +1 -0
- package/src/lib/shared/activePage.ts +1 -0
- package/src/lib/shared/buildArtifact.ts +20 -0
- package/src/lib/shared/buildRpcRequest.ts +6 -2
- package/src/lib/shared/buildSocketOverChannel.ts +4 -3
- package/src/lib/shared/bundleGraphFromMetafile.ts +68 -0
- package/src/lib/shared/cache.ts +156 -131
- package/src/lib/shared/canonicalJson.ts +24 -1
- package/src/lib/shared/changeAffectsClient.ts +12 -7
- package/src/lib/shared/createCacheStore.ts +31 -8
- package/src/lib/shared/createChannelLog.ts +24 -0
- package/src/lib/shared/createLifecycleChannel.ts +7 -1
- package/src/lib/shared/createReachable.ts +47 -78
- package/src/lib/shared/createRemoteFunction.ts +52 -30
- package/src/lib/shared/createRpcServerProgram.ts +820 -0
- package/src/lib/shared/decodeRefJson.ts +4 -4
- package/src/lib/shared/decodeResponse.ts +2 -2
- package/src/lib/shared/decodeWireBody.ts +35 -0
- package/src/lib/shared/detectRpcMethod.ts +8 -1
- package/src/lib/shared/done.ts +8 -2
- package/src/lib/shared/encodeRefJson.ts +4 -4
- package/src/lib/shared/encodeWireBody.ts +18 -0
- package/src/lib/shared/exitOnBuildFailure.ts +4 -3
- package/src/lib/{server/rpc → shared}/fieldErrorsFromIssues.ts +5 -1
- package/src/lib/shared/generateDeclarations.ts +72 -0
- package/src/lib/shared/hasSeedableRequest.ts +25 -0
- package/src/lib/shared/hydrationWindow.ts +53 -0
- package/src/lib/shared/isAsyncCell.ts +11 -0
- package/src/lib/shared/isAsyncIterable.ts +8 -0
- package/src/lib/shared/isSubscribable.ts +3 -3
- package/src/lib/shared/isThenable.ts +9 -0
- package/src/lib/shared/jsonSchemaForType.ts +258 -0
- package/src/lib/shared/lenientDecode.ts +15 -0
- package/src/lib/shared/loadProjectTsConfig.ts +28 -0
- package/src/lib/shared/markFrameworkSourcesIgnored.ts +1 -1
- package/src/lib/shared/matchRoute.ts +4 -14
- package/src/lib/shared/parseEnv.ts +17 -6
- package/src/lib/shared/peek.ts +14 -0
- package/src/lib/shared/pending.ts +9 -6
- package/src/lib/shared/pendingAsyncCellsSlot.ts +13 -0
- package/src/lib/shared/prepareRpcModule.ts +91 -93
- package/src/lib/shared/prepareSocketModule.ts +3 -2
- package/src/lib/shared/probeRegistries.ts +5 -18
- package/src/lib/shared/reachable.ts +7 -10
- package/src/lib/shared/refresh.ts +12 -2
- package/src/lib/shared/refreshing.ts +8 -2
- package/src/lib/shared/resolvedCellsSlot.ts +13 -0
- package/src/lib/shared/reviveWireField.ts +49 -0
- package/src/lib/shared/reviveWireOutput.ts +36 -0
- package/src/lib/shared/rpcServerForRoot.ts +25 -0
- package/src/lib/shared/scanPages.ts +25 -0
- package/src/lib/shared/serializeEnv.ts +18 -6
- package/src/lib/shared/snapshotShippable.ts +8 -7
- package/src/lib/shared/snippet.ts +11 -6
- package/src/lib/shared/streamedCellsSlot.ts +14 -0
- package/src/lib/shared/subscribableFromResponse.ts +4 -4
- package/src/lib/shared/subscribableProbes.ts +1 -1
- package/src/lib/shared/tailProbeSlot.ts +1 -1
- package/src/lib/shared/types/AsyncComputed.ts +20 -0
- package/src/lib/shared/types/AsyncState.ts +13 -0
- package/src/lib/shared/types/CacheEntry.ts +7 -7
- package/src/lib/shared/types/CacheOptions.ts +23 -37
- package/src/lib/shared/types/CachePolicy.ts +25 -0
- package/src/lib/shared/types/CacheSnapshotEntry.ts +6 -5
- package/src/lib/shared/types/ErrorJsonSchemas.ts +8 -0
- package/src/lib/shared/types/HttpMethod.ts +3 -1
- package/src/lib/shared/types/InputCoercion.ts +17 -0
- package/src/lib/shared/types/{Subscribable.ts → NamedAsyncIterable.ts} +1 -1
- package/src/lib/shared/types/OutputWirePlan.ts +17 -0
- package/src/lib/shared/types/PagesScan.ts +7 -0
- package/src/lib/shared/types/PendingAsyncCells.ts +10 -0
- package/src/lib/shared/types/RawRemoteFunction.ts +6 -0
- package/src/lib/shared/types/RemoteCallable.ts +8 -7
- package/src/lib/shared/types/RemoteFunction.ts +16 -15
- package/src/lib/shared/types/ResolvedCells.ts +11 -0
- package/src/lib/shared/types/ReturnBody.ts +15 -0
- package/src/lib/shared/types/RpcBuildStamps.ts +23 -0
- package/src/lib/shared/types/RpcErrorGuard.ts +3 -8
- package/src/lib/shared/types/Socket.ts +4 -4
- package/src/lib/shared/types/SsrPayload.ts +5 -1
- package/src/lib/shared/types/StreamPolicy.ts +11 -0
- package/src/lib/shared/types/StreamedCells.ts +19 -0
- package/src/lib/shared/types/StreamedResolution.ts +24 -6
- package/src/lib/shared/types/TailHooks.ts +1 -1
- package/src/lib/shared/types/WireKind.ts +11 -0
- package/src/lib/shared/url.ts +5 -0
- package/src/lib/shared/validationHttpError.ts +33 -0
- package/src/lib/shared/warmSeedKey.ts +16 -0
- package/src/lib/shared/wireJsonReplacer.ts +30 -0
- package/src/lib/shared/writeRpcDts.ts +11 -1
- package/src/lib/shared/writeTestSocketsDts.ts +1 -1
- package/src/lib/test/createTestApp.ts +19 -1
- package/src/lib/ui/README.md +1 -1
- package/src/lib/ui/activePendingCells.ts +14 -0
- package/src/lib/ui/compile/BLOCK_KEYWORDS.ts +21 -0
- package/src/lib/ui/compile/SSR_ESCAPE.ts +4 -1
- package/src/lib/ui/compile/UI_RUNTIME_IMPORTS.ts +35 -7
- package/src/lib/ui/compile/abideUiPlugin.ts +19 -2
- package/src/lib/ui/compile/analyzeComponent.ts +89 -6
- package/src/lib/ui/compile/assignmentTargetNames.ts +54 -0
- package/src/lib/ui/compile/asyncInterpolationFields.ts +152 -0
- package/src/lib/ui/compile/asyncValuePositionError.ts +21 -0
- package/src/lib/ui/compile/asyncValuePositionInterpolations.ts +64 -0
- package/src/lib/ui/compile/attrLiftPosition.ts +18 -0
- package/src/lib/ui/compile/bindListenEvent.ts +5 -6
- package/src/lib/ui/compile/cachedSourceFile.ts +40 -0
- package/src/lib/ui/compile/catchBinding.ts +7 -5
- package/src/lib/ui/compile/classifyInterpolationType.ts +46 -0
- package/src/lib/ui/compile/collectAbideDiagnostics.ts +96 -0
- package/src/lib/ui/compile/compileComponent.ts +19 -3
- package/src/lib/ui/compile/compileModule.ts +27 -58
- package/src/lib/ui/compile/compileSSR.ts +52 -13
- package/src/lib/ui/compile/compileShadow.ts +265 -42
- package/src/lib/ui/compile/composeProps.ts +15 -4
- package/src/lib/ui/compile/createShadowLanguageService.ts +116 -68
- package/src/lib/ui/compile/createShadowProgram.ts +35 -6
- package/src/lib/ui/compile/declaredNames.ts +36 -0
- package/src/lib/ui/compile/desugarSignals.ts +419 -37
- package/src/lib/ui/compile/expressionIsPrefixEvaluable.ts +19 -0
- package/src/lib/ui/compile/generateBuild.ts +74 -17
- package/src/lib/ui/compile/generateSSR.ts +286 -75
- package/src/lib/ui/compile/hoistableAwaits.ts +193 -0
- package/src/lib/ui/compile/hoistableChildRenders.ts +112 -0
- package/src/lib/ui/compile/interpolatedTemplateLiteral.ts +3 -1
- package/src/lib/ui/compile/interpolationClassifierForRoot.ts +37 -0
- package/src/lib/ui/compile/isSpuriousAsyncReadDiagnostic.ts +174 -0
- package/src/lib/ui/compile/isWhitespaceText.ts +10 -2
- package/src/lib/ui/compile/liftAsyncSubExpressions.ts +166 -0
- package/src/lib/ui/compile/lowerAsyncInterpolations.ts +92 -0
- package/src/lib/ui/compile/lowerContext.ts +10 -0
- package/src/lib/ui/compile/lowerDocAccess.ts +51 -10
- package/src/lib/ui/compile/lowerScript.ts +40 -4
- package/src/lib/ui/compile/nodeAtShadowOffset.ts +28 -0
- package/src/lib/ui/compile/parseTemplate.ts +18 -1090
- package/src/lib/ui/compile/parseTemplateRecovering.ts +1385 -0
- package/src/lib/ui/compile/referencedIdentifiers.ts +35 -0
- package/src/lib/ui/compile/renameSignalRefs.ts +26 -40
- package/src/lib/ui/compile/resolveReactiveExport.ts +4 -7
- package/src/lib/ui/compile/scopeCss.ts +27 -4
- package/src/lib/ui/compile/seedTypeClassifierForRoot.ts +65 -0
- package/src/lib/ui/compile/shadowInterpolationClassifier.ts +47 -0
- package/src/lib/ui/compile/sourceFileOptionsSignature.ts +20 -0
- package/src/lib/ui/compile/structuralHeadTokens.ts +107 -0
- package/src/lib/ui/compile/templateSemanticTokens.ts +21 -0
- package/src/lib/ui/compile/templateStartOffset.ts +15 -0
- package/src/lib/ui/compile/tryPlan.ts +4 -3
- package/src/lib/ui/compile/types/AnalyzedComponent.ts +4 -0
- package/src/lib/ui/compile/types/AsyncInterpolationField.ts +19 -0
- package/src/lib/ui/compile/types/InterpolationClassifier.ts +12 -0
- package/src/lib/ui/compile/types/InterpolationKind.ts +7 -0
- package/src/lib/ui/compile/types/ParseDiagnostic.ts +8 -0
- package/src/lib/ui/compile/types/SeedTypeClassifier.ts +15 -0
- package/src/lib/ui/compile/types/TemplateNode.ts +36 -4
- package/src/lib/ui/compile/types/ValuePositionInterpolation.ts +13 -0
- package/src/lib/ui/compile/writtenTemplateNames.ts +84 -0
- package/src/lib/ui/computed.ts +28 -1
- package/src/lib/ui/createScope.ts +35 -68
- package/src/lib/ui/dom/anchoredBranch.ts +142 -0
- package/src/lib/ui/dom/appendText.ts +8 -3
- package/src/lib/ui/dom/awaitBlock.ts +62 -75
- package/src/lib/ui/dom/bindProp.ts +22 -0
- package/src/lib/ui/dom/bindableProp.ts +47 -0
- package/src/lib/ui/dom/cellPending.ts +24 -0
- package/src/lib/ui/dom/discardBoundary.ts +24 -6
- package/src/lib/ui/dom/disposeRange.ts +2 -1
- package/src/lib/ui/dom/each.ts +41 -12
- package/src/lib/ui/dom/eachAsync.ts +39 -3
- package/src/lib/ui/dom/fillBefore.ts +6 -7
- package/src/lib/ui/dom/fillBoundary.ts +2 -3
- package/src/lib/ui/dom/fillRange.ts +4 -4
- package/src/lib/ui/dom/hydrate.ts +6 -12
- package/src/lib/ui/dom/isComment.ts +1 -1
- package/src/lib/ui/dom/matchingRangeClose.ts +29 -0
- package/src/lib/ui/dom/mergeProps.ts +1 -1
- package/src/lib/ui/dom/mount.ts +1 -2
- package/src/lib/ui/dom/mountChild.ts +9 -40
- package/src/lib/ui/dom/mountRange.ts +2 -3
- package/src/lib/ui/dom/mountSlot.ts +1 -1
- package/src/lib/ui/dom/mountStreamedChild.ts +84 -0
- package/src/lib/ui/dom/mountSwappableRange.ts +46 -4
- package/src/lib/ui/dom/mutateDocContainer.ts +65 -0
- package/src/lib/ui/dom/on.ts +2 -2
- package/src/lib/ui/dom/readCell.ts +40 -0
- package/src/lib/ui/dom/restProps.ts +2 -2
- package/src/lib/ui/dom/spreadProps.ts +3 -4
- package/src/lib/ui/dom/switchBlock.ts +30 -7
- package/src/lib/ui/dom/tryBlock.ts +233 -70
- package/src/lib/ui/dom/types/SwitchCase.ts +5 -1
- package/src/lib/ui/dom/when.ts +12 -2
- package/src/lib/ui/dom/withScope.ts +9 -2
- package/src/lib/ui/finalizeStreamedChildren.ts +89 -0
- package/src/lib/ui/flight.ts +56 -0
- package/src/lib/ui/html.ts +12 -1
- package/src/lib/ui/isolateCellBarrier.ts +17 -0
- package/src/lib/ui/linked.ts +48 -2
- package/src/lib/ui/props.ts +17 -0
- package/src/lib/ui/remoteProxy.ts +84 -159
- package/src/lib/ui/renderChain.ts +53 -13
- package/src/lib/ui/renderToStream.ts +22 -18
- package/src/lib/ui/resumeSeedScript.ts +1 -1
- package/src/lib/ui/router.ts +86 -53
- package/src/lib/ui/runtime/AsyncCellError.ts +20 -0
- package/src/lib/ui/runtime/CELL_SEED.ts +14 -0
- package/src/lib/ui/runtime/CHILD_PRESENT.ts +2 -2
- package/src/lib/ui/runtime/CURRENT_BOUNDARY.ts +11 -0
- package/src/lib/ui/runtime/CURRENT_PATH.ts +29 -0
- package/src/lib/ui/runtime/RENDER.ts +10 -7
- package/src/lib/ui/runtime/RESUME.ts +4 -4
- package/src/lib/ui/runtime/STREAMED_CELLS.ts +57 -0
- package/src/lib/ui/runtime/ambientPathBacking.ts +32 -0
- package/src/lib/ui/runtime/applyPatchToTree.ts +17 -4
- package/src/lib/ui/runtime/blockId.ts +31 -0
- package/src/lib/ui/runtime/boundaryFor.ts +11 -0
- package/src/lib/ui/runtime/cellBarrierBacking.ts +30 -0
- package/src/lib/ui/runtime/createAsyncCell.ts +300 -0
- package/src/lib/ui/runtime/createDoc.ts +31 -54
- package/src/lib/ui/runtime/createEffectNode.ts +9 -0
- package/src/lib/ui/runtime/enterRenderPass.ts +5 -4
- package/src/lib/ui/runtime/flushEffects.ts +33 -1
- package/src/lib/ui/runtime/isAsyncFunction.ts +14 -0
- package/src/lib/ui/runtime/nextBlockId.ts +8 -7
- package/src/lib/ui/runtime/renderPath.ts +16 -0
- package/src/lib/ui/runtime/scope.ts +11 -0
- package/src/lib/ui/runtime/toTeardown.ts +10 -3
- package/src/lib/ui/runtime/types/Boundary.ts +9 -0
- package/src/lib/ui/runtime/types/RenderContext.ts +9 -7
- package/src/lib/ui/runtime/types/SsrRender.ts +9 -2
- package/src/lib/ui/runtime/types/UiComponent.ts +1 -5
- package/src/lib/ui/runtime/types/UiProps.ts +6 -5
- package/src/lib/ui/runtime/withOptionalPath.ts +8 -0
- package/src/lib/ui/runtime/withPath.ts +16 -0
- package/src/lib/ui/runtime/withPathFrom.ts +20 -0
- package/src/lib/ui/runtime/withoutHydration.ts +22 -0
- package/src/lib/ui/seedStreamedResolution.ts +31 -6
- package/src/lib/ui/settleAsyncCells.ts +24 -0
- package/src/lib/ui/socketProxy.ts +1 -1
- package/src/lib/ui/startClient.ts +16 -31
- package/src/lib/ui/state.ts +9 -3
- package/src/lib/ui/trackedComputed.ts +68 -0
- package/src/lib/ui/types/Scope.ts +8 -24
- package/src/lib/ui/watch.ts +3 -3
- package/src/serverEntry.ts +14 -0
- package/template/src/server/rpc/getHello.ts +15 -13
- package/template/test/app.test.ts +1 -1
- package/src/lib/server/runtime/devHotModuleResponse.ts +0 -41
- package/src/lib/shared/DEV_HOT_PREFIX.ts +0 -7
- package/src/lib/shared/UNREACHABLE_STATUSES.ts +0 -13
- package/src/lib/shared/hasReplayableRequest.ts +0 -17
- package/src/lib/shared/hydratingSlot.ts +0 -12
- package/src/lib/shared/outboxProbeSlot.ts +0 -20
- package/src/lib/shared/types/Outbox.ts +0 -9
- package/src/lib/shared/types/OutboxEntry.ts +0 -27
- package/src/lib/shared/types/SmartReadOptions.ts +0 -36
- package/src/lib/shared/wakeHydrationPeeks.ts +0 -20
- package/src/lib/ui/COMPONENT_WRAPPER_PREFIX.ts +0 -5
- package/src/lib/ui/compile/REACTIVE_CALLEES.ts +0 -11
- package/src/lib/ui/compile/assertRuntimeHelpersBound.ts +0 -80
- package/src/lib/ui/compile/markupTokens.ts +0 -313
- package/src/lib/ui/compile/structuralBlockTokens.ts +0 -100
- package/src/lib/ui/dom/applyResolved.ts +0 -87
- package/src/lib/ui/dom/scopeLabel.ts +0 -21
- package/src/lib/ui/dom/text.ts +0 -20
- package/src/lib/ui/history.ts +0 -101
- package/src/lib/ui/installHotBridge.ts +0 -93
- package/src/lib/ui/installInspectorBridge.ts +0 -140
- package/src/lib/ui/outbox.ts +0 -35
- package/src/lib/ui/persist.ts +0 -115
- package/src/lib/ui/rpcOutbox/createOutboxQueue.ts +0 -281
- package/src/lib/ui/rpcOutbox/outboxRegistry.ts +0 -69
- package/src/lib/ui/runtime/PATCH_BUS.ts +0 -28
- package/src/lib/ui/runtime/captureModelDoc.ts +0 -28
- package/src/lib/ui/runtime/hotInstances.ts +0 -10
- package/src/lib/ui/runtime/hotReloadEnabled.ts +0 -8
- package/src/lib/ui/runtime/hotReplace.ts +0 -38
- package/src/lib/ui/runtime/liveScopes.ts +0 -15
- package/src/lib/ui/runtime/localStoragePersistence.ts +0 -47
- package/src/lib/ui/runtime/registerHotInstance.ts +0 -23
- package/src/lib/ui/runtime/seedModelDoc.ts +0 -26
- package/src/lib/ui/runtime/types/HotInstance.ts +0 -22
- package/src/lib/ui/runtime/types/PatchEvent.ts +0 -16
- package/src/lib/ui/seedResolved.ts +0 -28
- package/src/lib/ui/sync.ts +0 -48
- package/src/lib/ui/types/History.ts +0 -14
- package/src/lib/ui/types/PersistHandle.ts +0 -11
- package/src/lib/ui/types/PersistenceStore.ts +0 -12
- package/src/lib/ui/types/ResolvedFrame.ts +0 -15
- package/src/lib/ui/types/SyncTransport.ts +0 -13
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,221 @@
|
|
|
1
1
|
# abide
|
|
2
2
|
|
|
3
|
+
## 0.50.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 8fb06cf: Async values — `state` holds, `computed`/`linked` track, and a reactive `{#try}` (ADR-0019)
|
|
8
|
+
|
|
9
|
+
`state` is now a pure value-taker; `computed`/`linked` track an async source. A `computed(await …)` / `linked(await …)` seed unwraps its promise into an async cell, and a seed producing a stream (`NamedAsyncIterable`) auto-tracks its frames. Async cells wear the probe family (`peek`/`pending`/`refreshing`/`error`/`refresh`, standalone + instance) and have no `.value` — sync → `.value`, async → probes. `AsyncState` adds `set()`, latching a local write until the next reseed.
|
|
10
|
+
|
|
11
|
+
`computed(EXPR)` / `linked(EXPR)` now accept a bare expression (wrapped into a thunk unless it is already a `() => …`); a top-level `await` lowers to an eager `async () => …` so independent cells load in parallel, not in a waterfall.
|
|
12
|
+
|
|
13
|
+
`{#try}` is a fully reactive error boundary — it catches a throw from a _later_ re-run (where async errors live), not just the initial render, and heals back to the guarded content when the failing cell recovers (`refresh()` or a dependency change), no manual retry.
|
|
14
|
+
|
|
15
|
+
Also renames the internal `Subscribable<T>` type to `NamedAsyncIterable<T>` (shape unchanged).
|
|
16
|
+
|
|
17
|
+
- b790726: Async template interpolation — `{await foo()}`, `{foo()}`, `{getStream()}` (ADR-0019 follow-up)
|
|
18
|
+
|
|
19
|
+
A template interpolation now understands async expressions, chosen by the expression's type (resolved through the shadow TypeChecker at build time — zero runtime cost, dev/prod consistent):
|
|
20
|
+
|
|
21
|
+
- `{await foo()}` — awaits the promise, **blocking** (bakes into the SSR HTML). Syntactic; desugars to a blocking `{#await … then}` block.
|
|
22
|
+
- `{foo()}` where `foo()` is a `Promise<T>` — **streaming** (real Tier-3 out-of-order SSR); desugars to a streaming `{#await}` block.
|
|
23
|
+
- `{getStream()}` where the expression is any `AsyncIterable<T>` (a socket, a streaming rpc, or a plain async generator) — renders the **latest frame**, live, as a stream cell.
|
|
24
|
+
- A `Promise`/`AsyncIterable` in a value slot that can't be rendered (an attribute, an `{#if}`/`{#switch}` head, a sync `{#each}` iterable) is a **compile error** with a hint, never a silent `[object Promise]`. `{#for await}` stays the sanctioned async-iterable position.
|
|
25
|
+
|
|
26
|
+
Errors compose with `{#try}`: a catch-less `{#await}` / `{#for await}` (and these new bare forms) now bubbles a rejection to the nearest enclosing `{#try}` instead of an unhandled rejection.
|
|
27
|
+
|
|
28
|
+
The type-directed lowering fails open to a plain read on any type-resolution hiccup, so it can never break a build; a component with no async interpolations is unaffected.
|
|
29
|
+
|
|
30
|
+
- 53ad08f: Endpoint-declared cache policy; namespace the rpc opts (ADR-0020). All cache/stream policy moves onto the rpc definition and the smart bare call becomes `fn(args)` with no call-site options. Opts are namespaced and kind-scoped by type: `schemas: { input, output, files }`, `cache: { ttl, tags, throttle, debounce, shared }` and `stream: { n }` on read helpers, `outbox` on mutating helpers (a `cache` on a write, or `outbox` on a read, is a compile error). `cache.tags` accepts an arg-derived function. `swr` is removed — SWR is unconditional for replayable reads. `ttl` now defaults to Infinity: an entry is retained for its store's lifetime (the request on the server, the tab on the client), and `shared` alone memoises across requests; a write coalesces only. Endpoint policy also ships to the client so client-side reads honor the declared ttl/refetch clock/tags.
|
|
31
|
+
|
|
32
|
+
BREAKING: `inputSchema`/`outputSchema`/`filesSchema` → `schemas: { … }`; call-site cache options (`fn(args, { ttl, tags, … })`) → endpoint `cache: { … }`, and the smart bare call drops its second argument (`fn(args)`). `.raw(args, init)` keeps per-call transport options unchanged.
|
|
33
|
+
|
|
34
|
+
- 5b2df3f: Type-directed async-cell classification (ADR-0023). A no-marker `computed`/`linked` stream seed now routes by the seed's checker type instead of a syntax heuristic: a stream produced by _any_ expression shape (`computed(obj.stream)`, a conditional) auto-tracks, where before only a bare call/identifier did, and a provably-sync seed skips the runtime probe. Resolved through the warm shadow program and **fails open** to the previous syntactic routing when no program is available; the `await`-marker path is unchanged.
|
|
35
|
+
- 8a61f5b: SSR auto-streaming for pending bare async reads (ADR-0024). A triggered point read still pending at render-return now streams its value into the HTML (shell first, then a resolve chunk) instead of shipping buffered — the server triggers the read and drains it as it settles. A pending read is bounded by its own endpoint `timeout` (which 504s the in-process handler during SSR, shipping a `{ key, miss }` so the client refetches) — there is no separate SSR-stream deadline. A page with no async reads still ships buffered; the Tier-2 blocking barrier and Tier-3 `{#await}` streaming are unchanged.
|
|
36
|
+
- bc83c22: Surface a handler's typed error branches into the generated OpenAPI (ADR-0030)
|
|
37
|
+
|
|
38
|
+
A handler's `error.typed(name, status, schema?)` return branches now flow into the generated OpenAPI spec the same way the success body reaches the 200. The warm server program's new `errorSchemasForModule` query walks the handler's return union, reads each `TypedError` brand's numeric status and projects its `data` type to JSON Schema; errors sharing a status combine under `anyOf`, and a nullary error surfaces its status with no body. The resolved map is baked at build time as `errorJsonSchemas` (paralleling `outputJsonSchema`) and `buildOpenApiSpec` merges each into `responses[status]` — never clobbering the 200. So one plainly-typed handler return documents the full contract: the 200 success body plus every typed error's status and payload, nothing declared twice.
|
|
39
|
+
|
|
40
|
+
`error.typed` now captures the status as a literal type (`Status extends number`) so the brand carries the exact code — a backward-compatible tightening of its return type.
|
|
41
|
+
|
|
42
|
+
- 43289e5: Handler-input-typed RPC surface (ADR-0030 input side). The input-side mirror of the return-typed output surface: the warm server program (ADR-0025) gains an `inputSchemaForModule` query that projects the endpoint's input args to JSON Schema through `jsonSchemaForType` — the SAME `Args` bag `inputCoercionForModule` reads (the exported RemoteFunction's first call-signature parameter, `FormData` dropped), with File/Blob members excluded exactly as `filesSchema` stays out of `inputSchema`. The resolved schema is baked into `RpcRegistryEntry.inputJsonSchema`, and the OpenAPI parameters/request body, MCP `inputSchema`, and inspector input surface fall back to it when the author declared no `schemas.input` VALIDATOR (which still overrides it on every surface). This is a SHAPE description only — it is never wired into runtime validation, so it can't produce a 422; an author who wants runtime narrowing still declares `schemas.input`. A build-projected `inputJsonSchema` also makes a plainly-typed read handler advertisable to MCP/CLI without a hand-written `schemas.input` (shape-only, no runtime gate) — the same role a declared input schema plays. Fails open to `undefined` (no warm program / unresolvable Args / File-only body), so a surface behaves exactly as before.
|
|
43
|
+
- fcbdeb2: error-recovering template parser ([`13244a4`](https://github.com/briancray/abide/commit/13244a43f0d73f7873cafc7e351285b89db2b245))
|
|
44
|
+
- fcbdeb2: render-path survives a render's awaits via a server ALS pathStore (ADR-0033) ([`16d76fc`](https://github.com/briancray/abide/commit/16d76fc8c52d047740e9b1b520a8d045c5fb7ac8))
|
|
45
|
+
- fcbdeb2: hoist independent SSR awaits to the render prefix (ADR-0034) ([`20f017c`](https://github.com/briancray/abide/commit/20f017ceb0646c71d8e9d1f352665801b259419f))
|
|
46
|
+
- fcbdeb2: asyncIterable interpolation → stream cell (ADR-0019 stage D) ([`3293e45`](https://github.com/briancray/abide/commit/3293e45355ded950d487c63d1b5e6c9868e8fadc))
|
|
47
|
+
- fcbdeb2: async-cell classify accepts any async iterable (ADR-0019) ([`41d78e7`](https://github.com/briancray/abide/commit/41d78e791d4260f23ceefc691c7504f3a7f4edec))
|
|
48
|
+
- fcbdeb2: catch→catch updates err in place in reactive {#try} (ADR-0019 D3) ([`439dbd3`](https://github.com/briancray/abide/commit/439dbd3843845a9e74c0334b5cbc3d990897bdcb))
|
|
49
|
+
- fcbdeb2: catch-less {#await}/{#for await} bubbles to enclosing {#try} (ADR-0019) ([`5f8dea8`](https://github.com/briancray/abide/commit/5f8dea8912af37ef20c8eb2a684cb20d4584ff89))
|
|
50
|
+
- fcbdeb2: blocking Tier-2 barrier bakes async-cell values into HTML (ADR-0019) ([`659ed41`](https://github.com/briancray/abide/commit/659ed41cecadd8d5c2e74d2d3a11556d5ac9ff63))
|
|
51
|
+
- fcbdeb2: async (sub)expressions lift to a peek-cell in every template position (ADR-0032) ([`72aaef6`](https://github.com/briancray/abide/commit/72aaef680dffd12b8ff9596c7ec9064b651b3445))
|
|
52
|
+
- fcbdeb2: value-position guard for async interpolations (ADR-0019 stage E) ([`748fcb0`](https://github.com/briancray/abide/commit/748fcb00b6eb35b50650e0320f512e43e419a0ef))
|
|
53
|
+
- fcbdeb2: Breaking: ttl defaults to Infinity — store lifetime, not ttl, ends a read (ADR-0020) ([`7715fd8`](https://github.com/briancray/abide/commit/7715fd8d368c8bd65a533452cbf8ba782355c26f))
|
|
54
|
+
- fcbdeb2: render-path identity for async cells — warm-seed across SSR→client ([`8f123b3`](https://github.com/briancray/abide/commit/8f123b37cf07f6f836dfe034a4b2f68f8559d013))
|
|
55
|
+
- fcbdeb2: type-directed interpolation — warm checker + promise→streaming (ADR-0019 stages B+C) ([`91cb6c6`](https://github.com/briancray/abide/commit/91cb6c65670709f53b2b90d300fcb4b84a95540a))
|
|
56
|
+
- fcbdeb2: interpolation type classifier (ADR-0019, type-directed lowering stage A) ([`9351b18`](https://github.com/briancray/abide/commit/9351b18eadfe6cc4b6e9a690a84204a67e58a964))
|
|
57
|
+
- fcbdeb2: Breaking: endpoint-declared cache policy; namespace rpc opts (ADR-0020) ([`95fa41c`](https://github.com/briancray/abide/commit/95fa41c81ccb62b8f16881a96a878ab6be2872bd))
|
|
58
|
+
- fcbdeb2: reactive {#try} error boundary — both directions (ADR-0019 D3) ([`9b38fe6`](https://github.com/briancray/abide/commit/9b38fe65cc512e245eb6fe6a32ec8cd705a5227d))
|
|
59
|
+
- fcbdeb2: warm-seed a streamed child's late async cells (ADR-0039) ([`a8acee3`](https://github.com/briancray/abide/commit/a8acee3ccf8a1c8f5d6813a844c7129615b3beb5))
|
|
60
|
+
- fcbdeb2: ship endpoint cache/stream policy to the client stub (ADR-0020) ([`ae56080`](https://github.com/briancray/abide/commit/ae5608044e92057be224ee7967ce209bf9dc1005))
|
|
61
|
+
- fcbdeb2: source-agnostic async cells for computed/linked (ADR-0019 D1) ([`bc04cbe`](https://github.com/briancray/abide/commit/bc04cbef933d72243c4d5d082431453e418ef2ee))
|
|
62
|
+
- fcbdeb2: value-aware throwing peek for async-cell reads (ADR-0019 D3.2) ([`c19af9b`](https://github.com/briancray/abide/commit/c19af9b7e18e8d03cc24f8f2dd527ac346ff3476))
|
|
63
|
+
- fcbdeb2: computed/linked wrap + await lowering (ADR-0019 D2) ([`c1dc57d`](https://github.com/briancray/abide/commit/c1dc57dcfab12bd11081e157a653b97cd951db70))
|
|
64
|
+
- fcbdeb2: revive Date/Set/Map/bigint input args via a type-directed wire codec (ADR-0029) ([`c70e2f7`](https://github.com/briancray/abide/commit/c70e2f73d9946763f5fa8a1853942d6174cccb0e))
|
|
65
|
+
- fcbdeb2: {await expr} interpolation → blocking await block (ADR-0019) ([`d11cbc2`](https://github.com/briancray/abide/commit/d11cbc2e995fdce6c1003b1db4ead6996431078e))
|
|
66
|
+
- fcbdeb2: client rpc transform via module graph + reachability guard (ADR-0022 D2/D3) ([`ddf1fd2`](https://github.com/briancray/abide/commit/ddf1fd215cca169421cb0d5bcfba0a728ec196d8))
|
|
67
|
+
- fcbdeb2: computed(getStream()) compile auto-track via trackedComputed (ADR-0019 D1) ([`e964253`](https://github.com/briancray/abide/commit/e964253dbb9d21e9a57acf0f2f94026561cdca86))
|
|
68
|
+
- fcbdeb2: stream non-cache streaming-cell values, adopt post-hydration (ADR-0035 phase 1) ([`f553731`](https://github.com/briancray/abide/commit/f5537310af6396ea9359e5dc8f7fddafe301c4a1))
|
|
69
|
+
- fcbdeb2: render-boundary streaming foundation + ADR-0039 ([`f83d828`](https://github.com/briancray/abide/commit/f83d82865eeb6a3e4ccc1cb824f24a9180755a89))
|
|
70
|
+
- fcbdeb2: project handler input type into mcp/cli/openapi surfaces (ADR-0030 input side) ([`fd13fa1`](https://github.com/briancray/abide/commit/fd13fa185ba2617f350d416199016bd523c14d0d))
|
|
71
|
+
- 6749824: Client-side input validation, always on (ADR-0026). When an rpc endpoint declares `schemas: { input }`, the client `remoteProxy` now validates the typed args against that schema before the fetch and, on a definitive failure, throws an `HttpError` shaped identically to the server's 422 (`kind: 'validation'`, the same field-error `data`) — no round-trip. A validator that _throws_ (a non-portable / async-resource refinement that can't run in the browser) falls through to the server instead of failing the call, so adding a schema can never break a request. Server validation stays authoritative and unconditional — the client check is a UX optimization only. No configuration: it runs whenever an input schema is present.
|
|
72
|
+
- b0cb79a: Remove the durable outbox and other unreachable surface — a tighter core
|
|
73
|
+
|
|
74
|
+
**Breaking:** the durable-delivery outbox is gone. The `@abide/abide/ui/outbox` export (`outbox()`, `outbox.retry()`, `GlobalOutbox`), the `outbox: true` rpc option (POST/PUT/PATCH/DELETE), the reserved `kind: 'queued'` error, and `OutboxEntry` are all removed. A mutating rpc now simply fetches and throws; durable local-first delivery is left to userspace (wrap the call, park failures in your own persisted queue via `fn.raw`). `RemoteFunction` loses its `Durable` type parameter and `.outbox` face; `remoteProxy`'s `DurableOptions` is renamed `RemoteProxyOptions`.
|
|
75
|
+
|
|
76
|
+
Removing outbox also drops the client persistence stack it was the only caller of (`persist`, `localStoragePersistence`, `PersistenceStore`/`PersistHandle`) and a whole build-time type-query (`outboxForModule`) from the warm server program.
|
|
77
|
+
|
|
78
|
+
Alongside it, several never-wired internals were deleted: the withdrawn `Scope` capability methods (`record`/`persist`/`broadcast`/`undo`/`redo`/`canUndo`/`canRedo`) and their `history`/`sync` backends, the unused `Scope.child`/`Scope.root` tree helpers, and the per-patch `PatchEvent.inverse` pre-image (computed on every mutation but read by nothing since the journal left). No behavioural change for app code that didn't use these.
|
|
79
|
+
|
|
80
|
+
### Patch Changes
|
|
81
|
+
|
|
82
|
+
- d5c3a04: Route the rpc method + `outbox` build transforms through the warm server program (ADR-0025 phase 2)
|
|
83
|
+
|
|
84
|
+
Phase 1 warmed one per-root `ts.Program` over the server module graph and used it only for streaming detection (gated on a build-cost budget). Phase 2 lifts that budget — the ~0.5 s cold cost is paid once per root, amortized, and always fail-open — and routes the two remaining text-scanners through the same warm program:
|
|
85
|
+
|
|
86
|
+
- **HTTP method** now resolves off the export helper's _symbol_ (following import aliases and re-exports), so `export const x = read(fn)` where `import { GET as read }` correctly types as `GET` in the generated `rpc.d.ts`, where the `RPC_EXPORT` regex read nothing.
|
|
87
|
+
- **`outbox`** now resolves off the opts object's property _type_, lifting "must be an inline literal" to "must be statically known" — an imported const (`outbox: OUTBOX_ENABLED`) resolves to its literal `true` instead of erroring, and an `outbox:` mention inside the handler body is ignored.
|
|
88
|
+
|
|
89
|
+
Every query fails open to today's regex/char-scan (no warm program, an unresolvable node, or a checker throw → byte-identical to before), so this can only harden, never break, a build. The hand-rolled scanners remain as that fallback and as the residual span-finder for splicing.
|
|
90
|
+
|
|
91
|
+
Also adds a one-line build-start log (`[abide] building client bundle…`, one-shot builds only) so the program-warming pause at the start of `abide build`/`compile` isn't mistaken for a hang.
|
|
92
|
+
|
|
93
|
+
- 831ae88: Streaming rpc detection resolves through a warm `ts.Program` (ADR-0025). Whether a handler streams (returns `jsonl()`/`sse()`) is now decided by the handler's **return type** via a warm per-project-root program, instead of scanning the handler body for the call name — which fixes the wrapper-indirection blind spot where a handler returning a stream through a helper function was misclassified as a point read on the client. Built once per project root (a one-time boot cost, reused across every rpc in the build) and **fails open** to the previous char-scan.
|
|
94
|
+
- 95b4b13: Server-side type-directed query/form coercion (ADR-0028). A GET or form-encoded request delivers every field as a string, so a plain `z.object({ n: z.number() })` used to 422 on `?n=2`. The warm server program (ADR-0025) now reads the endpoint's wire `Args` type and stamps a build-time `coerce` plan of exactly which fields are numeric/boolean; `parseArgs` coerces those string values to their typed value before validation. Only fields the type declares numeric/boolean are coerced, so a string field that merely looks numeric (an id, a zip code, `'1.0'`) stays a string; a self-coercing schema's loose input is left for the schema to coerce; and with no warm program every field stays a string exactly as before (fail-open). Closes the long-standing `parseArgs` query-coercion TODO and completes the server half of client-side validation (ADR-0026).
|
|
95
|
+
- aa21b7c: Type-directed wire codec — output/response path (ADR-0029)
|
|
96
|
+
|
|
97
|
+
A handler's structured RETURN values now round-trip to the client instead of being lost or crashing. Previously `json()` serialized via plain `JSON.stringify`, which dropped a `Set`/`Map` to `{}` and threw a 500 on a `bigint`.
|
|
98
|
+
|
|
99
|
+
- **Server encode (all clients).** `json()` now serializes through a value-directed wire replacer: a `Set` crosses as a JSON array, a `Map` as an array of `[key, value]` entries, a `bigint` as a digit string, a `Date` as an ISO string. The wire stays honest, tag-free JSON, so curl / OpenAPI SDKs read it and it matches the generated schema.
|
|
100
|
+
- **Client decode (abide clients).** The warm server program resolves the handler's success-body type to a per-field output plan (`date`/`bigint`/`set`/`map`) and bakes it onto the client `remoteProxy` stub. The proxy revives those fields off a decoded response, so a `Set`/`Map`/`bigint`/`Date` return arrives as the real runtime type. A genuine array is untouched; no plan / an unrevivable value fails open to the honest-JSON form.
|
|
101
|
+
- **Projector coherence.** The `ts.Type` → JSON Schema projection now maps `Set<T>` → `array` and `Map<K,V>` → an array of `[K,V]` tuples, so the generated OpenAPI 200 matches the actual bytes.
|
|
102
|
+
|
|
103
|
+
Deferred: nested/recursive descent, streaming-frame (`jsonl`/`sse`) encoding, and server-side in-process revival.
|
|
104
|
+
|
|
105
|
+
- 52a7e5c: Type-directed structured input wire codec (ADR-0029). Generalizes ADR-0028's scalar query coercion to structured value kinds: the same warm server program now classifies a top-level `Args` field as a `Date`/`Set`/`Map` (by symbol identity through the checker) or a `bigint` (by type flag) and stamps it into the endpoint's build-time `coerce` plan. `parseArgs` revives each declared field from its plain-JSON wire form before validation — an ISO string → `Date`, a numeric string → `bigint`, a JSON array → `Set`, a JSON entries array (or object) → `Map` — so a `Date` GET argument or a non-abide JSON client's structured body reaches the handler as the right runtime type instead of a raw string/array. Top-level fields only; the wire stays tag-free (type-directed, not tag-directed) so a plain-JSON / OpenAPI client still reads it. Fail-open throughout: no plan, an unrevivable value, or an already-typed value (the abide client's own ref-json body, which already round-trips these kinds) passes through as today's behavior — never a throw. The symmetric response/output codec is deferred (the response path serializes with plain `Response.json`, which needs a server-side encode step first).
|
|
106
|
+
- 8b9505d: Handler-return-typed RPC output surface (ADR-0030 D2). A `ts.Type` → JSON-Schema projector (`jsonSchemaForType`) generates an rpc's OpenAPI 200 / MCP `outputSchema` / inspector output shape from the handler's return type when no `schemas.output` validator is declared — the complement of `jsonSchemaForSchema` (which projects a runtime validator). It covers the subset abide's `json()`/`jsonl()` emit (primitives, string-literal `const`/`enum`, objects with `required`, `Record` → `additionalProperties`, arrays, tuples, unions with optional-stripping, `Date` → `date-time`, `bigint` → string per ADR-0029) and fails OPEN — an unsupported/unresolvable type projects to permissive `{}` (omitted at the top level), with a mandatory cycle guard so a recursive type can't infinite-loop; it never throws, so a projection gap can't break a build.
|
|
107
|
+
|
|
108
|
+
The warm server program gains a `returnBodySchemaForModule` query that resolves the same success-body `ts.Type`(s) as `returnBodyForModule` and runs the projector. Since the OpenAPI/MCP/inspector surfaces render off the runtime rpc registry (not the build-time program), the resolver plugin BAKES the projected schema into the server `defineRpc` call — stamped as `outputJsonSchema`, exactly like the ADR-0028 `coerce` plan — so the registry entry carries it at runtime. A declared `schemas.output` validator still overrides the projection (a runtime narrowing the type can't express); with neither, the surface omits the response schema exactly as before.
|
|
109
|
+
|
|
110
|
+
- 32a2203: Handler-return-typed RPC surface foundation (ADR-0030). The warm server program (ADR-0025) gains a `returnBodyForModule` query: it reads the endpoint's success-BODY type off the handler's return type the same way streaming detection already reads it — unwrap `Promise`, drop the `TypedError` branches, take each success `TypedResponse<Body>` body (the type-side mirror of `RpcHelper`'s `SuccessBody<R>`). A streaming endpoint reports its per-FRAME type (the `AsyncIterable` element) and `streaming: true`, so a surface can describe one streamed item. Like every other server-program query it fails open to `undefined`. This is the output-side sibling of ADR-0028's `inputCoercionForModule` — the handler's return becomes the single source for the generated surfaces so a plainly-typed handler needs no redundant `schemas.output`. Consumer wiring (OpenAPI 200 / MCP `outputSchema` / `.d.ts`) is deferred: those surfaces want JSON Schema and the only projector today (`jsonSchemaForSchema`) runs off a runtime Standard-Schema object, not a TS type — a TS-type→JSON-Schema projector is the follow-up. Client typing needs nothing here: the caller's `Return` already flows natively from the imported rpc module (ADR-0022).
|
|
111
|
+
- 3160daa: Factor the post-DCE metafile walk into a reusable analysis seam and add a bundle-budget diagnostic (ADR-0031 D2). The client build's `build.onEnd` reachability pass is now `bundleGraphFromMetafile` — one walk of `Bun.build`'s metafile into a `BundleGraph` (`{ modules, importerChain }`) that both the side-crossing guard (unchanged behavior) and a new consumer read. First consumer: a non-blocking bundle-budget warning — a project `src/` module that survives tree-shaking into the client bundle over 512 KiB earns an `abideLog.warn` with its import chain, so an accidentally-huge input becomes observable without a new bundler pass. Never fails the build; the only hard `onEnd` failure remains a real client-reachable `$server/*` violation. ADR-0031 D1 (sharpening the post-await tracking lint with the script-region classifier) is deferred: the spike found the classifier precise but the current warning already never fires on the inert captures it was meant to stop flagging.
|
|
112
|
+
- 43289e5: Render-path identity now holds for async cells nested in control flow and across a render's awaits (ADR-0033), fixing warm-seed misses that made such cells refetch and flash on hydrate. Two parts. First, `generateSSR` pushes the same render-path segment the client pushes inside `{#each}`/`{#if}`/`{#switch}` (keyed key / keyless row index for each; `then`/`else` or switch branch-index) — previously only child components got a segment, so a cell in a loop/branch composed a divergent scope id server-vs-client. Second, the render-path base itself now survives a render's `await`s: `withPath`/`withPathFrom` set `CURRENT_PATH` and restored it synchronously, but an SSR render's `build()` returns a pending promise awaited outside the wrapper, so the base was restored the instant a render yielded — any scope created past that await (a 2nd sibling child, anything after a page-level cell barrier, a child two awaits deep) composed against an ancestor's path. The swappable `ambientPathBacking` widens from `{get,set}` to `{run,get}`; the server backs `run` with a dedicated `AsyncLocalStorage` (`pathStore`) whose value is inherited by the render's post-await continuations, and `CURRENT_PATH.current` becomes read-only. The client keeps its synchronous save/restore (its mount is synchronous). No codegen change; `CURRENT_SCOPE` was audited and does not share the bug.
|
|
113
|
+
- a6c5749: Independent SSR awaits now render in parallel, not in series (ADR-0034). An independent blocking `{await X}` and streaming `{#await Y}` used to render in the SUM of their latencies: the blocking await halts the sequential render walk, and the streaming flight is a deferred thunk drained only after `render()` returns, so a streaming read behind a blocking await couldn't start until it settled. The SSR back-end now hoists each _hoistable_ await's promise-START into the synchronous render prefix (server-only, via a new plumbing `$$flight` helper) so independent flights overlap — an await is hoistable when its promise references only component-scope names (no `{#for}`/`{:then}`/snippet binder, no async cell), is not inside a conditional branch, and is statically-single. The block's boundary markers, `$ctx` block-id, the RESUME/streaming wire, and the entire client build are untouched, so hydration is byte-identical and the client stays fully reactive. On the kitchen-sink `templating/async` page this cuts SSR from ~842ms to ~427ms (max, not sum). Transparent: no code change for app authors; a page with a single or no async await is unaffected.
|
|
114
|
+
- a6c5749: Non-cache streaming peeks stop flashing `loading…` on hydrate (ADR-0035). A bare async peek whose loader is a plain (non-cache) promise — `{loadProfile(attempt)?.name}` — shipped pending in the SSR shell and the client cold-re-ran its seed on hydrate, so it showed `loading…` for the full latency even though the server had already computed the value. Unlike a `{#await}` block (streams its resolved HTML fragment) or a cache-backed peek (streams its cache entry via `__abideResolve`), a plain-promise peek had no server→client value channel. It now does: a streaming cell records its settled value in a per-request partition, the page renderer streams it after the shell as an `__abideResolve({ cellKey, value })` chunk keyed by the cell's render-path id, and the client adopts it as a POST-hydration reactive update (deferred a microtask so it lands after the pending markup is claimed — no `assertClaimedText` desync). Values (not promises) are recorded so a cell that stays pending all request can never hang the response; only cells settled by the drain are streamed (a page with a blocking `{await}` or barrier — the common case — is covered; a pure-streaming-peek page cold-runs as before). Reactivity and the RESUME/`$resume` wire are untouched. Transparent behaviour improvement; no API or config change.
|
|
115
|
+
- 56b948e: An inline (bare smart read) rpc call now seeds the SSR warm snapshot regardless of HTTP method, so it hydrates warm instead of re-firing after render (ADR-0036). Previously only GET entries rode the warm snapshot: a non-GET rpc consumed inline in render position — e.g. `{html(highlightCode({ code, lang })?.html)}` where `highlightCode` is a POST (POST so the large `code` payload rides the body, not a multi-KB query string) — ran the handler in-process during SSR **and** re-fetched on the client after hydration, firing the call twice per page load (a second POST can 500 on a unique constraint / double-mutate). The `{ GET }` gate conflated two concerns: _seeding_ the SSR-computed body (safe for any method — the value already exists) and _re-firing_ the stored request unprompted on invalidate/refresh/staleness (safe only for GET). They're now decoupled: seeding is gated on "the entry carries a wire request" (any method), while re-firing stays GET-only — `REPLAYABLE_METHODS` is unchanged, so a write is still coalesce-only (re-submittable), never SWR-retained, and never auto-replayed from the snapshot. A seeded write is read warm once during hydration; a later reactive re-read re-issues it live with real args. Keying already includes canonical-JSON body args, so each inline write seeds under its own distinct key. Verified: an inline POST hydrates warm with zero post-hydration refetch. No API or config change.
|
|
116
|
+
- 126474d: SSR await/try block ids are now keyed by render-path instead of a single flat counter (ADR-0037), making block-id allocation congruent SSR↔client even under concurrent renders. Previously every `await`/`try` block drew from one monotonic counter shared across a component and the children it inlines (`$ctx.next++` server / `RENDER.blockId` client), which only stayed congruent because sibling child renders ran strictly sequentially — the blocker to parallelizing them. A block id is now `${render-path}:${n}` (a per-path counter), reusing the ADR-0033 AsyncLocalStorage render-path so each child's ids live in their own namespace; a pathless render (a top-level page with an empty route key, or a bare test component) keeps the plain `0,1,2…` form, so the common case is unchanged. DOM adoption was already positional (boundary-marker ids are not compared, only the `RESUME` manifest key is), so the id widened `number → string` with no parser change. This is a transparent refactor — id allocation order is unchanged, so behaviour is identical and the full hydration suite stays green. On that foundation, **sibling `<Child/>` renders now run in parallel during SSR** (ADR-0037 Phase 2): a hoistable top-level-spine child render (childless, prefix-evaluable props, no `bind:`) starts in the render prefix as an isolated `$$flight` and is awaited at its position, so independent cards render in ~max not ~sum of their latencies while the HTML still assembles in source order. Each hoisted render runs under its own async-cell barrier list (`isolateCellBarrier`, a server-only per-render AsyncLocalStorage) so concurrent siblings never `splice(0)`-drain each other's cells. Transparent — same HTML, same hydration; only independent child work overlaps. No API or config change.
|
|
117
|
+
- dc064ac: A route's layout layers now render in parallel during SSR (ADR-0038). Previously `renderChain` rendered the layout chain (outermost layout → … → page) sequentially, so a route with N layouts each doing an independent I/O read flushed its shell in the sum of their latencies. Now the layers render via `Promise.all`, each under `isolateCellBarrier` (so their async-cell barriers don't cross-drain) and its distinct route-key `withPath` (so path-keyed block ids stay collision-free) — the html fold and state/awaits/resume aggregation run after all settle and are order-independent, so output and hydration are byte-identical, just faster. A lone page with no layouts still renders directly (no wrapping overhead, same bare-read streaming timing). Server-only; reuses the ADR-0037 primitives. Verified with a timing test (three layers ~40ms each render in ~max not ~sum) and the full hydration suite. No API or config change.
|
|
118
|
+
- 3bfdcb6: A slow hoistable child component now STREAMS its fragment during SSR instead of blocking the shell (ADR-0039). Previously every hoistable `<Child/>` was awaited inline, so a page's shell couldn't flush until its slowest child settled. Now `generateSSR` reserves each hoistable child's output slot and, after the walk, `finalizeStreamedChildren` decides per render: a child whose isolated flight has already SETTLED inlines its html byte-identically to before (so an all-fast page is completely unchanged — one microtask, no macrotask, same wire), while a still-PENDING child gets an empty `abide:await:CHILDPATH` boundary in the shell and streams its `<abide-resolve>` fragment when it settles. The boundary id is the child's render-path, congruent with the client. The client emits a dual-mode `mountStreamedChild` for the same children: it probes the hydration cursor and adopts either an inlined `[ … ]` range or a swapped-in streamed boundary, with a plain create-mode mount on client navigation. Verified: three ~40ms sibling cards stream in ~max not ~sum, a streamed child hydrates with no desync, and fast/existing children stay byte-identical. Remaining refinement: warm-seeding a streamed child's late-resolving async cells (a blocking `{#await}` inside it already adopts via its resume delta). No API change.
|
|
119
|
+
- fcbdeb2: clear stale rows on eachAsync reseed ([`0173073`](https://github.com/briancray/abide/commit/01730732141c7a7f54001a4a9ba35b6749757412))
|
|
120
|
+
- fcbdeb2: reap embedded server on failed boot, bound readiness probe, escape plist XML ([`04cee1c`](https://github.com/briancray/abide/commit/04cee1c0f60098b55f69321d407886bbf23fae53))
|
|
121
|
+
- fcbdeb2: green up main — biome lint errors block the release run ([`0833487`](https://github.com/briancray/abide/commit/08334878be6191f7994543997a4b8403f36c4ebe))
|
|
122
|
+
- fcbdeb2: single source of truth for the proxied server subdirs ([`094892b`](https://github.com/briancray/abide/commit/094892b7de07751277bf735271080971daaa2384))
|
|
123
|
+
- fcbdeb2: guard streamed cancel race that logged a stray "Controller is already closed" ([`0bbc93c`](https://github.com/briancray/abide/commit/0bbc93cea4192cb2104e6ff83dd231c858d25fd4))
|
|
124
|
+
- fcbdeb2: one schema resolver for all surfaces — fixes CLI drift ([`1083327`](https://github.com/briancray/abide/commit/10833276b5ddb00d1267f6736cc375de732c15a2))
|
|
125
|
+
- fcbdeb2: stop the SSE face dropping Set/Map/bigint; unify the wire codec ([`17ca2d2`](https://github.com/briancray/abide/commit/17ca2d219450af1300ef25182eb16c4db6f5c7ca))
|
|
126
|
+
- fcbdeb2: mint the warm-seed cell key through one shared warmSeedKey ([`233787e`](https://github.com/briancray/abide/commit/233787e0c330e8c43926fcc46df6de77ece3116c))
|
|
127
|
+
- fcbdeb2: rename Socket.broadcast() to publish() to match Bun ([`250c883`](https://github.com/briancray/abide/commit/250c883a035cf9748129d4aa3e17b65a5a5a6189))
|
|
128
|
+
- fcbdeb2: fold REACTIVE_CALLEES into signal-ref lowering ([`269b762`](https://github.com/briancray/abide/commit/269b7623d422f4b1e556e46e8f8c7b68017f874d))
|
|
129
|
+
- fcbdeb2: rename Subscribable to NamedAsyncIterable ([`2d17ed2`](https://github.com/briancray/abide/commit/2d17ed23b9c3c5c18adb56feadaf1882c4d991c3))
|
|
130
|
+
- fcbdeb2: share one lenient percent-decode helper ([`3b7f320`](https://github.com/briancray/abide/commit/3b7f32088b514f49dd088893ebd7318c4cc0b8bb))
|
|
131
|
+
- fcbdeb2: drive LSP tokens from the parse, delete both lexers ([`4301e97`](https://github.com/briancray/abide/commit/4301e97abd8b612ebcfb6639426447947046c6b5))
|
|
132
|
+
- fcbdeb2: swap streamed SSR fragments via an inline script, dropping the resolved-frame runtime path ([`431aee3`](https://github.com/briancray/abide/commit/431aee3c406b8181e039a86b04c74192b4222964))
|
|
133
|
+
- fcbdeb2: drop the separate SSR-stream deadline; endpoint timeout governs (ADR-0024) ([`48e45d9`](https://github.com/briancray/abide/commit/48e45d9cf7c922cb9a846829f7ef5b2acee527de))
|
|
134
|
+
- fcbdeb2: thread rpc build stamps as one named RpcBuildStamps payload ([`493a6ac`](https://github.com/briancray/abide/commit/493a6ac0467e6d77ef180e807d769747270c1fd4))
|
|
135
|
+
- fcbdeb2: one-shot cell warm-seed + structural render-path key alignment ([`4a5383f`](https://github.com/briancray/abide/commit/4a5383f64ebadc511a8f55809f899b98d0a734d2))
|
|
136
|
+
- fcbdeb2: migrate disconnected.abide to {#if}/{#for} block syntax ([`57bd904`](https://github.com/briancray/abide/commit/57bd904fd84250c7e1cfd97d84483907fc25cbf3))
|
|
137
|
+
- fcbdeb2: pin the runtime and shadow front-ends to one async-lift plan ([`58e9691`](https://github.com/briancray/abide/commit/58e9691eea870650bf219a33cef2b523f3c5dc10))
|
|
138
|
+
- fcbdeb2: replace reachable's poll registry with a TTL memoize ([`5bd426e`](https://github.com/briancray/abide/commit/5bd426ef4701b2da11531cc30779bd2a953cac20))
|
|
139
|
+
- fcbdeb2: restore in-place HMR for streamed children; review cleanups ([`5eec25d`](https://github.com/briancray/abide/commit/5eec25d0fb27d688e2caa0f180968de5fbefe9c2))
|
|
140
|
+
- fcbdeb2: remove the inspector Reactive tab + PATCH_BUS ([`64e4da9`](https://github.com/briancray/abide/commit/64e4da957144fea6f7a6ecbd4415bf1db219f7c3))
|
|
141
|
+
- fcbdeb2: sync AGENTS.md/README to the ADR-0020 rpc API; format touched files ([`6dcc3dd`](https://github.com/briancray/abide/commit/6dcc3dd5a21cb334bf742e0fd6ef461013eb3cfb))
|
|
142
|
+
- fcbdeb2: refresh getHello templates for NamedAsyncIterable + schemas.input/output ([`7233a9b`](https://github.com/briancray/abide/commit/7233a9b11e663655f87f32e08b5ea98d20cdba7d))
|
|
143
|
+
- fcbdeb2: cache parsed SourceFiles across shadow programs ([`7241ca2`](https://github.com/briancray/abide/commit/7241ca244e1c6bd84dfb94d3c20ff1cfe70cc752))
|
|
144
|
+
- fcbdeb2: remove component hot-module replacement ([`7469c1d`](https://github.com/briancray/abide/commit/7469c1d1b1f2c175c2facfe4288ad81b0f89d063))
|
|
145
|
+
- fcbdeb2: stop stale-worker 500s; move codegen off the boot hot path ([`7c5b241`](https://github.com/briancray/abide/commit/7c5b2417c3ba6737d897c264837ca66a79282a99))
|
|
146
|
+
- fcbdeb2: sort imports ([`7fcd071`](https://github.com/briancray/abide/commit/7fcd0714ce337359bc11347fa243dff64ed682de))
|
|
147
|
+
- fcbdeb2: share block-keyword vocabulary so LSP highlighting can't drift ([`95ac19a`](https://github.com/briancray/abide/commit/95ac19a058574f8bba36aae64d20791c84a4e820))
|
|
148
|
+
- fcbdeb2: drop the runtime-helper binding backstop ([`9ba3513`](https://github.com/briancray/abide/commit/9ba3513432dd5639f93c0a61555d70ba510ff359))
|
|
149
|
+
- fcbdeb2: share the anchored-branch skeleton across await and try blocks ([`a301f0e`](https://github.com/briancray/abide/commit/a301f0e101e314ef904f4f26cd157937de2a8bd2))
|
|
150
|
+
- fcbdeb2: green up main CI — biome lint + strict-consumer typecheck ([`a39e030`](https://github.com/briancray/abide/commit/a39e0307e69e738717d9827464141a85a99dd1e4))
|
|
151
|
+
- fcbdeb2: remove the client→inspector BroadcastChannel bridge ([`a4920ea`](https://github.com/briancray/abide/commit/a4920ea3d969bd0812e4146acb80b775ba8807cf))
|
|
152
|
+
- fcbdeb2: surface diagnostics when the .abide source can't be read ([`a6b1881`](https://github.com/briancray/abide/commit/a6b188138e354fee2b4adb6ae80c4882d78c28c4))
|
|
153
|
+
- fcbdeb2: log streaming rpc handler errors server-side ([`a81d99d`](https://github.com/briancray/abide/commit/a81d99d442ae1f1ba73a98e5c5dc2a51078ba2d2))
|
|
154
|
+
- fcbdeb2: bound the stream-swap node removal to the matching close marker ([`aa3bce6`](https://github.com/briancray/abide/commit/aa3bce6bcb5ddfe1d29f76d8abae3e58d2b4a89d))
|
|
155
|
+
- fcbdeb2: revive wire fields in cache()/peek(); evict idle lifecycle channels ([`b1ffe5a`](https://github.com/briancray/abide/commit/b1ffe5a7676066e71af4ce3bfc7124ddb9ab4bd9))
|
|
156
|
+
- fcbdeb2: consolidate framework plain-text responses ([`b8cbb72`](https://github.com/briancray/abide/commit/b8cbb721e7cb6fbe86016db197d942ec413fc211))
|
|
157
|
+
- fcbdeb2: hoist three duplicated constants to shared origins ([`d0ee9df`](https://github.com/briancray/abide/commit/d0ee9dfeb35582646e33bb317f4c219141fad4d1))
|
|
158
|
+
- fcbdeb2: push render-path segments for each/if/switch rows and branches ([`d2d927a`](https://github.com/briancray/abide/commit/d2d927ac814622e4b258db944d75c930d64733c7))
|
|
159
|
+
- fcbdeb2: guard linked seed arg for noUncheckedIndexedAccess (consumer tsconfig) ([`d643b2b`](https://github.com/briancray/abide/commit/d643b2b467a1ec03b493af8f38a4e3e1f5b74bde))
|
|
160
|
+
- fcbdeb2: satisfy noUncheckedIndexedAccess in the template parser ([`dad539d`](https://github.com/briancray/abide/commit/dad539dd039f2ae44e159c2b544a9d27953b780b))
|
|
161
|
+
- fcbdeb2: fold hydratingSlot + wakeHydrationPeeks into hydrationWindow ([`dd9c682`](https://github.com/briancray/abide/commit/dd9c682d732f9d89c3412018f9c5656b58025ddc))
|
|
162
|
+
- fcbdeb2: move URL-shape route decisions behind createAppRouteResolver ([`e639324`](https://github.com/briancray/abide/commit/e63932426d81268f9fbc75806a7e26263f310ca0))
|
|
163
|
+
- fcbdeb2: refresh AGENTS/README for the wire codec, typed-error OpenAPI surface, and inline {await} ([`eecfe14`](https://github.com/briancray/abide/commit/eecfe145389e8c11f7e83c8d2babbc4ea3e92732))
|
|
164
|
+
- fcbdeb2: remove the dead scope-label plumbing ([`f068887`](https://github.com/briancray/abide/commit/f0688875b77677b670b145ce90982e93e9a1a545))
|
|
165
|
+
- fcbdeb2: gate refresh/invalidate reload on a live tracking reader ([`f0af782`](https://github.com/briancray/abide/commit/f0af782936a87a18cbb4f70c3926315cf6180b31))
|
|
166
|
+
- fcbdeb2: one origin for the rpc/socket shim global names ([`f0baaaf`](https://github.com/briancray/abide/commit/f0baaaffc04d55b32b906fff454221f27b190366))
|
|
167
|
+
- fcbdeb2: one wire-field decoder for input and output ([`f16f005`](https://github.com/briancray/abide/commit/f16f005933509dc5b1e1ee824a3bdca5cf036acd))
|
|
168
|
+
- fcbdeb2: extract the /__abide/* plumbing router from createServer ([`f8f5e22`](https://github.com/briancray/abide/commit/f8f5e227eff0149766281cd254193544099a638b))
|
|
169
|
+
- fcbdeb2: props type honors the destructure annotation — types work like TS (ADR-0022 D4) ([`fd3f74f`](https://github.com/briancray/abide/commit/fd3f74ffa9e938f1c87ec648fe1e4ccad20bde9b))
|
|
170
|
+
- afccb13: `abide check` now counts slotted content toward a required `children` prop. The shadow's completeness check treated `children` like any other prop, so `<Card>text</Card>` mounting a component that declares `children: Snippet` was falsely flagged as missing `children` — forcing `children?` optional as a workaround. Slotted content now satisfies the requirement (matching the runtime, which lowers it to the `children` layer), while a childless `<Card />` is still flagged. All other completeness and excess-prop checks are unchanged.
|
|
171
|
+
- 7e4309e: `bind:prop` now works on components, mirroring `bind:attr` on elements. `<Child bind:value={target} />` passes the prop with a two-way write-back channel — `target` takes the same forms an element bind does (an lvalue, or a `{ get, set }` accessor). The child reads the prop as usual; if it writes the prop (`value += 1`) or forwards it to another `bind:` (`<input bind:value={value} />`), those writes flow back to the parent's `target`.
|
|
172
|
+
|
|
173
|
+
There is no child-side marker: bindability is inferred from usage. A prop the child only reads stays a cheap read-only derive (unchanged); one it writes/forwards is upgraded to a writable cell that is a pass-through to the parent when bound, and a local reseeding cell when not (so a component still works standalone). Previously `bind:` on a component was a silent no-op passed through under a `bind:`-prefixed prop key.
|
|
174
|
+
|
|
175
|
+
- 4020519: Reactive-doc `Set`/`Map` mutations now emit a patch. The doc codec already serializes `Map` and `Set`, but a mutating method on a doc-held collection (`model.tags.add(x)`, `model.byId.set(k, v)`, `.delete`/`.clear`) lowered to a bare in-place call that mutated the live tree by reference and fired no patch — so readers never re-rendered and undo/persistence/sync never saw the change. These now route through the same clone-apply-replace path the in-place array methods use (`$$mutateDocArray` generalized to `$$mutateDocContainer`, covering Array, Map and Set); the mutating method names are disjoint across the three kinds, so the container kind is decided at runtime with no compile-time type check.
|
|
176
|
+
- eaa1829: `done()` / `peek()` are null-tolerant, so a probe fed a pending peek-lift no longer 500s
|
|
177
|
+
|
|
178
|
+
Under ADR-0032 a promise/iterable subexpression peek-lifts to `undefined` while pending, so writing a probe inline in a template — `{done(getFeed())}` / `{peek(getFeed())}` — hands the probe `undefined` on the first render pass. `done()` now returns `false` and `peek()` returns `undefined` on a nullish argument instead of throwing on `subscribable.name`, turning that pending render from an SSR 500 into a graceful empty state. Probing in script (`const closed = state.computed(() => done(feed))`) remains the correct idiom for an accurate stream probe, since a lifted `AsyncIterable` peek yields the latest frame, not the source.
|
|
179
|
+
|
|
180
|
+
## 0.49.0
|
|
181
|
+
|
|
182
|
+
### Minor Changes
|
|
183
|
+
|
|
184
|
+
- dfb4f13: props import required + additive route-shape type; drop ambient children ([`0dbe248`](https://github.com/briancray/abide/commit/0dbe248fc959f3ca8168fb83e6f30619a17eff3b))
|
|
185
|
+
- dfb4f13: slotted content rides the children prop key as a Snippet ([`0de19e5`](https://github.com/briancray/abide/commit/0de19e594dabb6ddd92b08d5e473f13296f17247))
|
|
186
|
+
- dfb4f13: publish abide/ui/props module for the props reader ([`197c1a9`](https://github.com/briancray/abide/commit/197c1a900c0ea81b40d1cbb4a6bec1e021b9e932))
|
|
187
|
+
- dfb4f13: type element attach node param from the element tag ([`444ef35`](https://github.com/briancray/abide/commit/444ef356372f8fc39a0b5786bca2f70dcf750c53))
|
|
188
|
+
- 951e90b: `props` is now a required import (`@abide/abide/ui/props`), resolved by import binding like `state` — a bare ambient `props()` no longer works, and every component that reads props must `import { props } from '@abide/abide/ui/props'`.
|
|
189
|
+
|
|
190
|
+
`children` is now an ordinary declared prop instead of an ambient callable: read it with `const { children } = props<{ children: Snippet }>()` (`Snippet` from `@abide/abide/shared/snippet`). Slotted content (`<Panel>…</Panel>`) and an explicit `children={aSnippet}` attribute now set the same `children` prop key (slotted content wins if both are present). `props<T>()` stays additive — a page/layout still gets its route-param shape auto-typed, and declaring `children` (or any other prop) only adds to it.
|
|
191
|
+
|
|
192
|
+
The `Snippet` type's generic changed from its internal payload to its call arguments: `Snippet<Args extends unknown[] = []>` is now `(...args: Args) => SnippetValue` — `children` is `Snippet` (invoked `children()`), a row/label snippet is `Snippet<[Item]>` (invoked `row(item)`). The former payload-generic form (`Snippet<Payload>` describing the value flowing through) is gone; the internal payload is the newly exported `SnippetValue`.
|
|
193
|
+
|
|
194
|
+
**Behavior change:** an unguarded `{children()}` on a component mounted without children now throws at render, where it previously rendered nothing. Guard with `{#if children}{children()}{:else}…{/if}`, or declare `children: Snippet` as a required (non-optional) prop so `abide check` catches missing children at the call site.
|
|
195
|
+
|
|
196
|
+
Migration: add `import { props } from '@abide/abide/ui/props'` to every component that calls `props()`; for any component that reads `children`, add `import type { Snippet } from '@abide/abide/shared/snippet'` and declare it — `const { children } = props<{ children: Snippet }>()` (or `children?: Snippet` if optional).
|
|
197
|
+
|
|
198
|
+
### Patch Changes
|
|
199
|
+
|
|
200
|
+
- 4a6bf93: mount a reactive/loop-bound component tag by its value, not the cell ([`32a7cb8`](https://github.com/briancray/abide/commit/32a7cb8bdef0800d76b418eefbe550b0a939cd73))
|
|
201
|
+
- dfb4f13: correct UiProps.children to the ordinary prop-thunk shape ([`33a0de7`](https://github.com/briancray/abide/commit/33a0de72dc2fe6ce4a0e025e4158ab192e47f1f0))
|
|
202
|
+
- c7d25e4: type state<T>(undefined) and binding-annotated state() as T | undefined ([`3c40d99`](https://github.com/briancray/abide/commit/3c40d9981617968330a00bc2f034456b80365419))
|
|
203
|
+
- c7d25e4: await a snippet whose body fills a {children()} slot ([`4c2744b`](https://github.com/briancray/abide/commit/4c2744bc1aa42728a80adb3426a77c02c79b30d4))
|
|
204
|
+
- dfb4f13: repair pre-existing gate failures blocking release ([`4c55a4a`](https://github.com/briancray/abide/commit/4c55a4a1cbcb0b2afc842f7cc7134aed590006ce))
|
|
205
|
+
- dfb4f13: layout child sentinel + restProps skip move to the children key ([`500d1d8`](https://github.com/briancray/abide/commit/500d1d8d696147602eb1ce34706cbbbf724ceb0b))
|
|
206
|
+
- dfb4f13: fix stale props-declaration comment in compileShadow ([`532e079`](https://github.com/briancray/abide/commit/532e0796c54aa77c7b155145ae2d16193b7de4e5))
|
|
207
|
+
- c7d25e4: expand a thrown Bun.build AggregateError into per-file diagnostics ([`5643d95`](https://github.com/briancray/abide/commit/5643d95691dd9211bc5f3edb5a2ae77aa3989f63))
|
|
208
|
+
- dfb4f13: children lowers as a destructured prop, not $children ([`60bbbeb`](https://github.com/briancray/abide/commit/60bbbeb15cae41d34e5f5b4f07590bf0a5a1b795))
|
|
209
|
+
- dfb4f13: resolve 35 correctness/ergonomics findings from full-tree audit ([`73a72ac`](https://github.com/briancray/abide/commit/73a72ac1946f901f76d790b38fa3ebbf29b661fe))
|
|
210
|
+
- dfb4f13: extract buildArtifact (build-or-die primitive) ([`938e312`](https://github.com/briancray/abide/commit/938e3129f03cb6787624703422cd9472fbdcb83b))
|
|
211
|
+
- dfb4f13: format spreadProps + renderChain to canonical prettier ([`97b1565`](https://github.com/briancray/abide/commit/97b1565670eb0977b8079425f8e92becd6deb68e))
|
|
212
|
+
- dfb4f13: thunk-wrap layout children sentinel so {#if children} presence reads truthy ([`a884de1`](https://github.com/briancray/abide/commit/a884de1bbb0fcffaea91268cf49aa1d1b24a3d7a))
|
|
213
|
+
- 4a6bf93: drop an await settle whose anchor was detached from the tree ([`ad3d00c`](https://github.com/briancray/abide/commit/ad3d00c36ecfd935721164e7ebff7a7b3fffca4e))
|
|
214
|
+
- dfb4f13: resolve props by import binding, not ambient special-case ([`b624893`](https://github.com/briancray/abide/commit/b624893745aa0e1fdb407047b15f29ac0ceac3ec))
|
|
215
|
+
- dfb4f13: shadow declares props under the author's local alias ([`b821a5b`](https://github.com/briancray/abide/commit/b821a5bfef17233b2aa24502ea397eede62329a0))
|
|
216
|
+
- dfb4f13: extract withoutHydration (5 sites -> 1 helper) ([`c36be09`](https://github.com/briancray/abide/commit/c36be09d64846f76216bfcc7932cdbc026631f04))
|
|
217
|
+
- dfb4f13: redefine Snippet<Args> as a callable; add SnippetValue ([`ecc861f`](https://github.com/briancray/abide/commit/ecc861f589d5149a299b92ba6d08fd362644bcd1))
|
|
218
|
+
|
|
3
219
|
## 0.48.0
|
|
4
220
|
|
|
5
221
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@ cd examples/kitchen-sink && bun run dev
|
|
|
30
30
|
|
|
31
31
|
An RPC is one exported handler per file under `src/server/rpc/` — the file path
|
|
32
32
|
is the URL. The export wraps the handler in an HTTP-method helper (`GET`,
|
|
33
|
-
`POST`, `PUT`, `PATCH`, `DELETE`, `HEAD`); a Standard Schema `
|
|
33
|
+
`POST`, `PUT`, `PATCH`, `DELETE`, `HEAD`); a Standard Schema `schemas.input`
|
|
34
34
|
(zod, valibot, arktype — no adapter) validates the args and projects the CLI
|
|
35
35
|
flags, the MCP tool, and the OpenAPI operation from the one declaration.
|
|
36
36
|
|
|
@@ -44,10 +44,12 @@ import { listMessages } from '$server/store'
|
|
|
44
44
|
export const getMessages = GET(
|
|
45
45
|
async ({ room, limit }) => json(await listMessages(room, limit)),
|
|
46
46
|
{
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
schemas: {
|
|
48
|
+
input: z.object({
|
|
49
|
+
room: z.string(),
|
|
50
|
+
limit: z.coerce.number().default(50),
|
|
51
|
+
}),
|
|
52
|
+
},
|
|
51
53
|
},
|
|
52
54
|
)
|
|
53
55
|
```
|
|
@@ -83,7 +85,7 @@ over `fetch` in the browser. Around it:
|
|
|
83
85
|
- `getMessages.pending(args?)` / `.refreshing(args?)` / `.error(args?)` —
|
|
84
86
|
reactive probes
|
|
85
87
|
- a handler that returns `jsonl()`/`sse()` makes the bare call return a
|
|
86
|
-
`
|
|
88
|
+
`NamedAsyncIterable` you `for await` — detected at build time, nothing to declare
|
|
87
89
|
|
|
88
90
|
> Query args travel as strings — use `z.coerce.*` for numbers and booleans on
|
|
89
91
|
> GET/HEAD. The per-RPC `timeout` option is a server-side handler deadline
|
|
@@ -110,7 +112,7 @@ export const chat = socket({
|
|
|
110
112
|
})
|
|
111
113
|
```
|
|
112
114
|
|
|
113
|
-
`chat.
|
|
115
|
+
`chat.publish(msg)` publishes from either side — schema-validated on the
|
|
114
116
|
server, and client publishes are gated by `clientPublish`. `for await (const
|
|
115
117
|
msg of chat)` is the live stream; `chat.peek()` reads the latest retained
|
|
116
118
|
frame; `chat.refresh()` re-pulls the server tail after a reconnect. A schema
|
|
@@ -130,11 +132,16 @@ component you read and write state as plain variables. The same file renders on
|
|
|
130
132
|
the server — blocking awaits inline, streaming awaits out of order, cached
|
|
131
133
|
reads seeded warm — and hydrates in the browser.
|
|
132
134
|
|
|
133
|
-
|
|
135
|
+
Nested content becomes the component's `children` prop — an ordinary declared
|
|
136
|
+
prop of type `Snippet` — and renders wherever the component calls
|
|
137
|
+
`{children()}`:
|
|
134
138
|
|
|
135
139
|
```html
|
|
136
140
|
<script>
|
|
137
|
-
|
|
141
|
+
import { props } from '@abide/abide/ui/props'
|
|
142
|
+
import type { Snippet } from '@abide/abide/shared/snippet'
|
|
143
|
+
|
|
144
|
+
const { title, children } = props<{ title: string; children?: Snippet }>()
|
|
138
145
|
</script>
|
|
139
146
|
|
|
140
147
|
<section>
|
|
@@ -160,9 +167,10 @@ template grammar:
|
|
|
160
167
|
import { state } from '@abide/abide/ui/state'
|
|
161
168
|
import { watch } from '@abide/abide/ui/watch'
|
|
162
169
|
import { html } from '@abide/abide/ui/html'
|
|
170
|
+
import { props } from '@abide/abide/ui/props'
|
|
163
171
|
import Panel from '$ui/components/Panel.abide'
|
|
164
172
|
|
|
165
|
-
const { room = 'lobby' } = props()
|
|
173
|
+
const { room = 'lobby' } = props<{ room?: string }>()
|
|
166
174
|
|
|
167
175
|
let draft = state('')
|
|
168
176
|
let author = state('anon')
|
|
@@ -199,6 +207,9 @@ template grammar:
|
|
|
199
207
|
{room} — {shout}
|
|
200
208
|
</h1>
|
|
201
209
|
|
|
210
|
+
<!-- {await expr} awaits inline (blocking); a Promise-typed {expr} would stream -->
|
|
211
|
+
<p>total messages: {await getMessages({ room }).then((all) => all.length)}</p>
|
|
212
|
+
|
|
202
213
|
{#await getMessages({ room })}
|
|
203
214
|
<p>loading…</p>
|
|
204
215
|
{:then messages}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abide/abide",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.50.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"description": "Isomorphic multimodal HTTP framework built for humans and machines in a single Bun runtime",
|
|
@@ -77,20 +77,31 @@
|
|
|
77
77
|
"./shared/createSubscriber": "./src/lib/shared/createSubscriber.ts",
|
|
78
78
|
"./ui/html": "./src/lib/ui/html.ts",
|
|
79
79
|
"./ui/state": "./src/lib/ui/state.ts",
|
|
80
|
+
"./ui/props": "./src/lib/ui/props.ts",
|
|
80
81
|
"./ui/effect": "./src/lib/ui/effect.ts",
|
|
81
82
|
"./ui/currentScope": "./src/lib/ui/scope.ts",
|
|
82
83
|
"./ui/enterRenderScope": "./src/lib/ui/enterScope.ts",
|
|
83
84
|
"./ui/exitRenderScope": "./src/lib/ui/exitScope.ts",
|
|
84
|
-
"./ui/outbox": "./src/lib/ui/outbox.ts",
|
|
85
85
|
"./ui/dom/mount": "./src/lib/ui/dom/mount.ts",
|
|
86
86
|
"./ui/dom/mountChild": "./src/lib/ui/dom/mountChild.ts",
|
|
87
|
+
"./ui/dom/mountStreamedChild": "./src/lib/ui/dom/mountStreamedChild.ts",
|
|
87
88
|
"./ui/dom/mergeProps": "./src/lib/ui/dom/mergeProps.ts",
|
|
88
89
|
"./ui/dom/spreadProps": "./src/lib/ui/dom/spreadProps.ts",
|
|
89
90
|
"./ui/dom/restProps": "./src/lib/ui/dom/restProps.ts",
|
|
91
|
+
"./ui/dom/bindProp": "./src/lib/ui/dom/bindProp.ts",
|
|
92
|
+
"./ui/dom/bindableProp": "./src/lib/ui/dom/bindableProp.ts",
|
|
90
93
|
"./ui/dom/spreadAttrs": "./src/lib/ui/dom/spreadAttrs.ts",
|
|
91
94
|
"./ui/dom/readCall": "./src/lib/ui/dom/readCall.ts",
|
|
95
|
+
"./ui/dom/readCell": "./src/lib/ui/dom/readCell.ts",
|
|
96
|
+
"./ui/dom/cellPending": "./src/lib/ui/dom/cellPending.ts",
|
|
97
|
+
"./ui/runtime/withPath": "./src/lib/ui/runtime/withPath.ts",
|
|
98
|
+
"./ui/settleAsyncCells": "./src/lib/ui/settleAsyncCells.ts",
|
|
99
|
+
"./ui/flight": "./src/lib/ui/flight.ts",
|
|
100
|
+
"./ui/isolateCellBarrier": "./src/lib/ui/isolateCellBarrier.ts",
|
|
101
|
+
"./ui/finalizeStreamedChildren": "./src/lib/ui/finalizeStreamedChildren.ts",
|
|
102
|
+
"./ui/runtime/renderPath": "./src/lib/ui/runtime/renderPath.ts",
|
|
103
|
+
"./ui/dom/mutateDocContainer": "./src/lib/ui/dom/mutateDocContainer.ts",
|
|
92
104
|
"./ui/dom/hydrate": "./src/lib/ui/dom/hydrate.ts",
|
|
93
|
-
"./ui/dom/text": "./src/lib/ui/dom/text.ts",
|
|
94
105
|
"./ui/dom/appendText": "./src/lib/ui/dom/appendText.ts",
|
|
95
106
|
"./ui/dom/appendTextAt": "./src/lib/ui/dom/appendTextAt.ts",
|
|
96
107
|
"./ui/dom/appendSnippet": "./src/lib/ui/dom/appendSnippet.ts",
|
|
@@ -110,9 +121,9 @@
|
|
|
110
121
|
"./ui/dom/awaitBlock": "./src/lib/ui/dom/awaitBlock.ts",
|
|
111
122
|
"./ui/dom/tryBlock": "./src/lib/ui/dom/tryBlock.ts",
|
|
112
123
|
"./ui/dom/switchBlock": "./src/lib/ui/dom/switchBlock.ts",
|
|
113
|
-
"./ui/dom/applyResolved": "./src/lib/ui/dom/applyResolved.ts",
|
|
114
124
|
"./ui/runtime/escapeKey": "./src/lib/ui/runtime/escapeKey.ts",
|
|
115
125
|
"./ui/runtime/nextBlockId": "./src/lib/ui/runtime/nextBlockId.ts",
|
|
126
|
+
"./ui/runtime/blockId": "./src/lib/ui/runtime/blockId.ts",
|
|
116
127
|
"./ui/runtime/enterRenderPass": "./src/lib/ui/runtime/enterRenderPass.ts",
|
|
117
128
|
"./ui/runtime/exitRenderPass": "./src/lib/ui/runtime/exitRenderPass.ts",
|
|
118
129
|
"./ui/router": "./src/lib/ui/router.ts",
|
package/src/abideLsp.ts
CHANGED
|
@@ -6,10 +6,9 @@ import type {
|
|
|
6
6
|
} from './lib/ui/compile/createShadowLanguageService.ts'
|
|
7
7
|
import { createShadowLanguageService } from './lib/ui/compile/createShadowLanguageService.ts'
|
|
8
8
|
import { encodeSemanticTokens } from './lib/ui/compile/encodeSemanticTokens.ts'
|
|
9
|
-
import { markupTokens } from './lib/ui/compile/markupTokens.ts'
|
|
10
9
|
import { nearestProjectRoot } from './lib/ui/compile/nearestProjectRoot.ts'
|
|
11
10
|
import { offsetToPosition } from './lib/ui/compile/offsetToPosition.ts'
|
|
12
|
-
import {
|
|
11
|
+
import { templateSemanticTokens } from './lib/ui/compile/templateSemanticTokens.ts'
|
|
13
12
|
import type { AbideDiagnostic } from './lib/ui/compile/types/AbideDiagnostic.ts'
|
|
14
13
|
|
|
15
14
|
/*
|
|
@@ -25,8 +24,9 @@ their own project — matching `abide check` run from that package.
|
|
|
25
24
|
*/
|
|
26
25
|
/*
|
|
27
26
|
The semantic-tokens `data` array for one component: the HTML markup structure and
|
|
28
|
-
the structural `{#…}` framing
|
|
29
|
-
|
|
27
|
+
the structural `{#…}` framing — both driven by the ONE parse walk
|
|
28
|
+
(`templateSemanticTokens`) — merged with the shadow's type-aware expression tokens,
|
|
29
|
+
encoded to the LSP wire format. The markup tokens make the LSP own the
|
|
30
30
|
element/attribute coloring too, so a tree-sitter parse desynced by an `attr={expr}`
|
|
31
31
|
value can't bleed miscoloring below it. Never throws — on any internal failure it
|
|
32
32
|
yields an empty stream so the editor falls back to tree-sitter highlighting.
|
|
@@ -38,8 +38,7 @@ export function componentSemanticTokens(
|
|
|
38
38
|
): number[] {
|
|
39
39
|
try {
|
|
40
40
|
const tokens = [
|
|
41
|
-
...
|
|
42
|
-
...structuralBlockTokens(text),
|
|
41
|
+
...templateSemanticTokens(text),
|
|
43
42
|
...service.semanticClassifications(abidePath),
|
|
44
43
|
]
|
|
45
44
|
return encodeSemanticTokens(text, tokens)
|