@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
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import type { SemanticToken } from './types/SemanticToken.ts'
|
|
2
|
-
|
|
3
|
-
/*
|
|
4
|
-
Lexical highlighting for `{#…}`/`{:…}`/`{/…}` control-flow framing — the part the
|
|
5
|
-
HTML grammar sees only as text and the shadow program lowers away. A pure scan of
|
|
6
|
-
raw source (independent of a successful parse, so it survives mid-edit), it emits
|
|
7
|
-
an `operator` token for the `{`+sigil opener and a `keyword` token for the block
|
|
8
|
-
word, plus the `of`/`by` connectors inside a `{#for …}` head. Expression interiors
|
|
9
|
-
and bare `{expr}` interpolations are NOT touched here — those are the shadow's job.
|
|
10
|
-
A keyword allowlist after the sigil prevents matching arbitrary `{:foo}` text.
|
|
11
|
-
Longest phrases first so `for await` beats `for` and `else if` beats `else`.
|
|
12
|
-
*/
|
|
13
|
-
const BLOCK_KEYWORDS = [
|
|
14
|
-
'for await',
|
|
15
|
-
'else if',
|
|
16
|
-
'if',
|
|
17
|
-
'for',
|
|
18
|
-
'await',
|
|
19
|
-
'switch',
|
|
20
|
-
'case',
|
|
21
|
-
'default',
|
|
22
|
-
'try',
|
|
23
|
-
'catch',
|
|
24
|
-
'finally',
|
|
25
|
-
'then',
|
|
26
|
-
'else',
|
|
27
|
-
]
|
|
28
|
-
|
|
29
|
-
const BLOCK_HEAD = new RegExp(`\\{([#:/])\\s*(${BLOCK_KEYWORDS.join('|')})\\b`, 'g')
|
|
30
|
-
|
|
31
|
-
export function structuralBlockTokens(source: string): SemanticToken[] {
|
|
32
|
-
const tokens: SemanticToken[] = []
|
|
33
|
-
for (const match of source.matchAll(BLOCK_HEAD)) {
|
|
34
|
-
const braceStart = match.index
|
|
35
|
-
const sigil = match[1]
|
|
36
|
-
const keyword = match[2]
|
|
37
|
-
if (keyword === undefined) {
|
|
38
|
-
continue
|
|
39
|
-
}
|
|
40
|
-
const keywordStart = braceStart + match[0].length - keyword.length
|
|
41
|
-
tokens.push({ start: braceStart, length: 2, type: 'operator', modifiers: [] })
|
|
42
|
-
tokens.push({ start: keywordStart, length: keyword.length, type: 'keyword', modifiers: [] })
|
|
43
|
-
/* A `{#for …}` head carries abide-only connectors `of`/`by` that the shadow
|
|
44
|
-
lowers away (`of`) or never emits (`by`), so color them here. */
|
|
45
|
-
if (sigil === '#' && (keyword === 'for' || keyword === 'for await')) {
|
|
46
|
-
tokens.push(...forHeadConnectors(source, keywordStart + keyword.length))
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
return tokens
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/*
|
|
53
|
-
Scans a `{#for …}` head from `from` to its closing `}`, emitting `keyword` tokens
|
|
54
|
-
for the `of`/`by` connectors at brace depth 0 — skipping any `of`/`by` nested in a
|
|
55
|
-
destructure, call, or string so an identifier or object key is never miscolored.
|
|
56
|
-
*/
|
|
57
|
-
function forHeadConnectors(source: string, from: number): SemanticToken[] {
|
|
58
|
-
const tokens: SemanticToken[] = []
|
|
59
|
-
let depth = 0
|
|
60
|
-
let cursor = from
|
|
61
|
-
while (cursor < source.length) {
|
|
62
|
-
const char = source.charAt(cursor)
|
|
63
|
-
if (char === '"' || char === "'" || char === '`') {
|
|
64
|
-
cursor += 1
|
|
65
|
-
while (cursor < source.length && source.charAt(cursor) !== char) {
|
|
66
|
-
if (source.charAt(cursor) === '\\') {
|
|
67
|
-
cursor += 1
|
|
68
|
-
}
|
|
69
|
-
cursor += 1
|
|
70
|
-
}
|
|
71
|
-
} else if (char === '{' || char === '(' || char === '[') {
|
|
72
|
-
depth += 1
|
|
73
|
-
} else if (char === ')' || char === ']') {
|
|
74
|
-
depth -= 1
|
|
75
|
-
} else if (char === '}') {
|
|
76
|
-
if (depth === 0) {
|
|
77
|
-
break
|
|
78
|
-
}
|
|
79
|
-
depth -= 1
|
|
80
|
-
} else if (depth === 0 && (char === 'o' || char === 'b')) {
|
|
81
|
-
const word = source.startsWith('of', cursor)
|
|
82
|
-
? 'of'
|
|
83
|
-
: source.startsWith('by', cursor)
|
|
84
|
-
? 'by'
|
|
85
|
-
: undefined
|
|
86
|
-
const isWordBoundary = (offset: number): boolean => /\s/.test(source.charAt(offset))
|
|
87
|
-
if (
|
|
88
|
-
word !== undefined &&
|
|
89
|
-
isWordBoundary(cursor - 1) &&
|
|
90
|
-
isWordBoundary(cursor + word.length)
|
|
91
|
-
) {
|
|
92
|
-
tokens.push({ start: cursor, length: word.length, type: 'keyword', modifiers: [] })
|
|
93
|
-
cursor += word.length
|
|
94
|
-
continue
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
cursor += 1
|
|
98
|
-
}
|
|
99
|
-
return tokens
|
|
100
|
-
}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import { seedResolved } from '../seedResolved.ts'
|
|
2
|
-
import { isComment } from './isComment.ts'
|
|
3
|
-
|
|
4
|
-
/*
|
|
5
|
-
Bundle-side consumer of an SSR stream chunk, the counterpart of the doc stream's inline
|
|
6
|
-
vanilla scripts (`SSR_SWAP_SCRIPT`'s `__abideSwap` and `CACHE_RESOLVE_SCRIPT`'s `__abideResolve`) for a stream the
|
|
7
|
-
running bundle consumes itself — streaming SPA navigation, socket-delivered SSR. It routes
|
|
8
|
-
the two chunk kinds the stream interleaves:
|
|
9
|
-
|
|
10
|
-
- `<abide-cache>{StreamedResolution}</abide-cache>` → seed the streamed cache partition.
|
|
11
|
-
A script set via innerHTML never runs, so the cache channel rides a data frame here
|
|
12
|
-
(not the doc stream's `<script>__abideResolve(…)</script>`); seeding it keeps the
|
|
13
|
-
pending {#await} read warm instead of cold-missing to the network.
|
|
14
|
-
- `<abide-resolve data-id="ID"><script type="application/json">…</script>…</abide-resolve>`
|
|
15
|
-
→ register the value in the resume manifest (for hydration), find the matching
|
|
16
|
-
`<!--abide:await:ID-->…<!--/abide:await:ID-->` boundary in `root`, remove the pending
|
|
17
|
-
nodes between the markers, and insert the resolved content in their place.
|
|
18
|
-
|
|
19
|
-
The pending shell painted instantly; this swaps in each value as it arrives — completing
|
|
20
|
-
the out-of-order streaming loop on the client.
|
|
21
|
-
*/
|
|
22
|
-
// @documentation plumbing
|
|
23
|
-
export function applyResolved(root: Element, frame: string): void {
|
|
24
|
-
const holder = document.createElement('div')
|
|
25
|
-
holder.innerHTML = frame
|
|
26
|
-
const resolved = holder.firstChild as Element | null
|
|
27
|
-
if (resolved === null || resolved.getAttribute === undefined) {
|
|
28
|
-
return
|
|
29
|
-
}
|
|
30
|
-
/* A cache-seed frame warms the streamed cache partition — paired with the DOM swap so a
|
|
31
|
-
bundle-consumed stream can't adopt a resolved branch while dropping its cache key. */
|
|
32
|
-
if (resolved.nodeName === 'ABIDE-CACHE') {
|
|
33
|
-
try {
|
|
34
|
-
seedResolved({ kind: 'cache', resolution: JSON.parse(resolved.textContent ?? 'null') })
|
|
35
|
-
} catch {
|
|
36
|
-
/* malformed payload — leave unseeded; the read falls back to a live fetch */
|
|
37
|
-
}
|
|
38
|
-
return
|
|
39
|
-
}
|
|
40
|
-
const id = resolved.getAttribute('data-id')
|
|
41
|
-
if (id === null) {
|
|
42
|
-
return
|
|
43
|
-
}
|
|
44
|
-
/* The resolved value rides in a leading <script type=application/json> as ref-json
|
|
45
|
-
text; store it raw and remove the node so only the resolved markup moves into the
|
|
46
|
-
boundary. Decoding is deferred to the read in `awaitBlock` (which has the codec);
|
|
47
|
-
recording it lets a later hydrate adopt this branch (no re-fetch). */
|
|
48
|
-
const payload = resolved.firstChild as Element | null
|
|
49
|
-
if (payload !== null && payload.nodeName === 'SCRIPT') {
|
|
50
|
-
seedResolved({ kind: 'resume', id: Number(id), resume: payload.textContent ?? '' })
|
|
51
|
-
payload.remove()
|
|
52
|
-
}
|
|
53
|
-
const open = `abide:await:${id}`
|
|
54
|
-
const close = `/abide:await:${id}`
|
|
55
|
-
const boundary = findBoundary(root, open)
|
|
56
|
-
if (boundary === undefined) {
|
|
57
|
-
return
|
|
58
|
-
}
|
|
59
|
-
const { parent, start } = boundary
|
|
60
|
-
/* Remove the pending nodes between the markers (exclusive of the markers). */
|
|
61
|
-
let node = start.nextSibling
|
|
62
|
-
while (node !== null && !isComment(node, close)) {
|
|
63
|
-
const next = node.nextSibling
|
|
64
|
-
parent.removeChild(node)
|
|
65
|
-
node = next
|
|
66
|
-
}
|
|
67
|
-
/* Insert resolved content after the open marker. */
|
|
68
|
-
let anchor = start.nextSibling
|
|
69
|
-
for (const child of [...resolved.childNodes]) {
|
|
70
|
-
parent.insertBefore(child, anchor)
|
|
71
|
-
anchor = child.nextSibling
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/* Depth-first search for the parent + open-marker comment of a boundary. */
|
|
76
|
-
function findBoundary(node: Node, open: string): { parent: Node; start: Node } | undefined {
|
|
77
|
-
for (const child of [...node.childNodes]) {
|
|
78
|
-
if (isComment(child, open)) {
|
|
79
|
-
return { parent: node, start: child }
|
|
80
|
-
}
|
|
81
|
-
const nested = findBoundary(child, open)
|
|
82
|
-
if (nested !== undefined) {
|
|
83
|
-
return nested
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
return undefined
|
|
87
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
The human-readable name for the scope the direct-mount entry (`mount`/`hydrate`)
|
|
3
|
-
establishes, derived from its host element's tag. The router instead fills layers into
|
|
4
|
-
marker boundaries with no host element, so it passes each layer's route key as an
|
|
5
|
-
explicit label (`fillBoundary`); a nested child likewise passes its component name (see
|
|
6
|
-
`mountRange`). The `abide-` prefix strip turns a framework host tag like `abide-resolve`
|
|
7
|
-
into `resolve`; any other host yields its lowercased tag. Feeds the inspector's
|
|
8
|
-
Reactive tab a readable scope name; computed and stored in all builds (only the
|
|
9
|
-
inspector surface is dev-only). Returns undefined when there's no element to name from.
|
|
10
|
-
*/
|
|
11
|
-
import { COMPONENT_WRAPPER_PREFIX } from '../COMPONENT_WRAPPER_PREFIX.ts'
|
|
12
|
-
|
|
13
|
-
export function scopeLabel(host: Element): string | undefined {
|
|
14
|
-
const tag = host.tagName?.toLowerCase()
|
|
15
|
-
if (tag === undefined) {
|
|
16
|
-
return undefined
|
|
17
|
-
}
|
|
18
|
-
return tag.startsWith(COMPONENT_WRAPPER_PREFIX)
|
|
19
|
-
? tag.slice(COMPONENT_WRAPPER_PREFIX.length)
|
|
20
|
-
: tag
|
|
21
|
-
}
|
package/src/lib/ui/dom/text.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { effect } from '../effect.ts'
|
|
2
|
-
|
|
3
|
-
/*
|
|
4
|
-
A text node whose content tracks `read()`. The effect captures whatever reactive
|
|
5
|
-
cells `read` touches, so the node — and only this node — re-renders when they
|
|
6
|
-
change: one text node, one effect — fine-grained granularity.
|
|
7
|
-
|
|
8
|
-
Plain-text only — `read()` is coerced with String(). For a `{expr}` interpolation
|
|
9
|
-
that may yield an `html\`…\`` or snippet value the compiler emits `appendText`,
|
|
10
|
-
which branches on the branded value and inserts raw markup; `text` cannot host
|
|
11
|
-
multiple nodes and would stringify such a value to `[object Object]`.
|
|
12
|
-
*/
|
|
13
|
-
// @documentation plumbing
|
|
14
|
-
export function text(read: () => unknown): Text {
|
|
15
|
-
const node = document.createTextNode('')
|
|
16
|
-
effect(() => {
|
|
17
|
-
node.data = String(read())
|
|
18
|
-
})
|
|
19
|
-
return node
|
|
20
|
-
}
|
package/src/lib/ui/history.ts
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { PATCH_BUS } from './runtime/PATCH_BUS.ts'
|
|
2
|
-
import type { Doc } from './runtime/types/Doc.ts'
|
|
3
|
-
import type { Patch } from './runtime/types/Patch.ts'
|
|
4
|
-
import type { History } from './types/History.ts'
|
|
5
|
-
|
|
6
|
-
/*
|
|
7
|
-
Undo/redo for a document. Subscribes the `PATCH_BUS`, filters to this `doc`, and
|
|
8
|
-
journals each applied patch's `inverse` into a bounded stack — O(size of the
|
|
9
|
-
change) per step, never a tree snapshot. `undo`/`redo` replay inverses through
|
|
10
|
-
`doc.apply`; the patches that replay itself emits are routed into a `sink` so a
|
|
11
|
-
replay never opens a fresh entry nor clears the opposite stack (it instead fills
|
|
12
|
-
it, keeping the move reversible). A genuine new edit clears the redo stack.
|
|
13
|
-
`transaction(fn)` groups every patch `fn` emits into one entry. `limit` caps
|
|
14
|
-
depth — the oldest entry drops. Inert (but harmless) on the server.
|
|
15
|
-
*/
|
|
16
|
-
// @documentation plumbing
|
|
17
|
-
export function history(doc: Doc, { limit = 100 }: { limit?: number } = {}): History {
|
|
18
|
-
const undoStack: Patch[][] = []
|
|
19
|
-
const redoStack: Patch[][] = []
|
|
20
|
-
/* When set, captured inverses accumulate here instead of opening a new undo entry
|
|
21
|
-
— held by an in-progress transaction and by an undo/redo replay. */
|
|
22
|
-
let sink: Patch[] | undefined
|
|
23
|
-
|
|
24
|
-
/* Push one finished entry, evicting the oldest past `limit`. */
|
|
25
|
-
const push = (stack: Patch[][], entry: Patch[]): void => {
|
|
26
|
-
stack.push(entry)
|
|
27
|
-
if (stack.length > limit) {
|
|
28
|
-
stack.shift()
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const unsubscribe = PATCH_BUS.subscribe((event) => {
|
|
33
|
-
if (event.doc !== doc || event.inverse === undefined) {
|
|
34
|
-
return
|
|
35
|
-
}
|
|
36
|
-
if (sink !== undefined) {
|
|
37
|
-
sink.push(event.inverse)
|
|
38
|
-
return
|
|
39
|
-
}
|
|
40
|
-
push(undoStack, [event.inverse])
|
|
41
|
-
redoStack.length = 0
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
/* Apply an entry's inverses in reverse application order (LIFO), capturing the
|
|
45
|
-
inverses they emit — the original forward patches — onto `target`, so the move
|
|
46
|
-
is itself reversible and lands on the opposite stack. */
|
|
47
|
-
const replay = (entry: Patch[], target: Patch[][]): void => {
|
|
48
|
-
const captured: Patch[] = []
|
|
49
|
-
sink = captured
|
|
50
|
-
try {
|
|
51
|
-
for (let index = entry.length - 1; index >= 0; index -= 1) {
|
|
52
|
-
doc.apply(entry[index] as Patch)
|
|
53
|
-
}
|
|
54
|
-
} finally {
|
|
55
|
-
sink = undefined
|
|
56
|
-
}
|
|
57
|
-
if (captured.length > 0) {
|
|
58
|
-
push(target, captured)
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return {
|
|
63
|
-
undo: () => {
|
|
64
|
-
const entry = undoStack.pop()
|
|
65
|
-
if (entry !== undefined) {
|
|
66
|
-
replay(entry, redoStack)
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
|
-
redo: () => {
|
|
70
|
-
const entry = redoStack.pop()
|
|
71
|
-
if (entry !== undefined) {
|
|
72
|
-
replay(entry, undoStack)
|
|
73
|
-
}
|
|
74
|
-
},
|
|
75
|
-
canUndo: () => undoStack.length > 0,
|
|
76
|
-
canRedo: () => redoStack.length > 0,
|
|
77
|
-
transaction: (run: () => void) => {
|
|
78
|
-
/* A nested transaction folds into the one already collecting. */
|
|
79
|
-
if (sink !== undefined) {
|
|
80
|
-
run()
|
|
81
|
-
return
|
|
82
|
-
}
|
|
83
|
-
const entry: Patch[] = []
|
|
84
|
-
sink = entry
|
|
85
|
-
try {
|
|
86
|
-
run()
|
|
87
|
-
} finally {
|
|
88
|
-
sink = undefined
|
|
89
|
-
}
|
|
90
|
-
if (entry.length > 0) {
|
|
91
|
-
push(undoStack, entry)
|
|
92
|
-
redoStack.length = 0
|
|
93
|
-
}
|
|
94
|
-
},
|
|
95
|
-
dispose: () => {
|
|
96
|
-
unsubscribe()
|
|
97
|
-
undoStack.length = 0
|
|
98
|
-
redoStack.length = 0
|
|
99
|
-
},
|
|
100
|
-
}
|
|
101
|
-
}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import { snippet } from '../shared/snippet.ts'
|
|
2
|
-
import { anchorCursor } from './dom/anchorCursor.ts'
|
|
3
|
-
import { appendSnippet } from './dom/appendSnippet.ts'
|
|
4
|
-
import { appendStatic } from './dom/appendStatic.ts'
|
|
5
|
-
import { appendText } from './dom/appendText.ts'
|
|
6
|
-
import { appendTextAt } from './dom/appendTextAt.ts'
|
|
7
|
-
import { attach } from './dom/attach.ts'
|
|
8
|
-
import { attr } from './dom/attr.ts'
|
|
9
|
-
import { awaitBlock } from './dom/awaitBlock.ts'
|
|
10
|
-
import { bindSelectValue } from './dom/bindSelectValue.ts'
|
|
11
|
-
import { cloneStatic } from './dom/cloneStatic.ts'
|
|
12
|
-
import { each } from './dom/each.ts'
|
|
13
|
-
import { eachAsync } from './dom/eachAsync.ts'
|
|
14
|
-
import { hydrate } from './dom/hydrate.ts'
|
|
15
|
-
import { mergeProps } from './dom/mergeProps.ts'
|
|
16
|
-
import { mount } from './dom/mount.ts'
|
|
17
|
-
import { mountChild } from './dom/mountChild.ts'
|
|
18
|
-
import { mountSlot } from './dom/mountSlot.ts'
|
|
19
|
-
import { on } from './dom/on.ts'
|
|
20
|
-
import { outlet } from './dom/outlet.ts'
|
|
21
|
-
import { readCall } from './dom/readCall.ts'
|
|
22
|
-
import { restProps } from './dom/restProps.ts'
|
|
23
|
-
import { skeleton } from './dom/skeleton.ts'
|
|
24
|
-
import { spreadAttrs } from './dom/spreadAttrs.ts'
|
|
25
|
-
import { spreadProps } from './dom/spreadProps.ts'
|
|
26
|
-
import { switchBlock } from './dom/switchBlock.ts'
|
|
27
|
-
import { tryBlock } from './dom/tryBlock.ts'
|
|
28
|
-
import { when } from './dom/when.ts'
|
|
29
|
-
import { effect } from './effect.ts'
|
|
30
|
-
import { enterScope } from './enterScope.ts'
|
|
31
|
-
import { exitScope } from './exitScope.ts'
|
|
32
|
-
import { enterRenderPass } from './runtime/enterRenderPass.ts'
|
|
33
|
-
import { escapeKey } from './runtime/escapeKey.ts'
|
|
34
|
-
import { exitRenderPass } from './runtime/exitRenderPass.ts'
|
|
35
|
-
import { hotReloadEnabled } from './runtime/hotReloadEnabled.ts'
|
|
36
|
-
import { hotReplace } from './runtime/hotReplace.ts'
|
|
37
|
-
import { nextBlockId } from './runtime/nextBlockId.ts'
|
|
38
|
-
import { scope } from './scope.ts'
|
|
39
|
-
import { watch } from './watch.ts'
|
|
40
|
-
|
|
41
|
-
/*
|
|
42
|
-
Dev-only: exposes the abide-ui runtime plus `hotReplace` on `window.__abide`, and
|
|
43
|
-
flips on `hotReloadEnabled` so `mountChild` records every instance it mounts. A
|
|
44
|
-
hot module (the dev server's standalone recompile of one edited `.abide`) reads
|
|
45
|
-
its runtime from this object instead of importing fresh copies — so it shares the
|
|
46
|
-
one reactive graph and instance registry — then calls `hotReplace` to swap every
|
|
47
|
-
live instance in place. The keys mirror `UI_RUNTIME_IMPORTS` (+ `hotReplace`); a
|
|
48
|
-
test guards that pairing. `startClient` calls this when the server marks the page
|
|
49
|
-
dev (the live-reload script sets `window.__abideDev`).
|
|
50
|
-
*/
|
|
51
|
-
export function installHotBridge(): void {
|
|
52
|
-
;(globalThis as { __abide?: Record<string, unknown> }).__abide = {
|
|
53
|
-
snippet,
|
|
54
|
-
scope,
|
|
55
|
-
enterScope,
|
|
56
|
-
exitScope,
|
|
57
|
-
effect,
|
|
58
|
-
watch,
|
|
59
|
-
mount,
|
|
60
|
-
appendText,
|
|
61
|
-
appendTextAt,
|
|
62
|
-
appendSnippet,
|
|
63
|
-
appendStatic,
|
|
64
|
-
cloneStatic,
|
|
65
|
-
skeleton,
|
|
66
|
-
anchorCursor,
|
|
67
|
-
attr,
|
|
68
|
-
on,
|
|
69
|
-
attach,
|
|
70
|
-
bindSelectValue,
|
|
71
|
-
each,
|
|
72
|
-
eachAsync,
|
|
73
|
-
when,
|
|
74
|
-
awaitBlock,
|
|
75
|
-
tryBlock,
|
|
76
|
-
switchBlock,
|
|
77
|
-
mountSlot,
|
|
78
|
-
outlet,
|
|
79
|
-
mountChild,
|
|
80
|
-
mergeProps,
|
|
81
|
-
spreadProps,
|
|
82
|
-
restProps,
|
|
83
|
-
spreadAttrs,
|
|
84
|
-
readCall,
|
|
85
|
-
hydrate,
|
|
86
|
-
escapeKey,
|
|
87
|
-
nextBlockId,
|
|
88
|
-
enterRenderPass,
|
|
89
|
-
exitRenderPass,
|
|
90
|
-
hotReplace,
|
|
91
|
-
}
|
|
92
|
-
hotReloadEnabled.current = true
|
|
93
|
-
}
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import { effect } from './effect.ts'
|
|
2
|
-
import { clientPage } from './runtime/clientPage.ts'
|
|
3
|
-
import { historyEntries } from './runtime/historyEntries.ts'
|
|
4
|
-
import { liveScopes } from './runtime/liveScopes.ts'
|
|
5
|
-
import { PATCH_BUS } from './runtime/PATCH_BUS.ts'
|
|
6
|
-
import { runtimePath } from './runtime/runtimePath.ts'
|
|
7
|
-
|
|
8
|
-
/* Same-origin cross-tab channel the inspector page listens on. The app tab
|
|
9
|
-
publishes scope + router state; the inspector subscribes. Web-standard, so no
|
|
10
|
-
server route or buffer is involved — core publishes, the package consumes. */
|
|
11
|
-
const CHANNEL = 'abide:inspector'
|
|
12
|
-
|
|
13
|
-
/* Coalesce a burst of patches into one snapshot — the post is the cost, the read is cheap. */
|
|
14
|
-
const SNAPSHOT_DEBOUNCE_MS = 60
|
|
15
|
-
|
|
16
|
-
/* JSON round-trip to strip anything structured-clone can't carry (functions,
|
|
17
|
-
class instances, DOM nodes) before postMessage, degrading to undefined rather
|
|
18
|
-
than throwing into the channel. */
|
|
19
|
-
function cloneable(value: unknown): unknown {
|
|
20
|
-
try {
|
|
21
|
-
return JSON.parse(JSON.stringify(value))
|
|
22
|
-
} catch {
|
|
23
|
-
return undefined
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/* The live scope forest as a flat list — the inspector rebuilds the tree from
|
|
28
|
-
each node's `parent` id (the Scope surface exposes no children accessor). */
|
|
29
|
-
function scopeNodes(): Array<{
|
|
30
|
-
id: string
|
|
31
|
-
label: string | undefined
|
|
32
|
-
parent: string | undefined
|
|
33
|
-
state: unknown
|
|
34
|
-
recorded: boolean
|
|
35
|
-
}> {
|
|
36
|
-
return Array.from(liveScopes.scopes, (scope) => ({
|
|
37
|
-
id: scope.id,
|
|
38
|
-
label: scope.label,
|
|
39
|
-
parent: scope.parent?.id,
|
|
40
|
-
state: cloneable(scope.snapshot()),
|
|
41
|
-
recorded: scope.canUndo() || scope.canRedo(),
|
|
42
|
-
}))
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/* Router state off the existing reactive holders — read, not subscribed, here;
|
|
46
|
-
the nav effect drives re-reads. */
|
|
47
|
-
function routerState() {
|
|
48
|
-
const page = clientPage.value
|
|
49
|
-
return {
|
|
50
|
-
path: runtimePath.value,
|
|
51
|
-
route: page.route,
|
|
52
|
-
/* `page.params` is a reactive Proxy — structuredClone (postMessage) can't carry
|
|
53
|
-
a Proxy and throws, dropping every router frame. Spread to a plain object. */
|
|
54
|
-
params: { ...page.params },
|
|
55
|
-
navigating: page.navigating,
|
|
56
|
-
url: page.url.href,
|
|
57
|
-
entry: historyEntries.current,
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/*
|
|
62
|
-
Installs the client→inspector bridge: a BroadcastChannel the inspector page reads
|
|
63
|
-
to render its Reactive + Router tabs. Gated by `__abideInspect` (server-injected
|
|
64
|
-
only when the inspector is enabled) and called from startClient before the router
|
|
65
|
-
builds any scope — so registration is armed before the first scope exists. A
|
|
66
|
-
no-op where BroadcastChannel is absent (SSR, old runtimes). Mirrors
|
|
67
|
-
installHotBridge: dev instrumentation, not public surface.
|
|
68
|
-
*/
|
|
69
|
-
export function installInspectorBridge(): void {
|
|
70
|
-
/* No BroadcastChannel means no consumer for the scope registry — bail before
|
|
71
|
-
arming `liveScopes.enabled`, so createScope never pays scope tracking for a
|
|
72
|
-
set nothing reads. */
|
|
73
|
-
if (typeof BroadcastChannel === 'undefined') {
|
|
74
|
-
return
|
|
75
|
-
}
|
|
76
|
-
liveScopes.enabled = true
|
|
77
|
-
const channel = new BroadcastChannel(CHANNEL)
|
|
78
|
-
const tab = typeof crypto !== 'undefined' ? crypto.randomUUID() : String(performance.now())
|
|
79
|
-
const post = (message: object) => {
|
|
80
|
-
try {
|
|
81
|
-
channel.postMessage({ tab, ...message })
|
|
82
|
-
} catch {
|
|
83
|
-
/* A non-cloneable slipped through despite the JSON pass — drop the frame
|
|
84
|
-
rather than throw into a patch/nav handler. */
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const announce = () =>
|
|
89
|
-
post({
|
|
90
|
-
kind: 'announce',
|
|
91
|
-
url: typeof location !== 'undefined' ? location.href : '',
|
|
92
|
-
app: typeof document !== 'undefined' ? document.title : '',
|
|
93
|
-
})
|
|
94
|
-
const sendSnapshot = () =>
|
|
95
|
-
post({ kind: 'snapshot', scopes: scopeNodes(), router: routerState() })
|
|
96
|
-
|
|
97
|
-
let snapshotTimer: ReturnType<typeof setTimeout> | undefined
|
|
98
|
-
const scheduleSnapshot = () => {
|
|
99
|
-
clearTimeout(snapshotTimer)
|
|
100
|
-
snapshotTimer = setTimeout(sendSnapshot, SNAPSHOT_DEBOUNCE_MS)
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/* Inspector handshakes: `hello` (it just opened — everyone re-announce + push)
|
|
104
|
-
and `request` (it wants a fresh snapshot of this tab). */
|
|
105
|
-
channel.onmessage = (event) => {
|
|
106
|
-
const message = event.data as { kind?: string; tab?: string }
|
|
107
|
-
if (message.kind === 'hello') {
|
|
108
|
-
announce()
|
|
109
|
-
sendSnapshot()
|
|
110
|
-
} else if (message.kind === 'request' && message.tab === tab) {
|
|
111
|
-
sendSnapshot()
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/* Every doc mutation flows through PATCH_BUS; forward the patch as a live
|
|
116
|
-
mutation event and re-snapshot (debounced) so values stay current. */
|
|
117
|
-
PATCH_BUS.subscribe((patchEvent) => {
|
|
118
|
-
post({ kind: 'patch', op: patchEvent.patch.op, path: patchEvent.patch.path })
|
|
119
|
-
scheduleSnapshot()
|
|
120
|
-
})
|
|
121
|
-
|
|
122
|
-
/* Reading the page + path States tracks them, so this re-runs on navigation. */
|
|
123
|
-
effect(() => {
|
|
124
|
-
clientPage.value
|
|
125
|
-
runtimePath.value
|
|
126
|
-
post({ kind: 'nav', router: routerState() })
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
if (typeof addEventListener === 'function') {
|
|
130
|
-
addEventListener('pagehide', () => {
|
|
131
|
-
post({ kind: 'bye' })
|
|
132
|
-
channel.close()
|
|
133
|
-
})
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
announce()
|
|
137
|
-
/* First snapshot once the router has built the initial scope tree (this runs
|
|
138
|
-
before router()). */
|
|
139
|
-
setTimeout(sendSnapshot, 0)
|
|
140
|
-
}
|
package/src/lib/ui/outbox.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import type { OutboxEntry } from '../shared/types/OutboxEntry.ts'
|
|
2
|
-
import type { RemoteFunction } from '../shared/types/RemoteFunction.ts'
|
|
3
|
-
import { outboxRegistry } from './rpcOutbox/outboxRegistry.ts'
|
|
4
|
-
|
|
5
|
-
/* One entry in the global outbox, tagged with the RPC it belongs to. */
|
|
6
|
-
export type GlobalOutboxEntry = OutboxEntry<unknown> & { rpc: RemoteFunction<unknown, unknown> }
|
|
7
|
-
|
|
8
|
-
/* The global outbox: callable for the flat entry list, awaitable `retry()` to drain every
|
|
9
|
-
queue (resolves when every replay settles). */
|
|
10
|
-
export type GlobalOutbox = (() => GlobalOutboxEntry[]) & { retry: () => Promise<void> }
|
|
11
|
-
|
|
12
|
-
function list(): GlobalOutboxEntry[] {
|
|
13
|
-
return outboxRegistry.all().flatMap(({ rpc, queue }) =>
|
|
14
|
-
queue.entries().map((entry) => ({
|
|
15
|
-
...entry,
|
|
16
|
-
rpc: rpc as RemoteFunction<unknown, unknown>,
|
|
17
|
-
})),
|
|
18
|
-
)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/*
|
|
22
|
-
The global, reactive view of every durable RPC's outbox — a flat list of undelivered
|
|
23
|
-
entries across all `outbox` rpcs, each tagged with its `rpc`. Reactive: reading it in a
|
|
24
|
-
template/effect subscribes to each registered queue, so it updates as writes park, drain,
|
|
25
|
-
fail, or cancel. Use it for an app-wide "N unsynced" badge or a sync panel; cancel a
|
|
26
|
-
pending write through `entry.controller.abort()`, retry one through `entry.retry()`, or
|
|
27
|
-
drain everything through `outbox.retry()`. A single rpc's slice is `rpc.outbox`. Server-
|
|
28
|
-
side there are no client queues, so it returns an empty list.
|
|
29
|
-
*/
|
|
30
|
-
// @documentation ui
|
|
31
|
-
export const outbox: GlobalOutbox = Object.assign(list, {
|
|
32
|
-
async retry(): Promise<void> {
|
|
33
|
-
await Promise.all(outboxRegistry.all().map(({ queue }) => queue.retry()))
|
|
34
|
-
},
|
|
35
|
-
})
|