@abide/abide 0.28.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/CHANGELOG.md +607 -0
- package/LICENSE +21 -0
- package/README.md +154 -0
- package/bin/abide.ts +212 -0
- package/package.json +155 -0
- package/src/abideLsp.ts +211 -0
- package/src/abideModules.d.ts +8 -0
- package/src/abideResolverPlugin.ts +923 -0
- package/src/appEntry.ts +151 -0
- package/src/assets/app.html +12 -0
- package/src/build.ts +143 -0
- package/src/buildCli.ts +127 -0
- package/src/buildDisconnected.ts +118 -0
- package/src/bundleApp.ts +147 -0
- package/src/bundleDisconnectedEntry.ts +14 -0
- package/src/checkAbide.ts +77 -0
- package/src/cliEntry.ts +25 -0
- package/src/clientBuildPlugins.ts +33 -0
- package/src/clientEntry.ts +17 -0
- package/src/compile.ts +63 -0
- package/src/controlServerWorker.ts +426 -0
- package/src/devEntry.ts +250 -0
- package/src/discoveryEntry.ts +81 -0
- package/src/lib/bundle/BundleMenu.ts +12 -0
- package/src/lib/bundle/BundleMenuItem.ts +25 -0
- package/src/lib/bundle/BundleWindow.ts +37 -0
- package/src/lib/bundle/WEBVIEW_BUILD_REVISION.ts +9 -0
- package/src/lib/bundle/WEBVIEW_VERSION.ts +7 -0
- package/src/lib/bundle/bindConnectedFlag.ts +29 -0
- package/src/lib/bundle/bindRequestNavigate.ts +34 -0
- package/src/lib/bundle/buildWebviewLib.ts +111 -0
- package/src/lib/bundle/bundled.ts +35 -0
- package/src/lib/bundle/disconnected.abide +236 -0
- package/src/lib/bundle/disconnected.css +9 -0
- package/src/lib/bundle/ensureWebviewLib.ts +20 -0
- package/src/lib/bundle/exitWithParent.ts +28 -0
- package/src/lib/bundle/infoPlist.ts +46 -0
- package/src/lib/bundle/installDownloads.ts +24 -0
- package/src/lib/bundle/installMacMenu.ts +39 -0
- package/src/lib/bundle/listenLocalControlServer.ts +19 -0
- package/src/lib/bundle/native/abideMenu.mm +422 -0
- package/src/lib/bundle/native/webview.h +4557 -0
- package/src/lib/bundle/onMenu.ts +42 -0
- package/src/lib/bundle/openWebview.ts +104 -0
- package/src/lib/bundle/pngToIcns.ts +47 -0
- package/src/lib/bundle/probeAbideServer.ts +57 -0
- package/src/lib/bundle/resolveServerBinary.ts +12 -0
- package/src/lib/bundle/resolveWebviewLib.ts +53 -0
- package/src/lib/bundle/serverBinaryFilename.ts +8 -0
- package/src/lib/bundle/signMacApp.ts +37 -0
- package/src/lib/bundle/spawnEmbeddedServer.ts +64 -0
- package/src/lib/bundle/stableLocalPort.ts +19 -0
- package/src/lib/bundle/waitForServer.ts +23 -0
- package/src/lib/bundle/webviewCachePath.ts +23 -0
- package/src/lib/bundle/webviewLibName.ts +11 -0
- package/src/lib/cli/connectToServer.ts +23 -0
- package/src/lib/cli/createClient.ts +108 -0
- package/src/lib/cli/dispatchCommand.ts +71 -0
- package/src/lib/cli/loadEnvFromBinaryDir.ts +15 -0
- package/src/lib/cli/parseArgvForRpc.ts +100 -0
- package/src/lib/cli/printHelp.ts +119 -0
- package/src/lib/cli/printSessionHelp.ts +27 -0
- package/src/lib/cli/printSessionStatus.ts +21 -0
- package/src/lib/cli/printTrimmed.ts +8 -0
- package/src/lib/cli/printValue.ts +10 -0
- package/src/lib/cli/resolveCliTarget.ts +48 -0
- package/src/lib/cli/runCli.ts +176 -0
- package/src/lib/cli/runSession.ts +108 -0
- package/src/lib/cli/startLocalInstance.ts +14 -0
- package/src/lib/cli/tokenizeLine.ts +51 -0
- package/src/lib/cli/types/CliManifest.ts +9 -0
- package/src/lib/cli/types/CliManifestEntry.ts +17 -0
- package/src/lib/cli/types/CliTarget.ts +13 -0
- package/src/lib/mcp/annotationsForMethod.ts +29 -0
- package/src/lib/mcp/createMcpResourceServer.ts +102 -0
- package/src/lib/mcp/createMcpServer.ts +48 -0
- package/src/lib/mcp/dispatchMcpRequest.ts +138 -0
- package/src/lib/mcp/mcpResourceServerSlot.ts +18 -0
- package/src/lib/mcp/mcpSurface.ts +295 -0
- package/src/lib/mcp/toolResultFromResponse.ts +66 -0
- package/src/lib/mcp/types/JsonRpcRequest.ts +12 -0
- package/src/lib/mcp/types/JsonRpcResponse.ts +20 -0
- package/src/lib/mcp/types/McpResourceContents.ts +10 -0
- package/src/lib/mcp/types/McpResourceDescriptor.ts +6 -0
- package/src/lib/mcp/types/McpResourceServer.ts +12 -0
- package/src/lib/mcp/types/McpServer.ts +9 -0
- package/src/lib/mcp/types/McpServerOptions.ts +16 -0
- package/src/lib/server/AppModule.ts +47 -0
- package/src/lib/server/DELETE.ts +10 -0
- package/src/lib/server/GET.ts +10 -0
- package/src/lib/server/HEAD.ts +10 -0
- package/src/lib/server/PATCH.ts +10 -0
- package/src/lib/server/POST.ts +10 -0
- package/src/lib/server/PUT.ts +10 -0
- package/src/lib/server/agent.ts +86 -0
- package/src/lib/server/appDataDir.ts +16 -0
- package/src/lib/server/cli/buildEnvContent.ts +19 -0
- package/src/lib/server/cli/createTarGz.ts +77 -0
- package/src/lib/server/cli/handleCliDownload.ts +150 -0
- package/src/lib/server/cli/handleCliInstall.ts +37 -0
- package/src/lib/server/cli/installScript.ts +31 -0
- package/src/lib/server/cli/maxSourceMtime.ts +26 -0
- package/src/lib/server/cookies.ts +30 -0
- package/src/lib/server/env.ts +51 -0
- package/src/lib/server/error.ts +73 -0
- package/src/lib/server/json.ts +42 -0
- package/src/lib/server/jsonl.ts +47 -0
- package/src/lib/server/prompts/definePrompt.ts +21 -0
- package/src/lib/server/prompts/promptRegistry.ts +9 -0
- package/src/lib/server/prompts/registerPrompt.ts +6 -0
- package/src/lib/server/prompts/renderPromptTemplate.ts +17 -0
- package/src/lib/server/prompts/types/Prompt.ts +13 -0
- package/src/lib/server/prompts/types/PromptOptions.ts +12 -0
- package/src/lib/server/prompts/types/PromptRegistryEntry.ts +13 -0
- package/src/lib/server/prompts/types/PromptRoutes.ts +10 -0
- package/src/lib/server/reachable.ts +45 -0
- package/src/lib/server/redirect.ts +43 -0
- package/src/lib/server/request.ts +19 -0
- package/src/lib/server/rpc/defineVerb.ts +210 -0
- package/src/lib/server/rpc/dispatchVerbInProcess.ts +46 -0
- package/src/lib/server/rpc/findVerbByCommandName.ts +18 -0
- package/src/lib/server/rpc/parseArgs.ts +127 -0
- package/src/lib/server/rpc/readBodyWithinLimit.ts +44 -0
- package/src/lib/server/rpc/registerVerb.ts +6 -0
- package/src/lib/server/rpc/runWithVerbTimeout.ts +49 -0
- package/src/lib/server/rpc/types/RemoteHandler.ts +27 -0
- package/src/lib/server/rpc/types/RemoteRoutes.ts +13 -0
- package/src/lib/server/rpc/types/TypedResponse.ts +18 -0
- package/src/lib/server/rpc/types/VerbHelper.ts +87 -0
- package/src/lib/server/rpc/types/VerbRegistryEntry.ts +35 -0
- package/src/lib/server/rpc/unprocessed.ts +14 -0
- package/src/lib/server/rpc/verbRegistry.ts +11 -0
- package/src/lib/server/runtime/DEFAULT_PORT.ts +6 -0
- package/src/lib/server/runtime/DEV_READY_MESSAGE.ts +6 -0
- package/src/lib/server/runtime/DEV_REBUILD_MESSAGE.ts +4 -0
- package/src/lib/server/runtime/DEV_RELOAD_CLIENT_SCRIPT.ts +107 -0
- package/src/lib/server/runtime/SSR_SWAP_SCRIPT.ts +16 -0
- package/src/lib/server/runtime/acceptsGzip.ts +24 -0
- package/src/lib/server/runtime/buildCacheSnapshot.ts +61 -0
- package/src/lib/server/runtime/buildHealthPayload.ts +34 -0
- package/src/lib/server/runtime/buildInspectorSurface.ts +37 -0
- package/src/lib/server/runtime/buildOpenApiSpec.ts +106 -0
- package/src/lib/server/runtime/cacheControlForAsset.ts +22 -0
- package/src/lib/server/runtime/containsTraversal.ts +37 -0
- package/src/lib/server/runtime/createAppAssetServer.ts +76 -0
- package/src/lib/server/runtime/createAssetHeaderCache.ts +31 -0
- package/src/lib/server/runtime/createPublicAssetServer.ts +67 -0
- package/src/lib/server/runtime/createReachable.ts +109 -0
- package/src/lib/server/runtime/createRouteDispatcher.ts +127 -0
- package/src/lib/server/runtime/createServer.ts +674 -0
- package/src/lib/server/runtime/createUiPageRenderer.ts +181 -0
- package/src/lib/server/runtime/crossOriginForbidden.ts +17 -0
- package/src/lib/server/runtime/crossOriginGate.ts +29 -0
- package/src/lib/server/runtime/devClientFingerprint.ts +117 -0
- package/src/lib/server/runtime/devHotModuleResponse.ts +40 -0
- package/src/lib/server/runtime/devReloadResponse.ts +41 -0
- package/src/lib/server/runtime/disableIdleTimeoutForStream.ts +27 -0
- package/src/lib/server/runtime/envSchemaStore.ts +15 -0
- package/src/lib/server/runtime/findOpenPort.ts +21 -0
- package/src/lib/server/runtime/getActiveServer.ts +6 -0
- package/src/lib/server/runtime/globToPathSet.ts +29 -0
- package/src/lib/server/runtime/gzipResponse.ts +46 -0
- package/src/lib/server/runtime/inProcessServer.ts +20 -0
- package/src/lib/server/runtime/internalErrorResponse.ts +25 -0
- package/src/lib/server/runtime/isCrossOriginRequest.ts +23 -0
- package/src/lib/server/runtime/listenOnOpenPort.ts +36 -0
- package/src/lib/server/runtime/logExposedSurfaces.ts +156 -0
- package/src/lib/server/runtime/maybeMountInspector.ts +97 -0
- package/src/lib/server/runtime/mimeForExtension.ts +14 -0
- package/src/lib/server/runtime/pageUrlFromStore.ts +15 -0
- package/src/lib/server/runtime/parseIdleTimeout.ts +10 -0
- package/src/lib/server/runtime/parsePort.ts +11 -0
- package/src/lib/server/runtime/registryManifests.ts +66 -0
- package/src/lib/server/runtime/requestContext.ts +5 -0
- package/src/lib/server/runtime/resolvePageSnapshot.ts +25 -0
- package/src/lib/server/runtime/respondWithEmbeddedAsset.ts +18 -0
- package/src/lib/server/runtime/runWithRequestScope.ts +150 -0
- package/src/lib/server/runtime/safeJsonForScript.ts +17 -0
- package/src/lib/server/runtime/serializeCacheSnapshot.ts +45 -0
- package/src/lib/server/runtime/serverSlot.ts +13 -0
- package/src/lib/server/runtime/setActiveServer.ts +6 -0
- package/src/lib/server/runtime/snapshotEntryFromCache.ts +83 -0
- package/src/lib/server/runtime/streamCacheResolutions.ts +37 -0
- package/src/lib/server/runtime/streamFromIterator.ts +86 -0
- package/src/lib/server/runtime/types/Assets.ts +6 -0
- package/src/lib/server/runtime/types/DevReloadStamp.ts +18 -0
- package/src/lib/server/runtime/types/InspectorCacheEntry.ts +24 -0
- package/src/lib/server/runtime/types/InspectorCacheSnapshot.ts +11 -0
- package/src/lib/server/runtime/types/InspectorContext.ts +30 -0
- package/src/lib/server/runtime/types/InspectorSocket.ts +17 -0
- package/src/lib/server/runtime/types/InspectorSurface.ts +13 -0
- package/src/lib/server/runtime/types/InspectorVerb.ts +27 -0
- package/src/lib/server/runtime/types/RequestStore.ts +55 -0
- package/src/lib/server/runtime/warnUnguardedMcp.ts +32 -0
- package/src/lib/server/runtime/withResponseDefaults.ts +24 -0
- package/src/lib/server/server.ts +33 -0
- package/src/lib/server/socket.ts +32 -0
- package/src/lib/server/sockets/createSocketDispatcher.ts +337 -0
- package/src/lib/server/sockets/defineSocket.ts +179 -0
- package/src/lib/server/sockets/lookupSocket.ts +6 -0
- package/src/lib/server/sockets/registerSocket.ts +6 -0
- package/src/lib/server/sockets/socketOperations.ts +36 -0
- package/src/lib/server/sockets/socketRegistry.ts +9 -0
- package/src/lib/server/sockets/types/Socket.ts +23 -0
- package/src/lib/server/sockets/types/SocketClientFrame.ts +19 -0
- package/src/lib/server/sockets/types/SocketOperation.ts +22 -0
- package/src/lib/server/sockets/types/SocketOptions.ts +26 -0
- package/src/lib/server/sockets/types/SocketRegistryEntry.ts +19 -0
- package/src/lib/server/sockets/types/SocketRoutes.ts +10 -0
- package/src/lib/server/sockets/types/SocketServerFrame.ts +24 -0
- package/src/lib/server/sse.ts +54 -0
- package/src/lib/shared/ABIDE_PACKAGE_NAME.ts +7 -0
- package/src/lib/shared/ABIDE_VERSION.ts +9 -0
- package/src/lib/shared/CACHE_CONTROL_VALUES.ts +16 -0
- package/src/lib/shared/CACHE_WRAPPED.ts +8 -0
- package/src/lib/shared/CLI_PATH.ts +7 -0
- package/src/lib/shared/DEV_HOT_PREFIX.ts +7 -0
- package/src/lib/shared/DEV_RELOAD_PATH.ts +6 -0
- package/src/lib/shared/HEALTH_PATH.ts +7 -0
- package/src/lib/shared/HttpError.ts +20 -0
- package/src/lib/shared/IDENTITY_PATH.ts +6 -0
- package/src/lib/shared/INSPECTOR_PATH.ts +7 -0
- package/src/lib/shared/NAV_HEADER.ts +8 -0
- package/src/lib/shared/OFFLINE_HEADER.ts +8 -0
- package/src/lib/shared/REMOTE_FUNCTION.ts +8 -0
- package/src/lib/shared/REPLAYABLE_METHODS.ts +12 -0
- package/src/lib/shared/SOCKETS_PATH.ts +7 -0
- package/src/lib/shared/STREAMING_CONTENT_TYPES.ts +11 -0
- package/src/lib/shared/SocketDisconnectedError.ts +13 -0
- package/src/lib/shared/TEXT_PLAIN.ts +7 -0
- package/src/lib/shared/abideImportName.ts +44 -0
- package/src/lib/shared/abideLog.ts +38 -0
- package/src/lib/shared/activeCacheStore.ts +20 -0
- package/src/lib/shared/activePage.ts +25 -0
- package/src/lib/shared/appDataDir.ts +34 -0
- package/src/lib/shared/appNameSlot.ts +10 -0
- package/src/lib/shared/basePath.ts +10 -0
- package/src/lib/shared/basePathFromAppUrl.ts +20 -0
- package/src/lib/shared/baseSlot.ts +14 -0
- package/src/lib/shared/binaryDirEnvPath.ts +12 -0
- package/src/lib/shared/browserClientFlags.ts +10 -0
- package/src/lib/shared/buildRpcProxy.ts +39 -0
- package/src/lib/shared/buildRpcRequest.ts +70 -0
- package/src/lib/shared/buildSocketOverChannel.ts +58 -0
- package/src/lib/shared/bundleLayout.ts +36 -0
- package/src/lib/shared/cache.ts +951 -0
- package/src/lib/shared/cacheEntryFromSnapshot.ts +59 -0
- package/src/lib/shared/cacheStoreSlot.ts +16 -0
- package/src/lib/shared/cacheStores.ts +10 -0
- package/src/lib/shared/canonicalJson.ts +63 -0
- package/src/lib/shared/carriesBodyArgs.ts +13 -0
- package/src/lib/shared/clearLastConnection.ts +7 -0
- package/src/lib/shared/commandNameForUrl.ts +17 -0
- package/src/lib/shared/createCacheStore.ts +104 -0
- package/src/lib/shared/createChannelLog.ts +122 -0
- package/src/lib/shared/createLifecycleChannel.ts +56 -0
- package/src/lib/shared/createLivenessWatch.ts +118 -0
- package/src/lib/shared/createPushIterator.ts +127 -0
- package/src/lib/shared/createRemoteFunction.ts +122 -0
- package/src/lib/shared/createSubscriber.ts +55 -0
- package/src/lib/shared/createTraceContext.ts +21 -0
- package/src/lib/shared/dataDirEnvPath.ts +12 -0
- package/src/lib/shared/decodeResponse.ts +47 -0
- package/src/lib/shared/detectTarget.ts +27 -0
- package/src/lib/shared/detectVerbMethod.ts +17 -0
- package/src/lib/shared/emitLogRecord.ts +190 -0
- package/src/lib/shared/exeSuffix.ts +9 -0
- package/src/lib/shared/exitOnBuildFailure.ts +17 -0
- package/src/lib/shared/extraForwardHeaders.ts +16 -0
- package/src/lib/shared/fileStem.ts +9 -0
- package/src/lib/shared/findExportCallSite.ts +476 -0
- package/src/lib/shared/formatTraceparent.ts +6 -0
- package/src/lib/shared/forwardHeaders.ts +44 -0
- package/src/lib/shared/getRemoteMeta.ts +5 -0
- package/src/lib/shared/globalCacheStore.ts +15 -0
- package/src/lib/shared/globalCacheStoreSlot.ts +14 -0
- package/src/lib/shared/health.ts +179 -0
- package/src/lib/shared/healthReadSlot.ts +11 -0
- package/src/lib/shared/healthSeedSlot.ts +12 -0
- package/src/lib/shared/html.ts +38 -0
- package/src/lib/shared/importNamesToStrip.ts +13 -0
- package/src/lib/shared/invalidateEvent.ts +11 -0
- package/src/lib/shared/invalidateTripwire.ts +40 -0
- package/src/lib/shared/isAbideHealthPayload.ts +11 -0
- package/src/lib/shared/isCompileTarget.ts +15 -0
- package/src/lib/shared/isDebugEnabled.ts +26 -0
- package/src/lib/shared/isDebugNegated.ts +19 -0
- package/src/lib/shared/isModuleNotFound.ts +16 -0
- package/src/lib/shared/isReadOnlyMethod.ts +14 -0
- package/src/lib/shared/isReplayableMethod.ts +7 -0
- package/src/lib/shared/isStreamingResponse.ts +11 -0
- package/src/lib/shared/isSubscribable.ts +15 -0
- package/src/lib/shared/jsonSchemaForPromptArguments.ts +29 -0
- package/src/lib/shared/jsonSchemaForSchema.ts +39 -0
- package/src/lib/shared/jsonlErrorFrame.ts +24 -0
- package/src/lib/shared/keyForRemoteCall.ts +29 -0
- package/src/lib/shared/keyMatchesPrefix.ts +9 -0
- package/src/lib/shared/lastConnectionPath.ts +7 -0
- package/src/lib/shared/layoutChainForRoute.ts +22 -0
- package/src/lib/shared/loadEnvFile.ts +17 -0
- package/src/lib/shared/loadEnvFromDataDir.ts +14 -0
- package/src/lib/shared/log.ts +24 -0
- package/src/lib/shared/logClosingRecord.ts +28 -0
- package/src/lib/shared/logTapSlot.ts +13 -0
- package/src/lib/shared/manifestModule.ts +39 -0
- package/src/lib/shared/matchesDebugPattern.ts +16 -0
- package/src/lib/shared/memoizeByKey.ts +32 -0
- package/src/lib/shared/normalizeTarget.ts +10 -0
- package/src/lib/shared/online.ts +51 -0
- package/src/lib/shared/page.ts +30 -0
- package/src/lib/shared/pageSlot.ts +17 -0
- package/src/lib/shared/pageUrlForFile.ts +14 -0
- package/src/lib/shared/parseBoundedEnvInt.ts +20 -0
- package/src/lib/shared/parseDebugPatterns.ts +21 -0
- package/src/lib/shared/parseEnv.ts +30 -0
- package/src/lib/shared/parsePromptMarkdown.ts +35 -0
- package/src/lib/shared/parseRouteSegments.ts +22 -0
- package/src/lib/shared/parseTraceparent.ts +26 -0
- package/src/lib/shared/pending.ts +30 -0
- package/src/lib/shared/prepareRpcModule.ts +59 -0
- package/src/lib/shared/prepareSocketModule.ts +49 -0
- package/src/lib/shared/probeRegistries.ts +68 -0
- package/src/lib/shared/producerKey.ts +32 -0
- package/src/lib/shared/programNameForPackage.ts +14 -0
- package/src/lib/shared/promptNameForFile.ts +10 -0
- package/src/lib/shared/queryStringFromArgs.ts +27 -0
- package/src/lib/shared/randomHexId.ts +14 -0
- package/src/lib/shared/readEnvFile.ts +15 -0
- package/src/lib/shared/readLastConnection.ts +18 -0
- package/src/lib/shared/readPackageJson.ts +9 -0
- package/src/lib/shared/recordRemoteMeta.ts +5 -0
- package/src/lib/shared/refreshing.ts +31 -0
- package/src/lib/shared/remoteMetaStore.ts +16 -0
- package/src/lib/shared/requestScopeSlot.ts +15 -0
- package/src/lib/shared/resolveClientFlags.ts +20 -0
- package/src/lib/shared/responseErrorText.ts +9 -0
- package/src/lib/shared/rpcTimeoutSlot.ts +9 -0
- package/src/lib/shared/rpcUrlForFile.ts +19 -0
- package/src/lib/shared/runningAsStandaloneBinary.ts +13 -0
- package/src/lib/shared/selectorMatcher.ts +68 -0
- package/src/lib/shared/selectorPrefix.ts +39 -0
- package/src/lib/shared/serializeEnv.ts +18 -0
- package/src/lib/shared/setAppName.ts +5 -0
- package/src/lib/shared/setBaseResolver.ts +6 -0
- package/src/lib/shared/setCacheStoreResolver.ts +6 -0
- package/src/lib/shared/setGlobalCacheStoreResolver.ts +6 -0
- package/src/lib/shared/setPageResolver.ts +7 -0
- package/src/lib/shared/setRequestScopeResolver.ts +6 -0
- package/src/lib/shared/snippet.ts +25 -0
- package/src/lib/shared/socketNameForFile.ts +11 -0
- package/src/lib/shared/socketTapSlot.ts +12 -0
- package/src/lib/shared/sseErrorFrame.ts +29 -0
- package/src/lib/shared/streamResponse.ts +169 -0
- package/src/lib/shared/stripImport.ts +27 -0
- package/src/lib/shared/subscribableFromResponse.ts +51 -0
- package/src/lib/shared/tailProbeSlot.ts +16 -0
- package/src/lib/shared/toBunRoutePattern.ts +28 -0
- package/src/lib/shared/toScopeSet.ts +4 -0
- package/src/lib/shared/trace.ts +16 -0
- package/src/lib/shared/types/CacheEntry.ts +84 -0
- package/src/lib/shared/types/CacheInvalidation.ts +9 -0
- package/src/lib/shared/types/CacheOnContext.ts +25 -0
- package/src/lib/shared/types/CacheOptions.ts +39 -0
- package/src/lib/shared/types/CacheSelector.ts +17 -0
- package/src/lib/shared/types/CacheSnapshot.ts +16 -0
- package/src/lib/shared/types/CacheSnapshotEntry.ts +17 -0
- package/src/lib/shared/types/CacheStats.ts +13 -0
- package/src/lib/shared/types/CacheStore.ts +39 -0
- package/src/lib/shared/types/ChannelLog.ts +13 -0
- package/src/lib/shared/types/ClientFlags.ts +11 -0
- package/src/lib/shared/types/CompileTarget.ts +6 -0
- package/src/lib/shared/types/FrameworkLog.ts +13 -0
- package/src/lib/shared/types/HttpVerb.ts +1 -0
- package/src/lib/shared/types/LastConnection.ts +9 -0
- package/src/lib/shared/types/Log.ts +13 -0
- package/src/lib/shared/types/LogRecord.ts +42 -0
- package/src/lib/shared/types/LogVoice.ts +7 -0
- package/src/lib/shared/types/PageSnapshot.ts +14 -0
- package/src/lib/shared/types/PromptArgument.ts +12 -0
- package/src/lib/shared/types/RawRemoteFunction.ts +14 -0
- package/src/lib/shared/types/RemoteCallable.ts +12 -0
- package/src/lib/shared/types/RemoteFunction.ts +47 -0
- package/src/lib/shared/types/ReplayableMethod.ts +7 -0
- package/src/lib/shared/types/RequestScopeInfo.ts +16 -0
- package/src/lib/shared/types/RpcInvoker.ts +6 -0
- package/src/lib/shared/types/SocketChannel.ts +17 -0
- package/src/lib/shared/types/SocketSubCallbacks.ts +13 -0
- package/src/lib/shared/types/StandardSchemaV1.ts +56 -0
- package/src/lib/shared/types/StreamedResolution.ts +10 -0
- package/src/lib/shared/types/Subscribable.ts +26 -0
- package/src/lib/shared/types/TailHooks.ts +12 -0
- package/src/lib/shared/types/TailOptions.ts +10 -0
- package/src/lib/shared/types/TraceContext.ts +17 -0
- package/src/lib/shared/url.ts +118 -0
- package/src/lib/shared/withBase.ts +11 -0
- package/src/lib/shared/withBaseUrl.ts +17 -0
- package/src/lib/shared/withJsonSchema.ts +21 -0
- package/src/lib/shared/writeDts.ts +12 -0
- package/src/lib/shared/writeHealthDts.ts +36 -0
- package/src/lib/shared/writeLastConnection.ts +13 -0
- package/src/lib/shared/writePublicAssetsDts.ts +31 -0
- package/src/lib/shared/writeRoutesDts.ts +73 -0
- package/src/lib/shared/writeRpcDts.ts +49 -0
- package/src/lib/shared/writeTestRpcDts.ts +45 -0
- package/src/lib/shared/writeTestSocketsDts.ts +34 -0
- package/src/lib/test/assertAgentFrameConformance.ts +73 -0
- package/src/lib/test/createScriptedSurface.ts +45 -0
- package/src/lib/test/createTestApp.ts +203 -0
- package/src/lib/test/createTestSocketChannel.ts +142 -0
- package/src/lib/ui/README.md +86 -0
- package/src/lib/ui/compile/SSR_ESCAPE.ts +25 -0
- package/src/lib/ui/compile/UI_RUNTIME_IMPORTS.ts +36 -0
- package/src/lib/ui/compile/VOID_TAGS.ts +21 -0
- package/src/lib/ui/compile/abideUiPlugin.ts +65 -0
- package/src/lib/ui/compile/analyzeComponent.ts +117 -0
- package/src/lib/ui/compile/assetModulesFile.ts +32 -0
- package/src/lib/ui/compile/branchElements.ts +50 -0
- package/src/lib/ui/compile/collectAbideDiagnostics.ts +59 -0
- package/src/lib/ui/compile/compileComponent.ts +20 -0
- package/src/lib/ui/compile/compileModule.ts +116 -0
- package/src/lib/ui/compile/compileSSR.ts +36 -0
- package/src/lib/ui/compile/compileShadow.ts +352 -0
- package/src/lib/ui/compile/createShadowLanguageService.ts +197 -0
- package/src/lib/ui/compile/createShadowProgram.ts +96 -0
- package/src/lib/ui/compile/decodeHtmlEntities.ts +49 -0
- package/src/lib/ui/compile/desugarSignals.ts +133 -0
- package/src/lib/ui/compile/escapeHtml.ts +15 -0
- package/src/lib/ui/compile/generateBuild.ts +638 -0
- package/src/lib/ui/compile/generateSSR.ts +380 -0
- package/src/lib/ui/compile/groupBindParts.ts +28 -0
- package/src/lib/ui/compile/hoistCells.ts +120 -0
- package/src/lib/ui/compile/loadShadowTsConfig.ts +31 -0
- package/src/lib/ui/compile/lowerDocAccess.ts +202 -0
- package/src/lib/ui/compile/nearestProjectRoot.ts +16 -0
- package/src/lib/ui/compile/parseTemplate.ts +396 -0
- package/src/lib/ui/compile/partitionSlots.ts +36 -0
- package/src/lib/ui/compile/prepareNestedScript.ts +42 -0
- package/src/lib/ui/compile/remapShadowDiagnostic.ts +30 -0
- package/src/lib/ui/compile/renameSignalRefs.ts +85 -0
- package/src/lib/ui/compile/resolveAbideImports.ts +29 -0
- package/src/lib/ui/compile/scopeCss.ts +115 -0
- package/src/lib/ui/compile/shadowNaming.ts +11 -0
- package/src/lib/ui/compile/sourceToShadowOffset.ts +24 -0
- package/src/lib/ui/compile/staticAttrValue.ts +13 -0
- package/src/lib/ui/compile/stripEffects.ts +32 -0
- package/src/lib/ui/compile/types/AbideDiagnostic.ts +14 -0
- package/src/lib/ui/compile/types/AnalyzedComponent.ts +25 -0
- package/src/lib/ui/compile/types/CompiledShadow.ts +15 -0
- package/src/lib/ui/compile/types/TemplateAttr.ts +16 -0
- package/src/lib/ui/compile/types/TemplateNode.ts +78 -0
- package/src/lib/ui/compile/types/TextPart.ts +8 -0
- package/src/lib/ui/derived.ts +28 -0
- package/src/lib/ui/doc.ts +15 -0
- package/src/lib/ui/dom/appendSnippet.ts +34 -0
- package/src/lib/ui/dom/appendStatic.ts +27 -0
- package/src/lib/ui/dom/appendText.ts +114 -0
- package/src/lib/ui/dom/applyResolved.ts +72 -0
- package/src/lib/ui/dom/attach.ts +20 -0
- package/src/lib/ui/dom/attr.ts +19 -0
- package/src/lib/ui/dom/awaitBlock.ts +224 -0
- package/src/lib/ui/dom/cloneStatic.ts +52 -0
- package/src/lib/ui/dom/each.ts +115 -0
- package/src/lib/ui/dom/eachAsync.ts +153 -0
- package/src/lib/ui/dom/hydrate.ts +35 -0
- package/src/lib/ui/dom/mount.ts +29 -0
- package/src/lib/ui/dom/mountChild.ts +33 -0
- package/src/lib/ui/dom/on.ts +15 -0
- package/src/lib/ui/dom/openChild.ts +22 -0
- package/src/lib/ui/dom/openRoot.ts +20 -0
- package/src/lib/ui/dom/switchBlock.ts +75 -0
- package/src/lib/ui/dom/text.ts +20 -0
- package/src/lib/ui/dom/tryBlock.ts +112 -0
- package/src/lib/ui/dom/types/EachRow.ts +3 -0
- package/src/lib/ui/dom/types/SwitchCase.ts +6 -0
- package/src/lib/ui/dom/when.ts +73 -0
- package/src/lib/ui/effect.ts +16 -0
- package/src/lib/ui/installHotBridge.ts +73 -0
- package/src/lib/ui/matchRoute.ts +89 -0
- package/src/lib/ui/navigate.ts +17 -0
- package/src/lib/ui/probeNavigation.ts +33 -0
- package/src/lib/ui/remoteProxy.ts +97 -0
- package/src/lib/ui/renderChain.ts +50 -0
- package/src/lib/ui/renderToStream.ts +104 -0
- package/src/lib/ui/router.ts +286 -0
- package/src/lib/ui/runtime/OUTLET_TAG.ts +8 -0
- package/src/lib/ui/runtime/OWNER.ts +8 -0
- package/src/lib/ui/runtime/REACTIVE_CONTEXT.ts +14 -0
- package/src/lib/ui/runtime/RENDER.ts +23 -0
- package/src/lib/ui/runtime/RESUME.ts +16 -0
- package/src/lib/ui/runtime/applyPatchToTree.ts +41 -0
- package/src/lib/ui/runtime/claimChild.ts +10 -0
- package/src/lib/ui/runtime/clientPage.ts +16 -0
- package/src/lib/ui/runtime/createComputedNode.ts +16 -0
- package/src/lib/ui/runtime/createDoc.ts +177 -0
- package/src/lib/ui/runtime/createEffectNode.ts +58 -0
- package/src/lib/ui/runtime/createSignalNode.ts +16 -0
- package/src/lib/ui/runtime/detachLink.ts +21 -0
- package/src/lib/ui/runtime/endTracking.ts +24 -0
- package/src/lib/ui/runtime/enterRenderPass.ts +12 -0
- package/src/lib/ui/runtime/exitRenderPass.ts +7 -0
- package/src/lib/ui/runtime/firstOutlet.ts +22 -0
- package/src/lib/ui/runtime/flushEffects.ts +17 -0
- package/src/lib/ui/runtime/hotInstances.ts +10 -0
- package/src/lib/ui/runtime/hotReloadEnabled.ts +8 -0
- package/src/lib/ui/runtime/hotReplace.ts +25 -0
- package/src/lib/ui/runtime/nextBlockId.ts +11 -0
- package/src/lib/ui/runtime/pathExists.ts +23 -0
- package/src/lib/ui/runtime/readNode.ts +17 -0
- package/src/lib/ui/runtime/registerHotInstance.ts +23 -0
- package/src/lib/ui/runtime/runNode.ts +28 -0
- package/src/lib/ui/runtime/runtimePath.ts +9 -0
- package/src/lib/ui/runtime/scope.ts +24 -0
- package/src/lib/ui/runtime/toTeardown.ts +26 -0
- package/src/lib/ui/runtime/track.ts +58 -0
- package/src/lib/ui/runtime/trigger.ts +44 -0
- package/src/lib/ui/runtime/types/Cell.ts +5 -0
- package/src/lib/ui/runtime/types/Derived.ts +3 -0
- package/src/lib/ui/runtime/types/Doc.ts +19 -0
- package/src/lib/ui/runtime/types/EffectResult.ts +10 -0
- package/src/lib/ui/runtime/types/HotInstance.ts +14 -0
- package/src/lib/ui/runtime/types/NavVerdict.ts +9 -0
- package/src/lib/ui/runtime/types/Patch.ts +11 -0
- package/src/lib/ui/runtime/types/ReactiveLink.ts +21 -0
- package/src/lib/ui/runtime/types/ReactiveNode.ts +25 -0
- package/src/lib/ui/runtime/types/Route.ts +8 -0
- package/src/lib/ui/runtime/types/RouteLoader.ts +7 -0
- package/src/lib/ui/runtime/types/SsrRender.ts +22 -0
- package/src/lib/ui/runtime/types/State.ts +3 -0
- package/src/lib/ui/runtime/types/Teardown.ts +5 -0
- package/src/lib/ui/runtime/types/UiComponent.ts +16 -0
- package/src/lib/ui/runtime/types/UiProps.ts +15 -0
- package/src/lib/ui/runtime/unlinkDeps.ts +20 -0
- package/src/lib/ui/runtime/untrack.ts +20 -0
- package/src/lib/ui/runtime/valueAtPath.ts +18 -0
- package/src/lib/ui/runtime/writeNode.ts +16 -0
- package/src/lib/ui/socketChannel.ts +227 -0
- package/src/lib/ui/socketProxy.ts +25 -0
- package/src/lib/ui/startClient.ts +58 -0
- package/src/lib/ui/state.ts +25 -0
- package/src/lib/ui/tail.ts +324 -0
- package/src/lib/ui/types/Layouts.ts +9 -0
- package/src/lib/ui/types/Pages.ts +8 -0
- package/src/preload.ts +19 -0
- package/src/scaffold.ts +153 -0
- package/src/serverBuildPlugins.ts +19 -0
- package/src/serverEntry.ts +95 -0
- package/template/bunfig.toml +4 -0
- package/template/package.json +18 -0
- package/template/src/app.ts +28 -0
- package/template/src/bundle/icon.png +0 -0
- package/template/src/cli/banner.txt +3 -0
- package/template/src/cli/footer.txt +1 -0
- package/template/src/server/config.ts +17 -0
- package/template/src/server/rpc/getHello.ts +36 -0
- package/template/src/ui/Layout.abide +19 -0
- package/template/src/ui/app.css +21 -0
- package/template/src/ui/app.html +24 -0
- package/template/src/ui/pages/about/page.abide +9 -0
- package/template/src/ui/pages/page.abide +22 -0
- package/template/test/app.test.ts +30 -0
- package/template/tsconfig.json +18 -0
- package/tsconfig.app.json +17 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { rawHtmlString } from '../../shared/html.ts'
|
|
2
|
+
import { snippetPayload } from '../../shared/snippet.ts'
|
|
3
|
+
import { effect } from '../effect.ts'
|
|
4
|
+
import { claimChild } from '../runtime/claimChild.ts'
|
|
5
|
+
import { RENDER } from '../runtime/RENDER.ts'
|
|
6
|
+
import { appendSnippet } from './appendSnippet.ts'
|
|
7
|
+
|
|
8
|
+
const CLOSE = '/abide:html'
|
|
9
|
+
|
|
10
|
+
/*
|
|
11
|
+
A reactive `{expr}` interpolation under `parent`. A plain value is an escaped text
|
|
12
|
+
node: created and appended (create), or the server-rendered text node claimed
|
|
13
|
+
(hydrate) and bound. Adjacent SSR text merges into one node, so on hydrate the
|
|
14
|
+
claimed node is split at the current value's length — deterministic, because
|
|
15
|
+
`read()` returns the same value the server rendered.
|
|
16
|
+
|
|
17
|
+
A value branded by `html\`…\`` (see abide/shared/html) inserts raw markup instead:
|
|
18
|
+
its parsed nodes go between an anchor (create), or the server-rendered nodes
|
|
19
|
+
between `<!--abide:html-->`/`<!--/abide:html-->` markers are adopted (hydrate), and
|
|
20
|
+
a change re-parses and swaps. A binding is text or raw for its lifetime (decided by
|
|
21
|
+
its first value), so plain text — the common case — stays a cheap single node.
|
|
22
|
+
*/
|
|
23
|
+
// @readme plumbing
|
|
24
|
+
export function appendText(parent: Node, read: () => unknown, splitAlways = false): void {
|
|
25
|
+
/* A snippet call (`{row(args)}`) mounts its builder; a `html\`\`` value inserts
|
|
26
|
+
raw markup; everything else is escaped text — decided by the first value. */
|
|
27
|
+
if (typeof snippetPayload(read()) === 'function') {
|
|
28
|
+
appendSnippet(parent, read)
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
if (rawHtmlString(read()) !== undefined) {
|
|
32
|
+
appendRawHtml(parent, read)
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
const hydration = RENDER.hydration
|
|
36
|
+
if (hydration !== undefined) {
|
|
37
|
+
const node = claimChild(hydration, parent) as unknown as Text
|
|
38
|
+
const value = String(read())
|
|
39
|
+
/* Peel this binding's text off the merged SSR node. A non-final binding in a
|
|
40
|
+
run (`splitAlways`) splits even when it consumes the whole node, leaving an
|
|
41
|
+
empty node for the next binding — otherwise an interpolation that renders to
|
|
42
|
+
empty string (or whose followers do) has no node and the next claim grabs the
|
|
43
|
+
wrong sibling. The final binding keeps `<` so it doesn't leave a stray node a
|
|
44
|
+
following element would claim. */
|
|
45
|
+
if (
|
|
46
|
+
node !== null &&
|
|
47
|
+
(splitAlways ? value.length <= node.data.length : value.length < node.data.length)
|
|
48
|
+
) {
|
|
49
|
+
node.splitText(value.length)
|
|
50
|
+
}
|
|
51
|
+
hydration.next.set(parent, node === null ? null : node.nextSibling)
|
|
52
|
+
effect(() => {
|
|
53
|
+
node.data = String(read())
|
|
54
|
+
})
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
const node = document.createTextNode('')
|
|
58
|
+
parent.appendChild(node)
|
|
59
|
+
effect(() => {
|
|
60
|
+
node.data = String(read())
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/* Raw-markup interpolation: parse the branded string into nodes behind an anchor,
|
|
65
|
+
re-parsing on change; on hydrate adopt the server markup between its markers. */
|
|
66
|
+
function appendRawHtml(parent: Node, read: () => unknown): void {
|
|
67
|
+
const hydration = RENDER.hydration
|
|
68
|
+
const markup = (): string => rawHtmlString(read()) ?? ''
|
|
69
|
+
const anchor = document.createTextNode('')
|
|
70
|
+
let nodes: Node[] = []
|
|
71
|
+
|
|
72
|
+
const set = (value: string): void => {
|
|
73
|
+
for (const node of nodes) {
|
|
74
|
+
parent.removeChild(node)
|
|
75
|
+
}
|
|
76
|
+
const holder = document.createElement('div')
|
|
77
|
+
holder.innerHTML = value
|
|
78
|
+
nodes = [...holder.childNodes]
|
|
79
|
+
for (const node of nodes) {
|
|
80
|
+
parent.insertBefore(node, anchor)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (hydration !== undefined) {
|
|
85
|
+
const open = claimChild(hydration, parent)
|
|
86
|
+
let node: Node | null = open === null ? null : open.nextSibling
|
|
87
|
+
while (node !== null && !isComment(node, CLOSE)) {
|
|
88
|
+
nodes.push(node)
|
|
89
|
+
node = node.nextSibling
|
|
90
|
+
}
|
|
91
|
+
hydration.next.set(parent, node === null ? null : node.nextSibling)
|
|
92
|
+
parent.insertBefore(anchor, node)
|
|
93
|
+
let first = true
|
|
94
|
+
effect(() => {
|
|
95
|
+
const value = markup()
|
|
96
|
+
if (first) {
|
|
97
|
+
first = false // adopt the server markup as-is
|
|
98
|
+
return
|
|
99
|
+
}
|
|
100
|
+
set(value)
|
|
101
|
+
})
|
|
102
|
+
return
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
parent.appendChild(anchor)
|
|
106
|
+
effect(() => {
|
|
107
|
+
set(markup())
|
|
108
|
+
})
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/* A comment node carrying exactly `data`. */
|
|
112
|
+
function isComment(node: Node, data: string): boolean {
|
|
113
|
+
return (node as { data?: string }).data === data && node.childNodes.length === 0
|
|
114
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { RESUME } from '../runtime/RESUME.ts'
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
Client consumer of an SSR stream fragment. Parses a streamed
|
|
5
|
+
`<abide-resolve data-id="ID" data-resume="…">…</abide-resolve>` frame, registers
|
|
6
|
+
its serialized value in the resume manifest (for later hydration), finds the
|
|
7
|
+
matching `<!--abide:await:ID-->…<!--/abide:await:ID-->` boundary in `root`, removes
|
|
8
|
+
the pending nodes between the markers, and inserts the resolved content in their
|
|
9
|
+
place. The pending shell painted instantly; this swaps in each value as it
|
|
10
|
+
arrives — completing the out-of-order streaming loop on the client.
|
|
11
|
+
*/
|
|
12
|
+
// @readme plumbing
|
|
13
|
+
export function applyResolved(root: Element, frame: string): void {
|
|
14
|
+
const holder = document.createElement('div')
|
|
15
|
+
holder.innerHTML = frame
|
|
16
|
+
const resolved = holder.firstChild as Element | null
|
|
17
|
+
if (resolved === null || resolved.getAttribute === undefined) {
|
|
18
|
+
return
|
|
19
|
+
}
|
|
20
|
+
const id = resolved.getAttribute('data-id')
|
|
21
|
+
if (id === null) {
|
|
22
|
+
return
|
|
23
|
+
}
|
|
24
|
+
/* Record the resolved value so a later hydrate adopts this branch (no re-fetch). */
|
|
25
|
+
const resume = resolved.getAttribute('data-resume')
|
|
26
|
+
if (resume !== null) {
|
|
27
|
+
try {
|
|
28
|
+
RESUME[Number(id)] = JSON.parse(resume)
|
|
29
|
+
} catch {
|
|
30
|
+
/* malformed payload — leave unregistered, hydration re-runs the promise */
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const open = `abide:await:${id}`
|
|
34
|
+
const close = `/abide:await:${id}`
|
|
35
|
+
const boundary = findBoundary(root, open)
|
|
36
|
+
if (boundary === undefined) {
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
const { parent, start } = boundary
|
|
40
|
+
/* Remove the pending nodes between the markers (exclusive of the markers). */
|
|
41
|
+
let node = start.nextSibling
|
|
42
|
+
while (node !== null && !isComment(node, close)) {
|
|
43
|
+
const next = node.nextSibling
|
|
44
|
+
parent.removeChild(node)
|
|
45
|
+
node = next
|
|
46
|
+
}
|
|
47
|
+
/* Insert resolved content after the open marker. */
|
|
48
|
+
let anchor = start.nextSibling
|
|
49
|
+
for (const child of [...resolved.childNodes]) {
|
|
50
|
+
parent.insertBefore(child, anchor)
|
|
51
|
+
anchor = child.nextSibling
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* A comment node carrying exactly `data`. */
|
|
56
|
+
function isComment(node: Node, data: string): boolean {
|
|
57
|
+
return (node as { data?: string }).data === data && node.childNodes.length === 0
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* Depth-first search for the parent + open-marker comment of a boundary. */
|
|
61
|
+
function findBoundary(node: Node, open: string): { parent: Node; start: Node } | undefined {
|
|
62
|
+
for (const child of [...node.childNodes]) {
|
|
63
|
+
if (isComment(child, open)) {
|
|
64
|
+
return { parent: node, start: child }
|
|
65
|
+
}
|
|
66
|
+
const nested = findBoundary(child, open)
|
|
67
|
+
if (nested !== undefined) {
|
|
68
|
+
return nested
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return undefined
|
|
72
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { OWNER } from '../runtime/OWNER.ts'
|
|
2
|
+
import { toTeardown } from '../runtime/toTeardown.ts'
|
|
3
|
+
import type { EffectResult } from '../runtime/types/EffectResult.ts'
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
Runs an attachment against an element at build time and registers its optional
|
|
7
|
+
teardown with the current ownership scope, so it detaches when the component
|
|
8
|
+
disposes. The dual of `on`: where `on` owns a listener, `attach` owns whatever
|
|
9
|
+
the attachment sets up. Node-lifetime, not reactive — for param reactivity put an
|
|
10
|
+
`effect` inside the attachment and return its dispose. The attachment may be
|
|
11
|
+
async; its teardown then runs once the promise settles. Runtime target for an
|
|
12
|
+
`attach={…}` binding.
|
|
13
|
+
*/
|
|
14
|
+
// @readme plumbing
|
|
15
|
+
export function attach(element: Element, attachment: (node: Element) => EffectResult): void {
|
|
16
|
+
const teardown = toTeardown(attachment(element))
|
|
17
|
+
if (teardown !== undefined && OWNER.current !== undefined) {
|
|
18
|
+
OWNER.current.push(teardown)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { effect } from '../effect.ts'
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
Binds an element attribute to `read()`. A boolean true sets the bare attribute,
|
|
5
|
+
and false/null/undefined removes it (the standard present/absent semantics);
|
|
6
|
+
anything else is stringified. One effect per bound attribute, so only the
|
|
7
|
+
changed attribute touches the DOM.
|
|
8
|
+
*/
|
|
9
|
+
// @readme plumbing
|
|
10
|
+
export function attr(element: Element, name: string, read: () => unknown): void {
|
|
11
|
+
effect(() => {
|
|
12
|
+
const value = read()
|
|
13
|
+
if (value === false || value === null || value === undefined) {
|
|
14
|
+
element.removeAttribute(name)
|
|
15
|
+
} else {
|
|
16
|
+
element.setAttribute(name, value === true ? '' : String(value))
|
|
17
|
+
}
|
|
18
|
+
})
|
|
19
|
+
}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { effect } from '../effect.ts'
|
|
2
|
+
import { claimChild } from '../runtime/claimChild.ts'
|
|
3
|
+
import { RENDER } from '../runtime/RENDER.ts'
|
|
4
|
+
import { RESUME } from '../runtime/RESUME.ts'
|
|
5
|
+
import { scope } from '../runtime/scope.ts'
|
|
6
|
+
|
|
7
|
+
/*
|
|
8
|
+
Async binding — the runtime for `<template await>`. Renders the pending branch,
|
|
9
|
+
then swaps to the resolved branch (with the value) or the error branch on settle.
|
|
10
|
+
Each branch is a RANGE of element roots, tracked as a node array so a multi-root
|
|
11
|
+
branch inserts/removes as a unit.
|
|
12
|
+
|
|
13
|
+
The read runs inside a abide-ui `effect`, so it's reactive: `abide/shared/cache`'s
|
|
14
|
+
store subscribes the key it reads to this effect (createSubscriber is abide-ui-
|
|
15
|
+
native), so `cache.invalidate()` of that key re-runs the block — pending, then the
|
|
16
|
+
fresh value swaps in. A read that touches no reactive source runs exactly once.
|
|
17
|
+
|
|
18
|
+
Hydration adopts in place, by precedence:
|
|
19
|
+
1. a streamed resume value (`RESUME[id]`) → adopt the resolved branch the stream
|
|
20
|
+
swapped in, no read (the promise never runs — a plain producer resume);
|
|
21
|
+
2. a warm-sync read (a non-thenable result) → adopt the SSR branch with it;
|
|
22
|
+
3. otherwise (genuinely pending) → discard the SSR boundary and run fresh.
|
|
23
|
+
After the first (adopting) run, later invalidations swap content before an anchor
|
|
24
|
+
parked just before the close marker.
|
|
25
|
+
*/
|
|
26
|
+
// @readme plumbing
|
|
27
|
+
export function awaitBlock(
|
|
28
|
+
parent: Node,
|
|
29
|
+
id: number,
|
|
30
|
+
promiseThunk: () => unknown,
|
|
31
|
+
renderPending: ((parent: Node) => Node[]) | undefined,
|
|
32
|
+
renderThen: (parent: Node, value: unknown) => Node[],
|
|
33
|
+
/* Absent when the block has no catch branch — a rejection then surfaces (re-throws
|
|
34
|
+
to the unhandled-rejection path) instead of rendering an empty branch. */
|
|
35
|
+
renderCatch: ((parent: Node, error: unknown) => Node[]) | undefined,
|
|
36
|
+
): void {
|
|
37
|
+
const hydration = RENDER.hydration
|
|
38
|
+
let active: { nodes: Node[]; dispose: () => void } | undefined
|
|
39
|
+
let anchor: Node | undefined
|
|
40
|
+
let first = true
|
|
41
|
+
/* Bumped each run so a prior run's in-flight promise can't clobber a newer one. */
|
|
42
|
+
let generation = 0
|
|
43
|
+
|
|
44
|
+
const detach = (): void => {
|
|
45
|
+
if (active !== undefined) {
|
|
46
|
+
active.dispose()
|
|
47
|
+
for (const node of active.nodes) {
|
|
48
|
+
parent.removeChild(node)
|
|
49
|
+
}
|
|
50
|
+
active = undefined
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* Replace the current content with a freshly-built range, before the anchor. */
|
|
55
|
+
const place = (build: (parent: Node) => Node[]): void => {
|
|
56
|
+
detach()
|
|
57
|
+
let nodes: Node[] = []
|
|
58
|
+
const dispose = scope(() => {
|
|
59
|
+
nodes = build(parent)
|
|
60
|
+
})
|
|
61
|
+
active = { nodes, dispose }
|
|
62
|
+
for (const node of nodes) {
|
|
63
|
+
parent.insertBefore(node, anchor ?? null)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* Render a settled-or-pending result into the current generation. */
|
|
68
|
+
const render = (result: unknown): void => {
|
|
69
|
+
const gen = generation
|
|
70
|
+
if (!isThenable(result)) {
|
|
71
|
+
place((host) => renderThen(host, result)) // warm-sync → resolved now, no flash
|
|
72
|
+
return
|
|
73
|
+
}
|
|
74
|
+
if (renderPending !== undefined) {
|
|
75
|
+
place((host) => renderPending(host))
|
|
76
|
+
} else {
|
|
77
|
+
detach()
|
|
78
|
+
}
|
|
79
|
+
result.then(
|
|
80
|
+
(value) => {
|
|
81
|
+
if (gen === generation) {
|
|
82
|
+
place((host) => renderThen(host, value))
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
(error) => {
|
|
86
|
+
if (gen !== generation) {
|
|
87
|
+
return
|
|
88
|
+
}
|
|
89
|
+
/* No catch branch → surface the rejection instead of an empty branch. */
|
|
90
|
+
if (renderCatch === undefined) {
|
|
91
|
+
throw error
|
|
92
|
+
}
|
|
93
|
+
place((host) => renderCatch(host, error))
|
|
94
|
+
},
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/* Adopt an SSR-resolved branch in place (its roots claim the existing nodes),
|
|
99
|
+
then park an anchor just before the close marker for later swaps. */
|
|
100
|
+
const adopt = (open: Node | null, build: (parent: Node) => Node[]): void => {
|
|
101
|
+
const cursor = hydration as NonNullable<typeof hydration>
|
|
102
|
+
cursor.next.set(parent, open?.nextSibling ?? null)
|
|
103
|
+
let nodes: Node[] = []
|
|
104
|
+
const dispose = scope(() => {
|
|
105
|
+
nodes = build(parent)
|
|
106
|
+
})
|
|
107
|
+
const close = claimChild(cursor, parent)
|
|
108
|
+
cursor.next.set(parent, close?.nextSibling ?? null)
|
|
109
|
+
anchor = document.createTextNode('')
|
|
110
|
+
parent.insertBefore(anchor, close)
|
|
111
|
+
active = { nodes, dispose }
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* Discard the SSR boundary and (re)build the block from the live promise, fresh
|
|
115
|
+
(hydration off) — the recovery path when adoption can't use the server markup. */
|
|
116
|
+
const rebuildCold = (open: Node | null): void => {
|
|
117
|
+
detach()
|
|
118
|
+
discardBoundary(
|
|
119
|
+
parent,
|
|
120
|
+
open,
|
|
121
|
+
`/abide:await:${id}`,
|
|
122
|
+
hydration as NonNullable<typeof hydration>,
|
|
123
|
+
)
|
|
124
|
+
anchor = document.createTextNode('')
|
|
125
|
+
parent.appendChild(anchor)
|
|
126
|
+
const previous = RENDER.hydration
|
|
127
|
+
RENDER.hydration = undefined
|
|
128
|
+
try {
|
|
129
|
+
render(promiseThunk())
|
|
130
|
+
} finally {
|
|
131
|
+
RENDER.hydration = previous
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* The first run when hydrating: adopt by precedence (resume / warm-sync), else
|
|
136
|
+
discard the boundary and mount fresh. Adoption is guarded: a resume value that
|
|
137
|
+
didn't round-trip (e.g. a non-serializable Response) throws while building the
|
|
138
|
+
branch — fall back to the live promise, which reads the properly-reconstructed
|
|
139
|
+
warm cache (or re-fetches) instead of crashing hydration. */
|
|
140
|
+
const firstHydrate = (result: unknown): void => {
|
|
141
|
+
const cursor = hydration as NonNullable<typeof hydration>
|
|
142
|
+
const open = claimChild(cursor, parent)
|
|
143
|
+
const entry = RESUME[id]
|
|
144
|
+
if (entry !== undefined) {
|
|
145
|
+
let build: (host: Node) => Node[]
|
|
146
|
+
if (entry.ok) {
|
|
147
|
+
build = (host) => renderThen(host, entry.value)
|
|
148
|
+
} else if (renderCatch !== undefined) {
|
|
149
|
+
build = (host) => renderCatch(host, entry.error)
|
|
150
|
+
} else {
|
|
151
|
+
/* A resumed rejection with no catch branch surfaces (mirrors the cold
|
|
152
|
+
path); in practice the server 500s such a block, so none resumes. */
|
|
153
|
+
throw entry.error
|
|
154
|
+
}
|
|
155
|
+
try {
|
|
156
|
+
adopt(open, build)
|
|
157
|
+
} catch {
|
|
158
|
+
rebuildCold(open)
|
|
159
|
+
}
|
|
160
|
+
return
|
|
161
|
+
}
|
|
162
|
+
if (!isThenable(result)) {
|
|
163
|
+
try {
|
|
164
|
+
adopt(open, (host) => renderThen(host, result))
|
|
165
|
+
} catch {
|
|
166
|
+
rebuildCold(open)
|
|
167
|
+
}
|
|
168
|
+
return
|
|
169
|
+
}
|
|
170
|
+
discardBoundary(parent, open, `/abide:await:${id}`, cursor)
|
|
171
|
+
anchor = document.createTextNode('')
|
|
172
|
+
parent.appendChild(anchor)
|
|
173
|
+
render(result)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
effect(() => {
|
|
177
|
+
generation += 1
|
|
178
|
+
/* Read the promise EVERY run, including the first hydrate run, so the block
|
|
179
|
+
subscribes to its reactive source (a cache key). A cache-remote read is warm
|
|
180
|
+
on resume — it serves the snapshot without a network round-trip, so adoption
|
|
181
|
+
stays no-flash AND a later cache.invalidate re-runs the block. Without this
|
|
182
|
+
read a resume-adopted block has no deps and invalidate is a no-op. */
|
|
183
|
+
const result = promiseThunk()
|
|
184
|
+
if (first) {
|
|
185
|
+
first = false
|
|
186
|
+
if (hydration !== undefined) {
|
|
187
|
+
firstHydrate(result)
|
|
188
|
+
return
|
|
189
|
+
}
|
|
190
|
+
anchor = document.createTextNode('')
|
|
191
|
+
parent.appendChild(anchor)
|
|
192
|
+
}
|
|
193
|
+
render(result)
|
|
194
|
+
})
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/* Whether a value is Promise-like (the cold path); a non-thenable is warm-sync. */
|
|
198
|
+
function isThenable(value: unknown): value is Promise<unknown> {
|
|
199
|
+
return value !== null && typeof (value as { then?: unknown })?.then === 'function'
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/* Remove the SSR boundary — open marker through close marker (inclusive) — and
|
|
203
|
+
park the hydration cursor on the node after it, so a fresh run replaces it
|
|
204
|
+
without duplicating the server's pending shell. */
|
|
205
|
+
function discardBoundary(
|
|
206
|
+
parent: Node,
|
|
207
|
+
open: Node | null,
|
|
208
|
+
closeData: string,
|
|
209
|
+
hydration: NonNullable<(typeof RENDER)['hydration']>,
|
|
210
|
+
): void {
|
|
211
|
+
let node = open
|
|
212
|
+
let after: Node | null = null
|
|
213
|
+
while (node !== null) {
|
|
214
|
+
const next = node.nextSibling
|
|
215
|
+
const isClose = (node as { data?: string }).data === closeData
|
|
216
|
+
parent.removeChild(node)
|
|
217
|
+
if (isClose) {
|
|
218
|
+
after = next
|
|
219
|
+
break
|
|
220
|
+
}
|
|
221
|
+
node = next
|
|
222
|
+
}
|
|
223
|
+
hydration.next.set(parent, after)
|
|
224
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { claimChild } from '../runtime/claimChild.ts'
|
|
2
|
+
import { RENDER } from '../runtime/RENDER.ts'
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
Parsed-once `<template>` per unique static-skeleton string, reused across every
|
|
6
|
+
mount. A `<template>` (not a detached `<div>`) so table/select content parses by
|
|
7
|
+
the real content model, exactly as the browser parsed the server markup.
|
|
8
|
+
*/
|
|
9
|
+
const TEMPLATES = new Map<string, HTMLTemplateElement>()
|
|
10
|
+
|
|
11
|
+
function templateFor(html: string): HTMLTemplateElement {
|
|
12
|
+
let template = TEMPLATES.get(html)
|
|
13
|
+
if (template === undefined) {
|
|
14
|
+
template = document.createElement('template')
|
|
15
|
+
template.innerHTML = html
|
|
16
|
+
TEMPLATES.set(html, template)
|
|
17
|
+
}
|
|
18
|
+
return template
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/*
|
|
22
|
+
Appends a fully-static subtree (one or more top-level nodes) under `parent` — what
|
|
23
|
+
the compiler emits in place of the imperative `openChild`/`setAttribute`/
|
|
24
|
+
`appendStatic` chain when an element subtree carries no bindings, control flow, or
|
|
25
|
+
listeners. The skeleton string is generated by the same rules as the SSR back-end,
|
|
26
|
+
so it is byte-identical to the server markup.
|
|
27
|
+
|
|
28
|
+
Create mode: clone the cached template once per mount — a single deep clone (native
|
|
29
|
+
in the browser) instead of N create/append calls. Hydrate mode: nothing is built;
|
|
30
|
+
the server already rendered this exact markup, so it only advances the parent's
|
|
31
|
+
claim cursor past the run's top-level nodes (nothing inside binds, so none need
|
|
32
|
+
claiming individually). The node count comes from the parsed template, which has
|
|
33
|
+
the same top-level node count as the server markup.
|
|
34
|
+
*/
|
|
35
|
+
// @readme plumbing
|
|
36
|
+
export function cloneStatic(parent: Node, html: string): void {
|
|
37
|
+
const template = templateFor(html)
|
|
38
|
+
const hydration = RENDER.hydration
|
|
39
|
+
if (hydration !== undefined) {
|
|
40
|
+
let node = claimChild(hydration, parent)
|
|
41
|
+
let remaining = template.content.childNodes.length
|
|
42
|
+
while (remaining > 0 && node !== null) {
|
|
43
|
+
node = node.nextSibling
|
|
44
|
+
remaining -= 1
|
|
45
|
+
}
|
|
46
|
+
hydration.next.set(parent, node)
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
for (const child of template.content.childNodes) {
|
|
50
|
+
parent.appendChild(child.cloneNode(true))
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { effect } from '../effect.ts'
|
|
2
|
+
import { claimChild } from '../runtime/claimChild.ts'
|
|
3
|
+
import { OWNER } from '../runtime/OWNER.ts'
|
|
4
|
+
import { RENDER } from '../runtime/RENDER.ts'
|
|
5
|
+
import { scope } from '../runtime/scope.ts'
|
|
6
|
+
import type { EachRow } from './types/EachRow.ts'
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
Keyed list binding — the runtime for `<template each key=>`. Rows live in their own
|
|
10
|
+
region, bounded by a trailing anchor so positioning is relative to the each itself,
|
|
11
|
+
never `parent.firstChild` — a sibling before the each (e.g. a static nav link) must
|
|
12
|
+
not be treated as the first row. An effect tracks `items()` and reconciles by key:
|
|
13
|
+
a new key renders a row in its own ownership scope (so the row's bindings dispose
|
|
14
|
+
when it leaves), and a departed key disposes and is removed. Keying by identity
|
|
15
|
+
(not index) lets a row keep its node and inner effects across a reorder.
|
|
16
|
+
|
|
17
|
+
Placement walks the desired list *backwards* from the trailing anchor, holding a
|
|
18
|
+
cursor at the node each row should precede; a row already sitting there is left
|
|
19
|
+
untouched, so a stable list does zero DOM moves and an append does exactly one —
|
|
20
|
+
only out-of-place rows are re-inserted (`insertBefore` on an in-place node would
|
|
21
|
+
otherwise remove-then-reinsert it, O(rows) moves per change). Departed rows are
|
|
22
|
+
pruned *before* placement so their nodes can't shift the cursor's sibling checks.
|
|
23
|
+
|
|
24
|
+
On hydrate the SSR rows are already in place and in order: claim each one where it
|
|
25
|
+
sits (no reordering), park the anchor after them, and skip the first reconcile.
|
|
26
|
+
*/
|
|
27
|
+
// @readme plumbing
|
|
28
|
+
export function each<T>(
|
|
29
|
+
parent: Node,
|
|
30
|
+
items: () => Iterable<T>,
|
|
31
|
+
keyOf: (item: T) => string,
|
|
32
|
+
render: (parent: Node, item: T) => Node,
|
|
33
|
+
): void {
|
|
34
|
+
const rows = new Map<string, EachRow>()
|
|
35
|
+
|
|
36
|
+
/* Build one row in its own scope (render claims on hydrate, creates otherwise). */
|
|
37
|
+
const buildRow = (item: T): EachRow => {
|
|
38
|
+
let node: Node | undefined
|
|
39
|
+
const dispose = scope(() => {
|
|
40
|
+
node = render(parent, item)
|
|
41
|
+
})
|
|
42
|
+
return { node: node as Node, dispose }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const hydration = RENDER.hydration
|
|
46
|
+
let anchor: Node
|
|
47
|
+
/* When hydrating, the first effect run must NOT reconcile — the rows it would
|
|
48
|
+
build are already adopted in place below. */
|
|
49
|
+
let adopting = false
|
|
50
|
+
if (hydration !== undefined) {
|
|
51
|
+
for (const item of items()) {
|
|
52
|
+
rows.set(keyOf(item), buildRow(item)) // claims the SSR row where it sits
|
|
53
|
+
}
|
|
54
|
+
anchor = document.createTextNode('')
|
|
55
|
+
parent.insertBefore(anchor, claimChild(hydration, parent))
|
|
56
|
+
adopting = true
|
|
57
|
+
} else {
|
|
58
|
+
anchor = document.createTextNode('')
|
|
59
|
+
parent.appendChild(anchor)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
effect(() => {
|
|
63
|
+
/* Read (subscribe) every run, including the adopting one. Materialize a
|
|
64
|
+
non-array iterable to an array so a generator yields fresh each run and the
|
|
65
|
+
list can be safely traversed once for placement, once for pruning. */
|
|
66
|
+
const source = items()
|
|
67
|
+
if (adopting) {
|
|
68
|
+
adopting = false // rows already adopted in document order; nothing to move
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
const list = Array.isArray(source) ? source : [...source]
|
|
72
|
+
const keys = list.map(keyOf)
|
|
73
|
+
const present = new Set(keys)
|
|
74
|
+
/* Prune departed rows first so their nodes don't sit between survivors and
|
|
75
|
+
throw off the in-place sibling checks below. */
|
|
76
|
+
for (const [key, row] of rows) {
|
|
77
|
+
if (!present.has(key)) {
|
|
78
|
+
row.dispose()
|
|
79
|
+
parent.removeChild(row.node)
|
|
80
|
+
rows.delete(key)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/* Walk backwards from the anchor: `cursor` is the node the current row must
|
|
84
|
+
precede. A row already there keeps its place; only an out-of-order (or
|
|
85
|
+
freshly built) row is moved. Placement never touches preceding siblings. */
|
|
86
|
+
let cursor: Node = anchor
|
|
87
|
+
for (let index = list.length - 1; index >= 0; index -= 1) {
|
|
88
|
+
const key = keys[index] as string
|
|
89
|
+
let row = rows.get(key)
|
|
90
|
+
if (row === undefined) {
|
|
91
|
+
row = buildRow(list[index] as T)
|
|
92
|
+
rows.set(key, row)
|
|
93
|
+
}
|
|
94
|
+
if (row.node.nextSibling !== cursor) {
|
|
95
|
+
parent.insertBefore(row.node, cursor)
|
|
96
|
+
}
|
|
97
|
+
cursor = row.node
|
|
98
|
+
}
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
/* Dispose every row still live when the enclosing scope tears down. The effect's
|
|
102
|
+
own disposer only unsubscribes it from `items()`; it never reaches the per-row
|
|
103
|
+
ownership scopes, which are pruned only on the departed-key path above. Without
|
|
104
|
+
this, a row whose binding subscribes to a longer-lived signal (a module store,
|
|
105
|
+
the cache, `page`) stays in that signal's observers after the list unmounts. The
|
|
106
|
+
host's DOM is cleared by `mount`, so disposal need not remove the nodes. */
|
|
107
|
+
if (OWNER.current !== undefined) {
|
|
108
|
+
OWNER.current.push(() => {
|
|
109
|
+
for (const row of rows.values()) {
|
|
110
|
+
row.dispose()
|
|
111
|
+
}
|
|
112
|
+
rows.clear()
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
}
|