@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,37 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Inspects the raw request URL (not the parsed pathname) for path-traversal
|
|
3
|
+
patterns. The WHATWG URL parser decodes `%2E%2E` to `..` and then collapses
|
|
4
|
+
dot-segments out of the pathname during normalization, so by the time
|
|
5
|
+
`url.pathname` is observable any encoded traversal has been masked. The
|
|
6
|
+
remaining literal `..` check guards against any future URL-parser quirk
|
|
7
|
+
that lets a normalised path through.
|
|
8
|
+
|
|
9
|
+
Hot path early-out: if none of the suspect substrings appear in the raw
|
|
10
|
+
URL we never lowercase the whole string nor walk segments.
|
|
11
|
+
*/
|
|
12
|
+
export function containsTraversal(rawUrl: string): boolean {
|
|
13
|
+
if (rawUrl.includes('\\')) {
|
|
14
|
+
return true
|
|
15
|
+
}
|
|
16
|
+
if (rawUrl.includes('..') && segmentContainsDotDot(rawUrl)) {
|
|
17
|
+
return true
|
|
18
|
+
}
|
|
19
|
+
if (rawUrl.indexOf('%') === -1) {
|
|
20
|
+
return false
|
|
21
|
+
}
|
|
22
|
+
const lower = rawUrl.toLowerCase()
|
|
23
|
+
return lower.includes('%2e%2e') || lower.includes('%2f') || lower.includes('%5c')
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function segmentContainsDotDot(rawUrl: string): boolean {
|
|
27
|
+
const queryStart = rawUrl.indexOf('?')
|
|
28
|
+
const pathEnd = queryStart === -1 ? rawUrl.length : queryStart
|
|
29
|
+
const pathStart = rawUrl.indexOf('/', rawUrl.indexOf('://') + 3)
|
|
30
|
+
if (pathStart === -1 || pathStart >= pathEnd) {
|
|
31
|
+
return false
|
|
32
|
+
}
|
|
33
|
+
return rawUrl
|
|
34
|
+
.slice(pathStart, pathEnd)
|
|
35
|
+
.split('/')
|
|
36
|
+
.some((segment) => segment === '..')
|
|
37
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { NO_STORE } from '../../shared/CACHE_CONTROL_VALUES.ts'
|
|
2
|
+
import { TEXT_PLAIN } from '../../shared/TEXT_PLAIN.ts'
|
|
3
|
+
import { acceptsGzip } from './acceptsGzip.ts'
|
|
4
|
+
import { cacheControlForAsset } from './cacheControlForAsset.ts'
|
|
5
|
+
import { containsTraversal } from './containsTraversal.ts'
|
|
6
|
+
import { createAssetHeaderCache } from './createAssetHeaderCache.ts'
|
|
7
|
+
import { globToPathSet } from './globToPathSet.ts'
|
|
8
|
+
import { respondWithEmbeddedAsset } from './respondWithEmbeddedAsset.ts'
|
|
9
|
+
import type { Assets } from './types/Assets.ts'
|
|
10
|
+
|
|
11
|
+
/*
|
|
12
|
+
Serves the build's `_app` assets (hashed chunks, css, sourcemaps). Two
|
|
13
|
+
sources, picked at construction — the sibling of createPublicAssetServer for
|
|
14
|
+
the framework-owned tree:
|
|
15
|
+
|
|
16
|
+
- `assets` (standalone compile): a map of request path → gzip bytes
|
|
17
|
+
embedded into the binary.
|
|
18
|
+
- `distDir` on disk (dev + `abide start`): files served straight from
|
|
19
|
+
`dist`, with the precompressed `.gz` sibling set snapshotted once at
|
|
20
|
+
boot so a gzip-capable client gets those bytes without on-the-fly
|
|
21
|
+
compression.
|
|
22
|
+
|
|
23
|
+
Unlike the public server this answers every `/_app/` request itself (404 on
|
|
24
|
+
a miss — nothing falls through past the build tree). The path-traversal
|
|
25
|
+
guard inspects the raw request URL because the WHATWG parser normalizes
|
|
26
|
+
encoded `..` segments away before `url.pathname` is visible.
|
|
27
|
+
*/
|
|
28
|
+
export async function createAppAssetServer({
|
|
29
|
+
distDir,
|
|
30
|
+
assets,
|
|
31
|
+
}: {
|
|
32
|
+
distDir: string
|
|
33
|
+
assets?: Assets
|
|
34
|
+
}): Promise<(req: Request, url: URL) => Promise<Response>> {
|
|
35
|
+
// Per-pathname asset header bundles, hashed-chunk-aware Cache-Control.
|
|
36
|
+
const headersForAsset = createAssetHeaderCache(cacheControlForAsset)
|
|
37
|
+
const diskGzipPaths = assets
|
|
38
|
+
? new Set<string>()
|
|
39
|
+
: await globToPathSet(
|
|
40
|
+
`${distDir}/_app`,
|
|
41
|
+
'**/*.gz',
|
|
42
|
+
(file) => `/_app/${file.replace(/\.gz$/, '')}`,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
return async function serveAppAsset(req, url) {
|
|
46
|
+
if (containsTraversal(req.url)) {
|
|
47
|
+
return new Response('Not Found', {
|
|
48
|
+
status: 404,
|
|
49
|
+
headers: { 'Content-Type': TEXT_PLAIN, 'Cache-Control': NO_STORE },
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
if (assets) {
|
|
53
|
+
const compressed = assets[url.pathname]
|
|
54
|
+
/* Miss-check before header work: the header cache keys on
|
|
55
|
+
(request-controlled) pathnames, so building bundles for junk
|
|
56
|
+
`/_app/*` probes would grow it without bound. */
|
|
57
|
+
if (!compressed) {
|
|
58
|
+
return new Response('Not Found', {
|
|
59
|
+
status: 404,
|
|
60
|
+
headers: { 'Content-Type': TEXT_PLAIN, 'Cache-Control': NO_STORE },
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
return respondWithEmbeddedAsset(
|
|
64
|
+
compressed,
|
|
65
|
+
acceptsGzip(req),
|
|
66
|
+
headersForAsset(url.pathname),
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
const { base: baseHeaders, gzip: gzipHeaders } = headersForAsset(url.pathname)
|
|
70
|
+
const diskPath = distDir + url.pathname
|
|
71
|
+
if (acceptsGzip(req) && diskGzipPaths.has(url.pathname)) {
|
|
72
|
+
return new Response(Bun.file(`${diskPath}.gz`), { headers: gzipHeaders })
|
|
73
|
+
}
|
|
74
|
+
return new Response(Bun.file(diskPath), { headers: baseHeaders })
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { mimeForExtension } from './mimeForExtension.ts'
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
A static-asset response's headers depend only on its pathname (extension →
|
|
5
|
+
Content-Type, path → Cache-Control), so each distinct pathname's header bundle
|
|
6
|
+
is built once and reused across every hit on that chunk — avoiding a per-request
|
|
7
|
+
allocation on a cold page load that pulls dozens of files. Each bundle carries
|
|
8
|
+
the plain `base` headers plus a `gzip` variant with `Content-Encoding: gzip`.
|
|
9
|
+
`cacheControlFor` lets callers vary the policy: hashed-aware for `/_app/`,
|
|
10
|
+
fixed for public/.
|
|
11
|
+
*/
|
|
12
|
+
type AssetHeaderBundle = {
|
|
13
|
+
base: HeadersInit
|
|
14
|
+
gzip: HeadersInit
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function createAssetHeaderCache(
|
|
18
|
+
cacheControlFor: (pathname: string) => string,
|
|
19
|
+
): (pathname: string) => AssetHeaderBundle {
|
|
20
|
+
const cache = new Map<string, AssetHeaderBundle>()
|
|
21
|
+
return function headersFor(pathname) {
|
|
22
|
+
return cache.getOrInsertComputed(pathname, () => {
|
|
23
|
+
const base: HeadersInit = {
|
|
24
|
+
'Content-Type': mimeForExtension(pathname),
|
|
25
|
+
Vary: 'Accept-Encoding',
|
|
26
|
+
'Cache-Control': cacheControlFor(pathname),
|
|
27
|
+
}
|
|
28
|
+
return { base, gzip: { ...base, 'Content-Encoding': 'gzip' } }
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { PUBLIC_ASSET_CACHE_CONTROL } from '../../shared/CACHE_CONTROL_VALUES.ts'
|
|
2
|
+
import { acceptsGzip } from './acceptsGzip.ts'
|
|
3
|
+
import { containsTraversal } from './containsTraversal.ts'
|
|
4
|
+
import { createAssetHeaderCache } from './createAssetHeaderCache.ts'
|
|
5
|
+
import { globToPathSet } from './globToPathSet.ts'
|
|
6
|
+
import { respondWithEmbeddedAsset } from './respondWithEmbeddedAsset.ts'
|
|
7
|
+
import type { Assets } from './types/Assets.ts'
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
Serves files from the project's `public/` folder at the site root. Two
|
|
11
|
+
sources, picked at construction:
|
|
12
|
+
|
|
13
|
+
- `publicAssets` (standalone compile): a map of root path → gzip bytes
|
|
14
|
+
embedded into the binary, mirroring the `_app` asset embed.
|
|
15
|
+
- `publicDir` on disk (dev + `abide start`): files read straight from
|
|
16
|
+
`${cwd}/src/ui/public`, with the set of paths snapshotted once at
|
|
17
|
+
boot (see below).
|
|
18
|
+
|
|
19
|
+
Returns a server fn that resolves to `undefined` when no public file
|
|
20
|
+
matches the request path, so the caller falls through to its own 404 /
|
|
21
|
+
middleware path. The path-traversal guard mirrors serveStaticAsset's
|
|
22
|
+
defence against encoded `..` segments in the raw URL.
|
|
23
|
+
|
|
24
|
+
Async because disk mode globs `publicDir` once at construction to build a
|
|
25
|
+
Set of the available paths: every page nav and RPC falls through here, so
|
|
26
|
+
a Set lookup beats a filesystem stat per miss. A file added to public/
|
|
27
|
+
after boot needs a server restart to be seen — the same restart a code
|
|
28
|
+
change already triggers under `bun --watch`.
|
|
29
|
+
*/
|
|
30
|
+
export async function createPublicAssetServer({
|
|
31
|
+
publicDir,
|
|
32
|
+
publicAssets,
|
|
33
|
+
}: {
|
|
34
|
+
publicDir: string
|
|
35
|
+
publicAssets?: Assets
|
|
36
|
+
}): Promise<(req: Request, url: URL) => Promise<Response | undefined>> {
|
|
37
|
+
const headersFor = createAssetHeaderCache(() => PUBLIC_ASSET_CACHE_CONTROL)
|
|
38
|
+
// `dot: true` keeps dotfiles (e.g. `.well-known/…`) servable, matching a raw disk stat.
|
|
39
|
+
const diskPaths = publicAssets
|
|
40
|
+
? new Set<string>()
|
|
41
|
+
: await globToPathSet(publicDir, '**/*', (file) => `/${file}`, { dot: true })
|
|
42
|
+
|
|
43
|
+
/*
|
|
44
|
+
Existence is checked before any header work: every page nav and RPC
|
|
45
|
+
falls through here on its way to the 404/middleware path, and the
|
|
46
|
+
header cache keys on (request-controlled) pathnames — building bundles
|
|
47
|
+
for misses would grow it without bound.
|
|
48
|
+
*/
|
|
49
|
+
return async function servePublicAsset(req, url) {
|
|
50
|
+
if (containsTraversal(req.url)) {
|
|
51
|
+
return undefined
|
|
52
|
+
}
|
|
53
|
+
if (publicAssets) {
|
|
54
|
+
const compressed = publicAssets[url.pathname]
|
|
55
|
+
if (!compressed) {
|
|
56
|
+
return undefined
|
|
57
|
+
}
|
|
58
|
+
return respondWithEmbeddedAsset(compressed, acceptsGzip(req), headersFor(url.pathname))
|
|
59
|
+
}
|
|
60
|
+
if (!diskPaths.has(url.pathname)) {
|
|
61
|
+
return undefined
|
|
62
|
+
}
|
|
63
|
+
return new Response(Bun.file(publicDir + url.pathname), {
|
|
64
|
+
headers: headersFor(url.pathname).base,
|
|
65
|
+
})
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { createLivenessWatch } from '../../shared/createLivenessWatch.ts'
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
The reachability registry behind `abide/server/reachable`. A probe transport
|
|
5
|
+
and the timings are injected so the public name wires them from env + a real
|
|
6
|
+
HEAD while tests drive scripted outcomes on tiny intervals.
|
|
7
|
+
|
|
8
|
+
Per origin, the first read awaits one real probe (the FAITHFUL first answer —
|
|
9
|
+
its latency, including a full timeout when the host is down, is the price of
|
|
10
|
+
not guessing) and then hands the origin to a createLivenessWatch that re-probes
|
|
11
|
+
every `intervalMs` to keep the value warm. Every later read resolves instantly
|
|
12
|
+
off that warm value, fresh within one interval — the faithful cost is paid once.
|
|
13
|
+
|
|
14
|
+
The inaugural probe runs DIRECTLY, not through the watch: the watch's
|
|
15
|
+
failureLimit (anti-flap) is right for the ongoing poll but would make a down
|
|
16
|
+
host take failureLimit× the timeout to answer on the first call. The watch's
|
|
17
|
+
injected probe doubles as the idle reaper — a host nobody has read in `idleMs`
|
|
18
|
+
stops polling (stop() during the probe changes the watched url, so the watch
|
|
19
|
+
discards the result and never reschedules); the next read restarts it cold.
|
|
20
|
+
*/
|
|
21
|
+
export function createReachable(options: {
|
|
22
|
+
probe: (origin: string) => Promise<boolean>
|
|
23
|
+
intervalMs: number
|
|
24
|
+
idleMs: number
|
|
25
|
+
}): {
|
|
26
|
+
reachable: (host: string | URL) => Promise<boolean>
|
|
27
|
+
/* Stop every origin's poll — graceful shutdown, and test isolation. */
|
|
28
|
+
stop: () => void
|
|
29
|
+
/* `using registry = createReachable(...)` — disposal stops every poll. */
|
|
30
|
+
[Symbol.dispose]: () => void
|
|
31
|
+
} {
|
|
32
|
+
type Entry = {
|
|
33
|
+
alive: boolean
|
|
34
|
+
/* The inaugural probe while it is still in flight; concurrent cold reads await the same one. */
|
|
35
|
+
inflight: Promise<boolean> | undefined
|
|
36
|
+
watch: ReturnType<typeof createLivenessWatch> | undefined
|
|
37
|
+
lastReadAt: number
|
|
38
|
+
}
|
|
39
|
+
const registry = new Map<string, Entry>()
|
|
40
|
+
|
|
41
|
+
/* The ongoing poll's probe: reap an idle origin, else run the real probe. */
|
|
42
|
+
function watchProbe(origin: string): Promise<boolean> {
|
|
43
|
+
const entry = registry.get(origin)
|
|
44
|
+
if (entry && Date.now() - entry.lastReadAt > options.idleMs) {
|
|
45
|
+
entry.watch?.stop()
|
|
46
|
+
registry.delete(origin)
|
|
47
|
+
/* Discarded — stop() moved the watched url, so the watch won't reschedule. */
|
|
48
|
+
return Promise.resolve(false)
|
|
49
|
+
}
|
|
50
|
+
return options.probe(origin)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function startWatch(entry: Entry, origin: string): void {
|
|
54
|
+
entry.watch = createLivenessWatch({
|
|
55
|
+
probe: watchProbe,
|
|
56
|
+
onChange: (alive) => {
|
|
57
|
+
entry.alive = alive
|
|
58
|
+
},
|
|
59
|
+
intervalMs: options.intervalMs,
|
|
60
|
+
})
|
|
61
|
+
entry.watch.watch(origin)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function reachable(host: string | URL): Promise<boolean> {
|
|
65
|
+
/*
|
|
66
|
+
HEAD the origin root: this answers host connectivity, not endpoint
|
|
67
|
+
health. A bare host string defaults to https (the external-dependency
|
|
68
|
+
norm); an explicit http://… is honored.
|
|
69
|
+
*/
|
|
70
|
+
const url =
|
|
71
|
+
typeof host === 'string' && !/^https?:\/\//i.test(host) ? `https://${host}` : host
|
|
72
|
+
const origin = new URL(url).origin
|
|
73
|
+
const existing = registry.get(origin)
|
|
74
|
+
if (existing) {
|
|
75
|
+
existing.lastReadAt = Date.now()
|
|
76
|
+
return existing.inflight ?? existing.alive
|
|
77
|
+
}
|
|
78
|
+
/* Cold: optimistic seed, but the first read awaits a real probe before returning. */
|
|
79
|
+
const entry: Entry = {
|
|
80
|
+
alive: true,
|
|
81
|
+
inflight: undefined,
|
|
82
|
+
watch: undefined,
|
|
83
|
+
lastReadAt: Date.now(),
|
|
84
|
+
}
|
|
85
|
+
registry.set(origin, entry)
|
|
86
|
+
/* A rejecting probe reads as unreachable, not a permanent wedge: without
|
|
87
|
+
the catch a thrown probe leaves inflight set forever (every later read
|
|
88
|
+
returns the rejected promise) and never starts the watch. */
|
|
89
|
+
entry.inflight = options
|
|
90
|
+
.probe(origin)
|
|
91
|
+
.catch(() => false)
|
|
92
|
+
.then((alive) => {
|
|
93
|
+
entry.alive = alive
|
|
94
|
+
entry.inflight = undefined
|
|
95
|
+
startWatch(entry, origin)
|
|
96
|
+
return alive
|
|
97
|
+
})
|
|
98
|
+
return entry.inflight
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function stop(): void {
|
|
102
|
+
for (const entry of registry.values()) {
|
|
103
|
+
entry.watch?.stop()
|
|
104
|
+
}
|
|
105
|
+
registry.clear()
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return { reachable, stop, [Symbol.dispose]: stop }
|
|
109
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { NO_STORE } from '../../shared/CACHE_CONTROL_VALUES.ts'
|
|
2
|
+
import { memoizeByKey } from '../../shared/memoizeByKey.ts'
|
|
3
|
+
import { NAV_HEADER } from '../../shared/NAV_HEADER.ts'
|
|
4
|
+
import { REMOTE_FUNCTION } from '../../shared/REMOTE_FUNCTION.ts'
|
|
5
|
+
import { TEXT_PLAIN } from '../../shared/TEXT_PLAIN.ts'
|
|
6
|
+
import type { HttpVerb } from '../../shared/types/HttpVerb.ts'
|
|
7
|
+
import type { RemoteFunction } from '../../shared/types/RemoteFunction.ts'
|
|
8
|
+
import type { Pages } from '../../ui/types/Pages.ts'
|
|
9
|
+
import type { RemoteRoutes } from '../rpc/types/RemoteRoutes.ts'
|
|
10
|
+
import { crossOriginGate } from './crossOriginGate.ts'
|
|
11
|
+
import type { RequestStore } from './types/RequestStore.ts'
|
|
12
|
+
|
|
13
|
+
type AnyRemoteFunction = RemoteFunction<unknown, unknown>
|
|
14
|
+
|
|
15
|
+
/* Resolves a matched route to a Response, given the request and its scope. */
|
|
16
|
+
type RouteHandler = (
|
|
17
|
+
req: Request,
|
|
18
|
+
pathParams: Record<string, string>,
|
|
19
|
+
store: RequestStore,
|
|
20
|
+
) => Promise<Response>
|
|
21
|
+
|
|
22
|
+
/* Renders the page at `routeUrl` — injected so dispatch is testable without SSR. */
|
|
23
|
+
type RenderPage = (
|
|
24
|
+
routeUrl: string,
|
|
25
|
+
params: Record<string, string>,
|
|
26
|
+
store: RequestStore,
|
|
27
|
+
) => Promise<Response>
|
|
28
|
+
|
|
29
|
+
/* The framework's 405 — `Allow` names the permitted verb(s), body and NO_STORE shared so the rpc and page branches can't drift. */
|
|
30
|
+
function methodNotAllowed(allow: string): Response {
|
|
31
|
+
return new Response('Method Not Allowed', {
|
|
32
|
+
status: 405,
|
|
33
|
+
headers: { Allow: allow, 'Content-Type': TEXT_PLAIN, 'Cache-Control': NO_STORE },
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/*
|
|
38
|
+
Owns route dispatch: deciding, per registered URL, whether a request hits an
|
|
39
|
+
rpc verb, a page render, or nothing — and the method-matching that picks the
|
|
40
|
+
status. Page URLs (under src/ui/pages/) serve GET/HEAD by rendering; rpc
|
|
41
|
+
URLs (under src/server/rpc/, `/rpc/...`) dispatch to the single declared verb,
|
|
42
|
+
405 on method mismatch; an unregistered URL is 404. Page and rpc URLs are
|
|
43
|
+
disjoint by construction, so each route lands in exactly one branch.
|
|
44
|
+
|
|
45
|
+
`renderPage` is injected rather than built here: dispatch decisions (the
|
|
46
|
+
405/404 branches and the rpc method match) are the behaviour worth testing,
|
|
47
|
+
and keeping the page render behind the seam lets a test exercise them with a
|
|
48
|
+
stub instead of booting a server. The rpc-module loader is memoised internally
|
|
49
|
+
so each module loads once.
|
|
50
|
+
*/
|
|
51
|
+
export function createRouteDispatcher({
|
|
52
|
+
pages,
|
|
53
|
+
rpc,
|
|
54
|
+
renderPage,
|
|
55
|
+
}: {
|
|
56
|
+
pages: Pages
|
|
57
|
+
rpc: RemoteRoutes
|
|
58
|
+
renderPage: RenderPage
|
|
59
|
+
}): (routeUrl: string) => RouteHandler {
|
|
60
|
+
const loadRpc = memoizeByKey((url): Promise<AnyRemoteFunction | undefined> | undefined => {
|
|
61
|
+
const loader = rpc[url]
|
|
62
|
+
if (!loader) {
|
|
63
|
+
return undefined
|
|
64
|
+
}
|
|
65
|
+
/*
|
|
66
|
+
Each $rpc module has exactly one named export, validated at build
|
|
67
|
+
time. Pick the first REMOTE_FUNCTION-branded export — exact, so an
|
|
68
|
+
incidental re-export carrying method/url props can't be mistaken
|
|
69
|
+
for the verb.
|
|
70
|
+
*/
|
|
71
|
+
return loader().then((mod) => {
|
|
72
|
+
for (const value of Object.values(mod)) {
|
|
73
|
+
if (typeof value === 'function' && REMOTE_FUNCTION in value) {
|
|
74
|
+
return value as AnyRemoteFunction
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return undefined
|
|
78
|
+
})
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
return function buildRouteHandler(routeUrl: string): RouteHandler {
|
|
82
|
+
const hasPage = pages[routeUrl] !== undefined
|
|
83
|
+
const hasRpc = rpc[routeUrl] !== undefined
|
|
84
|
+
return async function routeHandler(req, pathParams, store) {
|
|
85
|
+
const method = req.method as HttpVerb
|
|
86
|
+
if (hasRpc) {
|
|
87
|
+
const fn = await loadRpc(routeUrl)
|
|
88
|
+
if (fn && fn.method === method) {
|
|
89
|
+
const forbidden = crossOriginGate(req, store.url, {
|
|
90
|
+
allowReadOnly: true,
|
|
91
|
+
optOut: fn.crossOrigin === true,
|
|
92
|
+
hint: 'Declare `crossOrigin: true` on the verb to accept cross-site calls.',
|
|
93
|
+
})
|
|
94
|
+
if (forbidden) {
|
|
95
|
+
return forbidden
|
|
96
|
+
}
|
|
97
|
+
return fn.fetch(req)
|
|
98
|
+
}
|
|
99
|
+
return methodNotAllowed(fn ? fn.method : '')
|
|
100
|
+
}
|
|
101
|
+
if (hasPage) {
|
|
102
|
+
if (method !== 'GET' && method !== 'HEAD') {
|
|
103
|
+
return methodNotAllowed('GET, HEAD')
|
|
104
|
+
}
|
|
105
|
+
/*
|
|
106
|
+
SPA navigation probe: the client router fetches the destination
|
|
107
|
+
with NAV_HEADER purely so app.handle runs (auth/redirect gating)
|
|
108
|
+
before it mounts the page itself. Reaching here means handle()
|
|
109
|
+
already passed — it called next — so a bare 204 says "cleared,
|
|
110
|
+
mount it client-side" without paying for a render. A redirect or
|
|
111
|
+
block from handle() short-circuits before next and never arrives.
|
|
112
|
+
*/
|
|
113
|
+
if (req.headers.has(NAV_HEADER)) {
|
|
114
|
+
return new Response(null, {
|
|
115
|
+
status: 204,
|
|
116
|
+
headers: { 'Cache-Control': NO_STORE },
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
return renderPage(routeUrl, pathParams, store)
|
|
120
|
+
}
|
|
121
|
+
return new Response('Not Found', {
|
|
122
|
+
status: 404,
|
|
123
|
+
headers: { 'Content-Type': TEXT_PLAIN, 'Cache-Control': NO_STORE },
|
|
124
|
+
})
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|