@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,380 @@
|
|
|
1
|
+
import { OUTLET_TAG } from '../runtime/OUTLET_TAG.ts'
|
|
2
|
+
import { branchElements } from './branchElements.ts'
|
|
3
|
+
import { escapeHtml } from './escapeHtml.ts'
|
|
4
|
+
import { groupBindParts } from './groupBindParts.ts'
|
|
5
|
+
import { lowerDocAccess } from './lowerDocAccess.ts'
|
|
6
|
+
import { partitionSlots } from './partitionSlots.ts'
|
|
7
|
+
import { nestedBindingNames } from './prepareNestedScript.ts'
|
|
8
|
+
import { renameSignalRefs } from './renameSignalRefs.ts'
|
|
9
|
+
import { staticAttrValue } from './staticAttrValue.ts'
|
|
10
|
+
import { stripEffects } from './stripEffects.ts'
|
|
11
|
+
import type { TemplateNode } from './types/TemplateNode.ts'
|
|
12
|
+
import { VOID_TAGS } from './VOID_TAGS.ts'
|
|
13
|
+
|
|
14
|
+
/*
|
|
15
|
+
Server code generator: turns the parsed template into statements that push HTML
|
|
16
|
+
fragments onto an output array, reading the document synchronously (no DOM, no
|
|
17
|
+
listeners). Same expression lowering as the client back-end, so server and client
|
|
18
|
+
render the same markup. Dynamic values go through `$esc`; `if` is a plain `if`,
|
|
19
|
+
`each` a `for…of`.
|
|
20
|
+
|
|
21
|
+
An `await` block emits boundary comments (`<!--abide:await:N-->…<!--/abide:await:N-->`)
|
|
22
|
+
and registers the promise plus its resolved/error string-renderers on `$awaits`. A
|
|
23
|
+
streaming block (no `then` on the tag) puts its pending branch between the markers;
|
|
24
|
+
`renderToStream` flushes each resolved fragment out of order — the await-block-streams
|
|
25
|
+
half of the cache rule. A blocking block (`then` on the tag) emits an empty boundary
|
|
26
|
+
and flags the entry, so `renderToStream` settles it before the first flush.
|
|
27
|
+
*/
|
|
28
|
+
export function generateSSR(
|
|
29
|
+
nodes: TemplateNode[],
|
|
30
|
+
stateNames: ReadonlySet<string>,
|
|
31
|
+
derivedNames: ReadonlySet<string>,
|
|
32
|
+
isLayout = false,
|
|
33
|
+
): string {
|
|
34
|
+
/* Compile-time counter for unique temp var names (runtime block ids, child render
|
|
35
|
+
results) — block ids themselves are allocated at runtime via nextBlockId(). */
|
|
36
|
+
let varCounter = 0
|
|
37
|
+
const nextVar = (prefix: string): string => `${prefix}${varCounter++}`
|
|
38
|
+
|
|
39
|
+
/* Branch-scoped nested-script bindings, deref'd to `.value` (see generateBuild). */
|
|
40
|
+
const localDerived = new Set<string>()
|
|
41
|
+
const derefScope = (): ReadonlySet<string> =>
|
|
42
|
+
localDerived.size === 0 ? derivedNames : new Set([...derivedNames, ...localDerived])
|
|
43
|
+
|
|
44
|
+
function lowerExpression(code: string): string {
|
|
45
|
+
return lowerDocAccess(renameSignalRefs(code, stateNames, derefScope()), 'model')
|
|
46
|
+
.trim()
|
|
47
|
+
.replace(/;$/, '')
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* Lowers a scoped-script body for SSR: rename refs, lower doc access, then strip
|
|
51
|
+
effects (client-only lifecycle that emits no HTML). */
|
|
52
|
+
function lowerScript(code: string): string {
|
|
53
|
+
return stripEffects(
|
|
54
|
+
lowerDocAccess(renameSignalRefs(code, stateNames, derefScope()), 'model').trim(),
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function push(target: string, literal: string): string {
|
|
59
|
+
return `${target}.push(${JSON.stringify(literal)});\n`
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function generateInto(children: TemplateNode[], target: string): string {
|
|
63
|
+
return children.map((child) => generate(child, target)).join('')
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* A control-flow branch's body: run its nested `<script>`s (lowered, in scope)
|
|
67
|
+
first, then push the element markup — so SSR re-seeds the same local signals
|
|
68
|
+
the client build does, keeping hydration aligned. */
|
|
69
|
+
function branchInto(children: TemplateNode[], context: string, target: string): string {
|
|
70
|
+
const added: string[] = []
|
|
71
|
+
for (const child of children) {
|
|
72
|
+
if (child.kind === 'script') {
|
|
73
|
+
for (const name of nestedBindingNames(child.code)) {
|
|
74
|
+
if (!localDerived.has(name)) {
|
|
75
|
+
localDerived.add(name)
|
|
76
|
+
added.push(name)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const scriptCode = children
|
|
82
|
+
.filter(
|
|
83
|
+
(child): child is Extract<TemplateNode, { kind: 'script' }> =>
|
|
84
|
+
child.kind === 'script',
|
|
85
|
+
)
|
|
86
|
+
.map((child) => `${lowerScript(child.code)}\n`)
|
|
87
|
+
.join('')
|
|
88
|
+
const markup = generateInto(branchElements(children, context, true), target)
|
|
89
|
+
for (const name of added) {
|
|
90
|
+
localDerived.delete(name)
|
|
91
|
+
}
|
|
92
|
+
return scriptCode + markup
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function generate(node: TemplateNode, target: string): string {
|
|
96
|
+
if (node.kind === 'text') {
|
|
97
|
+
return node.parts
|
|
98
|
+
.map((part) => {
|
|
99
|
+
if (part.kind === 'static') {
|
|
100
|
+
return part.value.trim() === '' ? '' : push(target, escapeHtml(part.value))
|
|
101
|
+
}
|
|
102
|
+
return `${target}.push($text(${lowerExpression(part.code)}));\n`
|
|
103
|
+
})
|
|
104
|
+
.join('')
|
|
105
|
+
}
|
|
106
|
+
if (node.kind === 'if') {
|
|
107
|
+
const elseBranch = node.children.find((child) => child.kind === 'case')
|
|
108
|
+
const thenChildren = node.children.filter((child) => child.kind !== 'case')
|
|
109
|
+
let code = `if (${lowerExpression(node.condition)}) {\n${branchInto(thenChildren, '<template if>', target)}}`
|
|
110
|
+
if (elseBranch !== undefined && elseBranch.kind === 'case') {
|
|
111
|
+
code += ` else {\n${branchInto(elseBranch.children, '<template else>', target)}}`
|
|
112
|
+
}
|
|
113
|
+
return `${code}\n`
|
|
114
|
+
}
|
|
115
|
+
if (node.kind === 'switch') {
|
|
116
|
+
const cases = node.children.filter(
|
|
117
|
+
(child): child is Extract<TemplateNode, { kind: 'case' }> => child.kind === 'case',
|
|
118
|
+
)
|
|
119
|
+
let code = `{ const $s = (${lowerExpression(node.subject)});\n`
|
|
120
|
+
let started = false
|
|
121
|
+
for (const branch of cases) {
|
|
122
|
+
if (branch.match !== undefined) {
|
|
123
|
+
code += `${started ? 'else ' : ''}if ($s === (${lowerExpression(branch.match)})) {\n${branchInto(branch.children, '<template case>', target)}}\n`
|
|
124
|
+
started = true
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const fallback = cases.find((branch) => branch.match === undefined)
|
|
128
|
+
if (fallback !== undefined) {
|
|
129
|
+
code += `${started ? 'else ' : ''}{\n${branchInto(fallback.children, '<template case>', target)}}\n`
|
|
130
|
+
}
|
|
131
|
+
return `${code}}\n`
|
|
132
|
+
}
|
|
133
|
+
if (node.kind === 'case') {
|
|
134
|
+
return ''
|
|
135
|
+
}
|
|
136
|
+
if (node.kind === 'snippet') {
|
|
137
|
+
/* A hoisted function returning the snippet's `$snip`-branded HTML string;
|
|
138
|
+
`{name(args)}` pushes it via `$text`, which wraps it in markers. */
|
|
139
|
+
const body = generateInto(node.children, '$o')
|
|
140
|
+
return `function ${node.name}(${node.params ?? ''}) {\nconst $o = [];\n${body}return $snip($o.join(''));\n}\n`
|
|
141
|
+
}
|
|
142
|
+
if (node.kind === 'script') {
|
|
143
|
+
/* A scoped reactive block: re-seed its local signals (lowered, in scope)
|
|
144
|
+
so SSR renders the same values the client build will. */
|
|
145
|
+
return `${lowerScript(node.code)}\n`
|
|
146
|
+
}
|
|
147
|
+
/* A `<style>` emits no markup — its scope attribute is already on the elements
|
|
148
|
+
it covers (above) and its CSS is bundled, not inlined. */
|
|
149
|
+
if (node.kind === 'style') {
|
|
150
|
+
return ''
|
|
151
|
+
}
|
|
152
|
+
if (node.kind === 'each') {
|
|
153
|
+
/* Async each (`await`) is drained on the client — render no rows on the
|
|
154
|
+
server (an infinite stream would hang SSR); the client inserts its anchor
|
|
155
|
+
before the next sibling during hydration, like an empty sync each. */
|
|
156
|
+
if (node.async) {
|
|
157
|
+
return ''
|
|
158
|
+
}
|
|
159
|
+
return `for (const ${node.as} of (${lowerExpression(node.items)})) {\n${branchInto(node.children, '<template each>', target)}}\n`
|
|
160
|
+
}
|
|
161
|
+
if (node.kind === 'await') {
|
|
162
|
+
return generateAwait(node, target)
|
|
163
|
+
}
|
|
164
|
+
if (node.kind === 'try') {
|
|
165
|
+
return generateTry(node, target)
|
|
166
|
+
}
|
|
167
|
+
if (node.kind === 'branch') {
|
|
168
|
+
return ''
|
|
169
|
+
}
|
|
170
|
+
if (node.kind === 'component') {
|
|
171
|
+
/* Server-render the child via its `render` and inline the HTML inside
|
|
172
|
+
the same wrapper the client mounts into, so SSR and client agree.
|
|
173
|
+
Props pass as thunks; slot content passes as a string-returning
|
|
174
|
+
`$children` the child invokes from its <slot>. */
|
|
175
|
+
const tag = node.name.toLowerCase()
|
|
176
|
+
const parts = node.props.map(
|
|
177
|
+
(prop) => `${JSON.stringify(prop.name)}: () => (${lowerExpression(prop.code)})`,
|
|
178
|
+
)
|
|
179
|
+
const groups = partitionSlots(node.children)
|
|
180
|
+
const slotCode = generateInto(groups.default, '$slot')
|
|
181
|
+
if (slotCode.trim() !== '') {
|
|
182
|
+
parts.push(
|
|
183
|
+
`"$children": () => { const $slot = []; ${slotCode}return $slot.join(''); }`,
|
|
184
|
+
)
|
|
185
|
+
}
|
|
186
|
+
if (groups.named.length > 0) {
|
|
187
|
+
const entries = groups.named
|
|
188
|
+
.map((group) => {
|
|
189
|
+
const code = generateInto(group.nodes, '$slot')
|
|
190
|
+
return `${JSON.stringify(group.name)}: () => { const $slot = []; ${code}return $slot.join(''); }`
|
|
191
|
+
})
|
|
192
|
+
.join(', ')
|
|
193
|
+
parts.push(`"$slots": { ${entries} }`)
|
|
194
|
+
}
|
|
195
|
+
/* Render the child and MERGE its await blocks into this page's `$awaits`
|
|
196
|
+
so they join the page's SSR stream — their markers carry render-pass
|
|
197
|
+
block ids (nextBlockId), unique across page + children, so the streamed
|
|
198
|
+
fragments resolve into the right boundaries. ($awaits is captured from
|
|
199
|
+
the enclosing render body, including from branch closures.) */
|
|
200
|
+
const result = nextVar('$child')
|
|
201
|
+
return (
|
|
202
|
+
push(target, `<${tag}>`) +
|
|
203
|
+
`const ${result} = ${node.name}.render({ ${parts.join(', ')} });\n` +
|
|
204
|
+
`${target}.push(${result}.html);\n` +
|
|
205
|
+
`for (const $a of ${result}.awaits) { $awaits.push($a); }\n` +
|
|
206
|
+
push(target, `</${tag}>`)
|
|
207
|
+
)
|
|
208
|
+
}
|
|
209
|
+
if (node.kind === 'element' && node.tag === 'slot') {
|
|
210
|
+
/* A layout's unnamed `<slot/>` is the router's page outlet: emit an empty
|
|
211
|
+
placeholder the chain composer folds the child layer's html into. */
|
|
212
|
+
if (isLayout && staticAttrValue(node, 'name') === undefined) {
|
|
213
|
+
return push(target, `<${OUTLET_TAG}></${OUTLET_TAG}>`)
|
|
214
|
+
}
|
|
215
|
+
return generateSlot(node, target)
|
|
216
|
+
}
|
|
217
|
+
let code = push(target, `<${node.tag}`)
|
|
218
|
+
/* Every `<style>` active at this element (own siblings + ancestors) — same set
|
|
219
|
+
the client stamps, so server and client markup carry identical attributes. */
|
|
220
|
+
for (const scope of node.scopes ?? []) {
|
|
221
|
+
code += push(target, ` ${scope}=""`)
|
|
222
|
+
}
|
|
223
|
+
for (const attr of node.attrs) {
|
|
224
|
+
if (attr.kind === 'static') {
|
|
225
|
+
/* Escape the literal value so a `"`/`&`/`<` in it can't break out of
|
|
226
|
+
the attribute or inject markup (the client uses setAttribute, which
|
|
227
|
+
needs no escaping — escaping here keeps SSR and client in sync). */
|
|
228
|
+
code += push(target, ` ${attr.name}="${escapeHtml(attr.value)}"`)
|
|
229
|
+
} else if (attr.kind === 'expression') {
|
|
230
|
+
/* present/absent semantics matching the client `attr` binding:
|
|
231
|
+
false/null/undefined drops it, true emits the bare attribute. */
|
|
232
|
+
code += `${target}.push($attr(${JSON.stringify(attr.name)}, ${lowerExpression(attr.code)}));\n`
|
|
233
|
+
} else if (attr.kind === 'bind' && attr.property === 'group') {
|
|
234
|
+
/* Render the checked state as a boolean attribute: present when the
|
|
235
|
+
path holds (radio) or contains (checkbox) this control's value. */
|
|
236
|
+
const { valueCode, isRadio } = groupBindParts(node)
|
|
237
|
+
const present = isRadio
|
|
238
|
+
? `(${lowerExpression(attr.code)}) === (${lowerExpression(valueCode)})`
|
|
239
|
+
: `(${lowerExpression(attr.code)}).includes(${lowerExpression(valueCode)})`
|
|
240
|
+
code += `${target}.push((${present}) ? ' checked' : '');\n`
|
|
241
|
+
} else if (attr.kind === 'bind' && attr.property === 'checked') {
|
|
242
|
+
/* A boolean property — its mere presence means checked, so emit the
|
|
243
|
+
attribute only when truthy (a string `checked="false"` still checks). */
|
|
244
|
+
code += `${target}.push((${lowerExpression(attr.code)}) ? ' checked' : '');\n`
|
|
245
|
+
} else if (attr.kind === 'bind') {
|
|
246
|
+
code += `${target}.push(${JSON.stringify(` ${attr.property}="`)} + $esc(${lowerExpression(attr.code)}) + '"');\n`
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
code += push(target, '>')
|
|
250
|
+
if (!VOID_TAGS.has(node.tag)) {
|
|
251
|
+
/* A `<script>` child scopes its bindings to this element's subtree. */
|
|
252
|
+
const added: string[] = []
|
|
253
|
+
for (const child of node.children) {
|
|
254
|
+
if (child.kind === 'script') {
|
|
255
|
+
for (const name of nestedBindingNames(child.code)) {
|
|
256
|
+
if (!localDerived.has(name)) {
|
|
257
|
+
localDerived.add(name)
|
|
258
|
+
added.push(name)
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
code += generateInto(node.children, target)
|
|
264
|
+
for (const name of added) {
|
|
265
|
+
localDerived.delete(name)
|
|
266
|
+
}
|
|
267
|
+
code += push(target, `</${node.tag}>`)
|
|
268
|
+
}
|
|
269
|
+
return code
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/* A `<slot>` outlet: emit the parent-provided content for this slot (default
|
|
273
|
+
via `$children`, named via `$slots[name]`), falling back to the slot's own
|
|
274
|
+
children when none was supplied. */
|
|
275
|
+
function generateSlot(
|
|
276
|
+
node: Extract<TemplateNode, { kind: 'element' }>,
|
|
277
|
+
target: string,
|
|
278
|
+
): string {
|
|
279
|
+
const name = staticAttrValue(node, 'name')
|
|
280
|
+
const guard =
|
|
281
|
+
name === undefined
|
|
282
|
+
? '$props && $props.$children'
|
|
283
|
+
: `$props && $props.$slots && $props.$slots[${JSON.stringify(name)}]`
|
|
284
|
+
const provided =
|
|
285
|
+
name === undefined ? '$props.$children' : `$props.$slots[${JSON.stringify(name)}]`
|
|
286
|
+
const fallback = generateInto(node.children, target)
|
|
287
|
+
if (fallback.trim() === '') {
|
|
288
|
+
return `if (${guard}) { ${target}.push(${provided}()); }\n`
|
|
289
|
+
}
|
|
290
|
+
return `if (${guard}) { ${target}.push(${provided}()); } else {\n${fallback}}\n`
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/* Boundary markers + a `$awaits` registration carrying the promise and
|
|
294
|
+
string-renderers for the resolved/error branches. Streaming emits the pending
|
|
295
|
+
branch between the markers (flushed now, value streamed later); blocking emits
|
|
296
|
+
an empty boundary — its resolved branch is the children bound to `node.as` — and
|
|
297
|
+
flags the entry so `renderToStream` settles it before the first flush. */
|
|
298
|
+
function generateAwait(node: Extract<TemplateNode, { kind: 'await' }>, target: string): string {
|
|
299
|
+
const branchOf = (which: 'then' | 'catch' | 'finally') =>
|
|
300
|
+
node.children.find(
|
|
301
|
+
(child): child is Extract<TemplateNode, { kind: 'branch' }> =>
|
|
302
|
+
child.kind === 'branch' && child.branch === which,
|
|
303
|
+
)
|
|
304
|
+
const catchBranch = branchOf('catch')
|
|
305
|
+
const finallyChildren = branchOf('finally')?.children ?? []
|
|
306
|
+
/* Resolved branch + its bound value: the children directly when blocking, the
|
|
307
|
+
`then` child when streaming. Pending (streaming only) is the non-branch
|
|
308
|
+
children. */
|
|
309
|
+
const thenBranch = branchOf('then')
|
|
310
|
+
const resolvedChildren = node.blocking
|
|
311
|
+
? node.children.filter((child) => child.kind !== 'branch')
|
|
312
|
+
: (thenBranch?.children ?? [])
|
|
313
|
+
const resolvedAs = node.blocking ? node.as : thenBranch?.as
|
|
314
|
+
const pending = node.blocking
|
|
315
|
+
? []
|
|
316
|
+
: node.children.filter((child) => child.kind !== 'branch')
|
|
317
|
+
/* Runtime block id (shared with the client + child components in this pass). */
|
|
318
|
+
const id = nextVar('$aid')
|
|
319
|
+
let code = `const ${id} = nextBlockId();\n`
|
|
320
|
+
code += `${target}.push("<!--abide:await:" + ${id} + "-->");\n`
|
|
321
|
+
code += branchInto(pending, '<template await> pending', target)
|
|
322
|
+
code += `${target}.push("<!--/abide:await:" + ${id} + "-->");\n`
|
|
323
|
+
/* The settled closures append `finally` after the outcome markup, matching the
|
|
324
|
+
client's concatenated node range so hydration aligns. */
|
|
325
|
+
const settled = (binding: string, children: TemplateNode[], context: string) =>
|
|
326
|
+
`(${binding}) => { const $o = []; ${branchInto(children, context, '$o')}${branchInto(finallyChildren, '<template finally>', '$o')}return $o.join(''); }`
|
|
327
|
+
/* Neither catch nor finally → omit `catch` so a rejection surfaces to the
|
|
328
|
+
stream/error path (renderToStream re-throws) instead of rendering an empty
|
|
329
|
+
branch. A finally-only block keeps a catch closure that renders just finally. */
|
|
330
|
+
const catchProp =
|
|
331
|
+
catchBranch === undefined && finallyChildren.length === 0
|
|
332
|
+
? ''
|
|
333
|
+
: `catch: ${settled(catchBranch?.as ?? '_error', catchBranch?.children ?? [], '<template catch>')} `
|
|
334
|
+
code +=
|
|
335
|
+
`$awaits.push({ id: ${id}, ` +
|
|
336
|
+
(node.blocking ? 'blocking: true, ' : '') +
|
|
337
|
+
`promise: () => (${lowerExpression(node.promise)}), ` +
|
|
338
|
+
`then: ${settled(resolvedAs ?? '_value', resolvedChildren, node.blocking ? '<template await then>' : '<template then>')}, ` +
|
|
339
|
+
`${catchProp}});\n`
|
|
340
|
+
return code
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/* A sync error boundary: push the guarded markup (++ finally) inside a real
|
|
344
|
+
try/catch; on a throw, truncate the output back to the boundary start and push
|
|
345
|
+
the catch markup (++ finally) instead — so even mid-stream a render throw
|
|
346
|
+
becomes catch markup, not a broken response. No catch re-throws (propagates to
|
|
347
|
+
an enclosing boundary / the 500 / the stream). Boundary comments let hydration
|
|
348
|
+
discard the server content if the client adoption fails. */
|
|
349
|
+
function generateTry(node: Extract<TemplateNode, { kind: 'try' }>, target: string): string {
|
|
350
|
+
const branchOf = (which: 'catch' | 'finally') =>
|
|
351
|
+
node.children.find(
|
|
352
|
+
(child): child is Extract<TemplateNode, { kind: 'branch' }> =>
|
|
353
|
+
child.kind === 'branch' && child.branch === which,
|
|
354
|
+
)
|
|
355
|
+
const catchBranch = branchOf('catch')
|
|
356
|
+
const finallyChildren = branchOf('finally')?.children ?? []
|
|
357
|
+
const guarded = node.children.filter((child) => child.kind !== 'branch')
|
|
358
|
+
const errName = catchBranch?.as ?? '_error'
|
|
359
|
+
const id = nextVar('$tid')
|
|
360
|
+
const mark = nextVar('$trim')
|
|
361
|
+
let code = `const ${id} = nextBlockId();\n`
|
|
362
|
+
code += `${target}.push("<!--abide:try:" + ${id} + "-->");\n`
|
|
363
|
+
code += `const ${mark} = ${target}.length;\n`
|
|
364
|
+
code += `try {\n`
|
|
365
|
+
code += branchInto(guarded, '<template try>', target)
|
|
366
|
+
code += branchInto(finallyChildren, '<template finally>', target)
|
|
367
|
+
code += `} catch (${errName}) {\n${target}.length = ${mark};\n`
|
|
368
|
+
if (catchBranch !== undefined) {
|
|
369
|
+
code += branchInto(catchBranch.children, '<template catch>', target)
|
|
370
|
+
code += branchInto(finallyChildren, '<template finally>', target)
|
|
371
|
+
} else {
|
|
372
|
+
code += `throw ${errName};\n`
|
|
373
|
+
}
|
|
374
|
+
code += `}\n`
|
|
375
|
+
code += `${target}.push("<!--/abide:try:" + ${id} + "-->");\n`
|
|
376
|
+
return code
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
return generateInto(nodes, '$out')
|
|
380
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { staticAttrValue } from './staticAttrValue.ts'
|
|
2
|
+
import type { TemplateNode } from './types/TemplateNode.ts'
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
The pieces a `bind:group` needs from its own element: `valueCode` is the JS source
|
|
6
|
+
of the control's `value` (a string literal for static `value="x"`, the expression
|
|
7
|
+
for `value={expr}`); `isRadio` selects single-value (radio) vs array-membership
|
|
8
|
+
(checkbox) semantics. Throws on the two cases the binding can't mean anything for —
|
|
9
|
+
a missing `value`, or a `type` not statically `radio`/`checkbox` (the semantics are
|
|
10
|
+
chosen at compile time, so the type can't be dynamic).
|
|
11
|
+
*/
|
|
12
|
+
export function groupBindParts(node: Extract<TemplateNode, { kind: 'element' }>): {
|
|
13
|
+
valueCode: string
|
|
14
|
+
isRadio: boolean
|
|
15
|
+
} {
|
|
16
|
+
const value = node.attrs.find(
|
|
17
|
+
(attr) => (attr.kind === 'static' || attr.kind === 'expression') && attr.name === 'value',
|
|
18
|
+
)
|
|
19
|
+
if (value === undefined || (value.kind !== 'static' && value.kind !== 'expression')) {
|
|
20
|
+
throw new Error('bind:group requires a `value` attribute on the same element')
|
|
21
|
+
}
|
|
22
|
+
const valueCode = value.kind === 'static' ? JSON.stringify(value.value) : value.code
|
|
23
|
+
const type = staticAttrValue(node, 'type')
|
|
24
|
+
if (type !== 'radio' && type !== 'checkbox') {
|
|
25
|
+
throw new Error('bind:group requires a static type="radio" or type="checkbox"')
|
|
26
|
+
}
|
|
27
|
+
return { valueCode, isRadio: type === 'radio' }
|
|
28
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import ts from 'typescript'
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
The perf pass that follows `lowerDocAccess`. Within a render scope, a static path
|
|
5
|
+
is read and written many times; resolving it to a node + parent + key on every
|
|
6
|
+
access (what `read`/`replace` do) is the path-string floor the bench measured.
|
|
7
|
+
This hoists each distinct static path to a `cell` bound once at the top of the
|
|
8
|
+
scope and rewrites accesses to the string-free `get`/`set` — the form that runs
|
|
9
|
+
~20x faster than re-resolving:
|
|
10
|
+
|
|
11
|
+
model.read("count") → _cell0.get()
|
|
12
|
+
model.replace("count", v) → _cell0.set(v)
|
|
13
|
+
// with, prepended once: const _cell0 = model.cell("count")
|
|
14
|
+
|
|
15
|
+
The input is a render-scope body where `docName` is already in scope (the cell
|
|
16
|
+
decls are prepended to it, so the doc must exist first). Dynamic-path accesses
|
|
17
|
+
(`read(`a/${i}`)`) and structural ops (`add`/`remove`) are left untouched — a
|
|
18
|
+
cell binds one fixed scalar leaf.
|
|
19
|
+
*/
|
|
20
|
+
export function hoistCells(code: string, docName: string): string {
|
|
21
|
+
const source = ts.createSourceFile('component.ts', code, ts.ScriptTarget.Latest, true)
|
|
22
|
+
const cellIdForPath = new Map<string, string>()
|
|
23
|
+
|
|
24
|
+
/* Pass 1: assign a cell id to each distinct static read/replace path. */
|
|
25
|
+
const collect = (node: ts.Node): void => {
|
|
26
|
+
const path = staticDocPath(node, docName, 'read') ?? staticDocPath(node, docName, 'replace')
|
|
27
|
+
if (path !== undefined && !cellIdForPath.has(path)) {
|
|
28
|
+
cellIdForPath.set(path, `_cell${cellIdForPath.size}`)
|
|
29
|
+
}
|
|
30
|
+
ts.forEachChild(node, collect)
|
|
31
|
+
}
|
|
32
|
+
collect(source)
|
|
33
|
+
if (cellIdForPath.size === 0) {
|
|
34
|
+
return code
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const result = ts.transform(source, [hoistTransformer(docName, cellIdForPath)])
|
|
38
|
+
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed })
|
|
39
|
+
const output = printer.printFile(result.transformed[0] as ts.SourceFile)
|
|
40
|
+
result.dispose()
|
|
41
|
+
return output
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* Returns the literal path of a `docName.method("literal", …)` call, else undefined. */
|
|
45
|
+
function staticDocPath(node: ts.Node, docName: string, method: string): string | undefined {
|
|
46
|
+
if (
|
|
47
|
+
ts.isCallExpression(node) &&
|
|
48
|
+
ts.isPropertyAccessExpression(node.expression) &&
|
|
49
|
+
ts.isIdentifier(node.expression.expression) &&
|
|
50
|
+
node.expression.expression.text === docName &&
|
|
51
|
+
node.expression.name.text === method
|
|
52
|
+
) {
|
|
53
|
+
const first = node.arguments[0]
|
|
54
|
+
if (first !== undefined && ts.isStringLiteral(first)) {
|
|
55
|
+
return first.text
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return undefined
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function hoistTransformer(
|
|
62
|
+
docName: string,
|
|
63
|
+
cellIdForPath: Map<string, string>,
|
|
64
|
+
): ts.TransformerFactory<ts.SourceFile> {
|
|
65
|
+
return (context) => (root) => {
|
|
66
|
+
function visit(node: ts.Node): ts.Node {
|
|
67
|
+
const readPath = staticDocPath(node, docName, 'read')
|
|
68
|
+
if (readPath !== undefined) {
|
|
69
|
+
return cellCall(cellIdForPath.get(readPath) as string, 'get', [])
|
|
70
|
+
}
|
|
71
|
+
const replacePath = staticDocPath(node, docName, 'replace')
|
|
72
|
+
if (replacePath !== undefined) {
|
|
73
|
+
const value = (node as ts.CallExpression).arguments[1]
|
|
74
|
+
return cellCall(cellIdForPath.get(replacePath) as string, 'set', [
|
|
75
|
+
ts.visitNode(value, visit) as ts.Expression,
|
|
76
|
+
])
|
|
77
|
+
}
|
|
78
|
+
return ts.visitEachChild(node, visit, context)
|
|
79
|
+
}
|
|
80
|
+
const visited = ts.visitNode(root, visit) as ts.SourceFile
|
|
81
|
+
const declarations = [...cellIdForPath].map(([path, id]) =>
|
|
82
|
+
cellDeclaration(docName, id, path),
|
|
83
|
+
)
|
|
84
|
+
return ts.factory.updateSourceFile(visited, [...declarations, ...visited.statements])
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/* Builds `cellId.method(...args)`. */
|
|
89
|
+
function cellCall(cellId: string, method: string, args: ts.Expression[]): ts.CallExpression {
|
|
90
|
+
return ts.factory.createCallExpression(
|
|
91
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(cellId), method),
|
|
92
|
+
undefined,
|
|
93
|
+
args,
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* Builds `const cellId = docName.cell("path")`. */
|
|
98
|
+
function cellDeclaration(docName: string, cellId: string, path: string): ts.VariableStatement {
|
|
99
|
+
return ts.factory.createVariableStatement(
|
|
100
|
+
undefined,
|
|
101
|
+
ts.factory.createVariableDeclarationList(
|
|
102
|
+
[
|
|
103
|
+
ts.factory.createVariableDeclaration(
|
|
104
|
+
cellId,
|
|
105
|
+
undefined,
|
|
106
|
+
undefined,
|
|
107
|
+
ts.factory.createCallExpression(
|
|
108
|
+
ts.factory.createPropertyAccessExpression(
|
|
109
|
+
ts.factory.createIdentifier(docName),
|
|
110
|
+
'cell',
|
|
111
|
+
),
|
|
112
|
+
undefined,
|
|
113
|
+
[ts.factory.createStringLiteral(path)],
|
|
114
|
+
),
|
|
115
|
+
),
|
|
116
|
+
],
|
|
117
|
+
ts.NodeFlags.Const,
|
|
118
|
+
),
|
|
119
|
+
)
|
|
120
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import ts from 'typescript'
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
Loads the project's tsconfig (for lib/paths/baseUrl/strictness — the shadows must
|
|
5
|
+
type-check against the same world the app does), then forces the overrides the
|
|
6
|
+
shadow needs: `noUnusedLocals`/`noUnusedParameters` off because the shadow
|
|
7
|
+
legitimately declares scope bindings a template may not read, and `noEmit`/
|
|
8
|
+
`skipLibCheck` because it only ever type-checks. Falls back to permissive defaults
|
|
9
|
+
when no tsconfig is found. Shared by the check Program and the LSP LanguageService.
|
|
10
|
+
*/
|
|
11
|
+
export function loadShadowTsConfig(cwd: string): ts.ParsedCommandLine {
|
|
12
|
+
const configPath = ts.findConfigFile(cwd, ts.sys.fileExists, 'tsconfig.json')
|
|
13
|
+
const base = configPath
|
|
14
|
+
? ts.parseJsonConfigFileContent(
|
|
15
|
+
ts.readConfigFile(configPath, ts.sys.readFile).config,
|
|
16
|
+
ts.sys,
|
|
17
|
+
cwd,
|
|
18
|
+
)
|
|
19
|
+
: { options: {}, fileNames: [], errors: [] }
|
|
20
|
+
return {
|
|
21
|
+
...base,
|
|
22
|
+
options: {
|
|
23
|
+
...base.options,
|
|
24
|
+
noEmit: true,
|
|
25
|
+
skipLibCheck: true,
|
|
26
|
+
noUnusedLocals: false,
|
|
27
|
+
noUnusedParameters: false,
|
|
28
|
+
allowUnreachableCode: true,
|
|
29
|
+
},
|
|
30
|
+
}
|
|
31
|
+
}
|