@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,42 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Subscribes to bundle menu clicks. Each custom menu item declared in the bundle
|
|
3
|
+
window config dispatches a `abide:menu` CustomEvent into the page when clicked.
|
|
4
|
+
Two forms, both returning an unsubscribe so they drop straight into an
|
|
5
|
+
`effect`:
|
|
6
|
+
|
|
7
|
+
// catch-all — every emit name flows through one handler
|
|
8
|
+
effect(() =>
|
|
9
|
+
onMenu((name) => {
|
|
10
|
+
if (name === 'reload') location.reload()
|
|
11
|
+
}),
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
// filtered — handler fires only for the named item
|
|
15
|
+
effect(() => onMenu('reload', () => location.reload()))
|
|
16
|
+
|
|
17
|
+
Inert during SSR and in a plain browser tab — `effect` only runs client-side,
|
|
18
|
+
the native menu that fires the event exists only in the bundled desktop app,
|
|
19
|
+
and `window` is guarded so importing the module never assumes a DOM.
|
|
20
|
+
*/
|
|
21
|
+
// @readme bundle
|
|
22
|
+
export function onMenu(handler: (name: string) => void): () => void
|
|
23
|
+
export function onMenu(name: string, handler: () => void): () => void
|
|
24
|
+
export function onMenu(
|
|
25
|
+
nameOrHandler: string | ((name: string) => void),
|
|
26
|
+
maybeHandler?: () => void,
|
|
27
|
+
): () => void {
|
|
28
|
+
if (typeof window === 'undefined') {
|
|
29
|
+
return () => {}
|
|
30
|
+
}
|
|
31
|
+
// String first arg = filter to that emit name; otherwise a catch-all handler.
|
|
32
|
+
const filter = typeof nameOrHandler === 'string' ? nameOrHandler : undefined
|
|
33
|
+
const handler = typeof nameOrHandler === 'string' ? maybeHandler : nameOrHandler
|
|
34
|
+
function listener(event: Event) {
|
|
35
|
+
const name = (event as CustomEvent<{ name: string }>).detail.name
|
|
36
|
+
if (filter === undefined || filter === name) {
|
|
37
|
+
handler?.(name)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
window.addEventListener('abide:menu', listener)
|
|
41
|
+
return () => window.removeEventListener('abide:menu', listener)
|
|
42
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { dlopen, FFIType, type Pointer } from 'bun:ffi'
|
|
2
|
+
import type { BundleMenu } from './BundleMenu.ts'
|
|
3
|
+
import { installDownloads } from './installDownloads.ts'
|
|
4
|
+
import { installMacMenu } from './installMacMenu.ts'
|
|
5
|
+
import { resolveWebviewLib } from './resolveWebviewLib.ts'
|
|
6
|
+
|
|
7
|
+
// WEBVIEW_HINT_NONE — the window is freely resizable (the only hint we need).
|
|
8
|
+
const WEBVIEW_HINT_NONE = 0
|
|
9
|
+
|
|
10
|
+
/*
|
|
11
|
+
Encodes a string as a NUL-terminated UTF-8 buffer for the C ABI. bun:ffi
|
|
12
|
+
passes a TypedArray to a `ptr` argument as a raw pointer, and the webview
|
|
13
|
+
C functions expect NUL-terminated `const char *`.
|
|
14
|
+
*/
|
|
15
|
+
function cString(value: string): Uint8Array {
|
|
16
|
+
return new TextEncoder().encode(`${value}\0`)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/*
|
|
20
|
+
Opens a native OS webview window pointed at `url` and blocks until the
|
|
21
|
+
user closes it. This drives the platform UI run loop (WebKit on macOS,
|
|
22
|
+
WebView2 on Windows, WebKitGTK on Linux) via FFI against the webview C
|
|
23
|
+
library — no Chromium is bundled. Because `webview_run` enters a blocking
|
|
24
|
+
native event loop on the calling thread, the abide server must already be
|
|
25
|
+
running in a separate process; this call owns the main thread until the
|
|
26
|
+
window closes, then destroys the handle and releases the library.
|
|
27
|
+
*/
|
|
28
|
+
export async function openWebview({
|
|
29
|
+
url,
|
|
30
|
+
title,
|
|
31
|
+
width = 1024,
|
|
32
|
+
height = 768,
|
|
33
|
+
menu,
|
|
34
|
+
fileMenu,
|
|
35
|
+
onWindow,
|
|
36
|
+
}: {
|
|
37
|
+
url: string
|
|
38
|
+
title: string
|
|
39
|
+
width?: number
|
|
40
|
+
height?: number
|
|
41
|
+
menu?: BundleMenu[]
|
|
42
|
+
// The File menu, inserted before Edit — the launcher's Start/Disconnect.
|
|
43
|
+
fileMenu?: BundleMenu
|
|
44
|
+
/*
|
|
45
|
+
Hands back the window handle once it exists, before the run loop blocks the
|
|
46
|
+
thread. The launcher forwards it to its control-server worker so the worker
|
|
47
|
+
can navigate the window from off-thread (e.g. bounce back to the connect
|
|
48
|
+
screen when the connected server dies).
|
|
49
|
+
*/
|
|
50
|
+
onWindow?: (handle: Pointer | null) => void
|
|
51
|
+
}): Promise<void> {
|
|
52
|
+
const libPath = await resolveWebviewLib()
|
|
53
|
+
const { symbols, close } = dlopen(libPath, {
|
|
54
|
+
webview_create: { args: [FFIType.i32, FFIType.ptr], returns: FFIType.ptr },
|
|
55
|
+
webview_set_title: { args: [FFIType.ptr, FFIType.ptr], returns: FFIType.void },
|
|
56
|
+
webview_set_size: {
|
|
57
|
+
args: [FFIType.ptr, FFIType.i32, FFIType.i32, FFIType.i32],
|
|
58
|
+
returns: FFIType.void,
|
|
59
|
+
},
|
|
60
|
+
webview_init: { args: [FFIType.ptr, FFIType.ptr], returns: FFIType.i32 },
|
|
61
|
+
webview_navigate: { args: [FFIType.ptr, FFIType.ptr], returns: FFIType.void },
|
|
62
|
+
webview_run: { args: [FFIType.ptr], returns: FFIType.void },
|
|
63
|
+
webview_destroy: { args: [FFIType.ptr], returns: FFIType.void },
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
/*
|
|
67
|
+
First arg is the webview's `debug` flag: 1 enables the native inspector
|
|
68
|
+
(WKWebView's Web Inspector, WebView2 DevTools, WebKitGTK inspector) so a JS
|
|
69
|
+
error on the loaded page — otherwise silent in a bare bundle window — can be
|
|
70
|
+
read via right-click → Inspect. Gated behind ABIDE_INSPECT so release bundles
|
|
71
|
+
ship without it. The second arg is an optional parent handle; null = fresh window.
|
|
72
|
+
*/
|
|
73
|
+
const debug = process.env.ABIDE_INSPECT ? 1 : 0
|
|
74
|
+
const handle = symbols.webview_create(debug, null)
|
|
75
|
+
symbols.webview_set_title(handle, cString(title))
|
|
76
|
+
symbols.webview_set_size(handle, width, height, WEBVIEW_HINT_NONE)
|
|
77
|
+
/*
|
|
78
|
+
Install the macOS menu bar (no-op off macOS) after the application exists
|
|
79
|
+
but before the run loop starts, so Quit and the Edit shortcuts work — the
|
|
80
|
+
upstream webview omits the menu entirely — plus the bundle's custom menus.
|
|
81
|
+
*/
|
|
82
|
+
installMacMenu(libPath, handle, title, menu, fileMenu)
|
|
83
|
+
/*
|
|
84
|
+
Attach the download delegate (no-op off macOS / before 11.3) before the
|
|
85
|
+
first navigation, so `<a download>`, blob/data links, and attachment
|
|
86
|
+
responses save a file instead of being silently dropped by the bare webview.
|
|
87
|
+
*/
|
|
88
|
+
installDownloads(libPath, handle)
|
|
89
|
+
onWindow?.(handle)
|
|
90
|
+
|
|
91
|
+
/*
|
|
92
|
+
Stamp the bundle marker before navigation so it runs ahead of page scripts on
|
|
93
|
+
every document the webview loads — local embedded server or a remote one. This
|
|
94
|
+
is what makes browser-side bundled() report "in the webview" regardless of who
|
|
95
|
+
served the page; a plain browser tab (even hitting the embedded localhost
|
|
96
|
+
server) never runs this, so it stays false there.
|
|
97
|
+
*/
|
|
98
|
+
symbols.webview_init(handle, cString('window.__ABIDE_BUNDLE__=true'))
|
|
99
|
+
symbols.webview_navigate(handle, cString(url))
|
|
100
|
+
// Blocks here, running the native UI loop, until the window is closed.
|
|
101
|
+
symbols.webview_run(handle)
|
|
102
|
+
symbols.webview_destroy(handle)
|
|
103
|
+
close()
|
|
104
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { abideLog } from '../shared/abideLog.ts'
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
The conventional macOS `.iconset` contents — each variant is a square PNG
|
|
5
|
+
at the named pixel size. `iconutil` packs a directory of exactly these
|
|
6
|
+
into a multi-resolution `.icns`. @2x entries are the retina variants.
|
|
7
|
+
*/
|
|
8
|
+
const ICONSET_VARIANTS = [
|
|
9
|
+
{ name: 'icon_16x16.png', size: 16 },
|
|
10
|
+
{ name: 'icon_16x16@2x.png', size: 32 },
|
|
11
|
+
{ name: 'icon_32x32.png', size: 32 },
|
|
12
|
+
{ name: 'icon_32x32@2x.png', size: 64 },
|
|
13
|
+
{ name: 'icon_128x128.png', size: 128 },
|
|
14
|
+
{ name: 'icon_128x128@2x.png', size: 256 },
|
|
15
|
+
{ name: 'icon_256x256.png', size: 256 },
|
|
16
|
+
{ name: 'icon_256x256@2x.png', size: 512 },
|
|
17
|
+
{ name: 'icon_512x512.png', size: 512 },
|
|
18
|
+
{ name: 'icon_512x512@2x.png', size: 1024 },
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
/*
|
|
22
|
+
Converts a PNG into a macOS `.icns` using the system `sips` + `iconutil`
|
|
23
|
+
tools, which ship with macOS. `sips` resizes the source into each iconset
|
|
24
|
+
variant; `iconutil` packs the iconset directory into the `.icns`. Returns
|
|
25
|
+
true on success. On any failure (tools missing, unreadable source) it logs
|
|
26
|
+
a warning and returns false so the bundle still completes without an icon
|
|
27
|
+
rather than aborting the whole build.
|
|
28
|
+
*/
|
|
29
|
+
export async function pngToIcns(pngPath: string, outPath: string): Promise<boolean> {
|
|
30
|
+
const iconset = `${outPath}.iconset`
|
|
31
|
+
try {
|
|
32
|
+
await Bun.$`mkdir -p ${iconset}`.quiet()
|
|
33
|
+
await Promise.all(
|
|
34
|
+
ICONSET_VARIANTS.map(({ name, size }) =>
|
|
35
|
+
Bun.$`sips -z ${size} ${size} ${pngPath} --out ${`${iconset}/${name}`}`.quiet(),
|
|
36
|
+
),
|
|
37
|
+
)
|
|
38
|
+
await Bun.$`iconutil -c icns ${iconset} -o ${outPath}`.quiet()
|
|
39
|
+
return true
|
|
40
|
+
} catch (error) {
|
|
41
|
+
abideLog.warn(`could not convert ${pngPath} to .icns — bundling without an icon`)
|
|
42
|
+
abideLog.error(error)
|
|
43
|
+
return false
|
|
44
|
+
} finally {
|
|
45
|
+
await Bun.$`rm -rf ${iconset}`.quiet()
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { HEALTH_PATH } from '../shared/HEALTH_PATH.ts'
|
|
2
|
+
import { IDENTITY_PATH } from '../shared/IDENTITY_PATH.ts'
|
|
3
|
+
import { isAbideHealthPayload } from '../shared/isAbideHealthPayload.ts'
|
|
4
|
+
|
|
5
|
+
// The identity shape a abide server returns from GET /__abide/health (and its /__abide/identity alias).
|
|
6
|
+
export type AbideIdentity = { name: string; version: string }
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
Confirms a URL points at a abide server before the launcher navigates the app
|
|
10
|
+
window there, by fetching its unauthenticated health endpoint. Returns the
|
|
11
|
+
server's identity on success, or undefined when nothing abide answers — a network
|
|
12
|
+
error, the wrong port, or a non-abide page (a bare 403/404, a different app, a
|
|
13
|
+
captive portal's 200 — hence the `abide: true` body check, never response.ok
|
|
14
|
+
alone). The endpoint bypasses the app's own middleware, so an auth-guarded abide
|
|
15
|
+
app still verifies here even though its pages would later redirect to a login.
|
|
16
|
+
Probes HEALTH_PATH first, falling back to the IDENTITY_PATH alias so a newer
|
|
17
|
+
launcher still recognises an older abide server. The fallback only runs when
|
|
18
|
+
the host actually answered (an older server 404s the health path) — a network
|
|
19
|
+
error or timeout skips it, because a host that didn't answer one path won't
|
|
20
|
+
answer the other and each attempt costs the full timeout (this probe sits in
|
|
21
|
+
the launcher's liveness loop).
|
|
22
|
+
*/
|
|
23
|
+
export async function probeAbideServer(target: string): Promise<AbideIdentity | undefined> {
|
|
24
|
+
const base = target.replace(/\/+$/, '')
|
|
25
|
+
try {
|
|
26
|
+
return (
|
|
27
|
+
(await probeIdentityAt(`${base}${HEALTH_PATH}`)) ??
|
|
28
|
+
(await probeIdentityAt(`${base}${IDENTITY_PATH}`))
|
|
29
|
+
)
|
|
30
|
+
} catch {
|
|
31
|
+
return undefined
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* Throws on network error/timeout; undefined means the host answered but isn't a abide server at this path. */
|
|
36
|
+
async function probeIdentityAt(url: string): Promise<AbideIdentity | undefined> {
|
|
37
|
+
const response = await fetch(url, {
|
|
38
|
+
headers: { accept: 'application/json' },
|
|
39
|
+
signal: AbortSignal.timeout(5000),
|
|
40
|
+
})
|
|
41
|
+
if (!response.ok) {
|
|
42
|
+
return undefined
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
const body = (await response.json()) as {
|
|
46
|
+
abide?: unknown
|
|
47
|
+
name?: string
|
|
48
|
+
version?: string
|
|
49
|
+
}
|
|
50
|
+
if (!isAbideHealthPayload(body)) {
|
|
51
|
+
return undefined
|
|
52
|
+
}
|
|
53
|
+
return { name: body.name ?? 'abide app', version: body.version ?? '0.0.0' }
|
|
54
|
+
} catch {
|
|
55
|
+
return undefined
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { dirname, join } from 'node:path'
|
|
2
|
+
import { serverBinaryFilename } from './serverBinaryFilename.ts'
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
Locates the embedded server binary that ships beside the launcher inside a
|
|
6
|
+
bundle. The launcher's own path is `process.execPath` (the compiled binary
|
|
7
|
+
itself), so the server sits in the same directory — true for both the
|
|
8
|
+
flat-directory layout and a macOS `.app`'s `Contents/MacOS/`.
|
|
9
|
+
*/
|
|
10
|
+
export function resolveServerBinary(): string {
|
|
11
|
+
return join(dirname(process.execPath), serverBinaryFilename())
|
|
12
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { dirname, join } from 'node:path'
|
|
2
|
+
import { bundleLayout } from '../shared/bundleLayout.ts'
|
|
3
|
+
import { webviewCachePath } from './webviewCachePath.ts'
|
|
4
|
+
import { webviewLibName } from './webviewLibName.ts'
|
|
5
|
+
|
|
6
|
+
/*
|
|
7
|
+
Locates the native webview shared library to load over FFI, without ever
|
|
8
|
+
compiling — this runs in the compiled launcher too, where no toolchain is
|
|
9
|
+
present. Resolution order:
|
|
10
|
+
|
|
11
|
+
1. ABIDE_WEBVIEW_LIB — explicit path, the escape hatch for any layout.
|
|
12
|
+
2. inside a bundle — beside the launcher binary (flat layout) or in
|
|
13
|
+
`../Frameworks` (macOS `.app`), so a shipped bundle is self-contained.
|
|
14
|
+
3. abide's own build cache — the library compiled from the vendored
|
|
15
|
+
header by buildWebviewLib (populated at build time via ensureWebviewLib).
|
|
16
|
+
|
|
17
|
+
abide ships the vendored source rather than a prebuilt binary, so the
|
|
18
|
+
toolchain path (`abide bundle`) calls ensureWebviewLib to build-on-miss;
|
|
19
|
+
this resolver only reports what already exists. Throws with
|
|
20
|
+
guidance when nothing resolves rather than letting dlopen fail opaquely.
|
|
21
|
+
*/
|
|
22
|
+
export async function resolveWebviewLib(_cwd: string = process.cwd()): Promise<string> {
|
|
23
|
+
const fromEnv = process.env.ABIDE_WEBVIEW_LIB
|
|
24
|
+
if (fromEnv) {
|
|
25
|
+
return fromEnv
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const libName = webviewLibName()
|
|
29
|
+
|
|
30
|
+
/*
|
|
31
|
+
Bundle-relative candidates. In dev `process.execPath` is the `bun`
|
|
32
|
+
binary, so these miss and we fall through to the build cache; in a
|
|
33
|
+
shipped bundle the launcher's own directory holds the lib (flat layout)
|
|
34
|
+
or its sibling Frameworks dir (macOS `.app`) — bundleLayout knows which.
|
|
35
|
+
*/
|
|
36
|
+
const { binDir, libDir } = bundleLayout(dirname(process.execPath))
|
|
37
|
+
const bundledCandidates = [join(binDir, libName), join(libDir, libName)]
|
|
38
|
+
for (const candidate of bundledCandidates) {
|
|
39
|
+
if (await Bun.file(candidate).exists()) {
|
|
40
|
+
return candidate
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const cached = webviewCachePath()
|
|
45
|
+
if (await Bun.file(cached).exists()) {
|
|
46
|
+
return cached
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
throw new Error(
|
|
50
|
+
'[abide] no native webview library found. Run `abide bundle` to ' +
|
|
51
|
+
'build it from the vendored source, or set ABIDE_WEBVIEW_LIB to a prebuilt one.',
|
|
52
|
+
)
|
|
53
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Filename of the embedded server binary that ships beside the launcher
|
|
3
|
+
inside a bundle. Both the bundler (which writes it) and the launcher
|
|
4
|
+
(which spawns it) derive the name here so they can't drift apart.
|
|
5
|
+
*/
|
|
6
|
+
export function serverBinaryFilename(platform: NodeJS.Platform = process.platform): string {
|
|
7
|
+
return platform === 'win32' ? 'server.exe' : 'server'
|
|
8
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { abideLog } from '../shared/abideLog.ts'
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
Ad-hoc code-signs an assembled macOS `.app` so it launches on other Macs.
|
|
5
|
+
|
|
6
|
+
Apple Silicon mandates a valid code signature for every executable. `bun
|
|
7
|
+
build --compile` emits an ad-hoc, linker-signed binary, but assembling the
|
|
8
|
+
`.app` around it (writing Info.plist, dropping in the lib) leaves the bundle
|
|
9
|
+
unsealed — `codesign --verify` then reports the signature as modified, and a
|
|
10
|
+
copy that picks up a quarantine flag (AirDrop, USB, download) gets silently
|
|
11
|
+
killed by Gatekeeper/AMFI: the icon bounces once and nothing opens.
|
|
12
|
+
|
|
13
|
+
Re-signing inside-out fixes that. Nested Mach-O code (the webview dylib, the
|
|
14
|
+
embedded server binary, the launcher) is signed first, then the bundle as a
|
|
15
|
+
whole, which seals Resources and binds Info.plist. The identity is `-`,
|
|
16
|
+
ad-hoc: no certificate, no Developer account, no network — as far as signing
|
|
17
|
+
goes without a paid Developer ID. Recipients copying a quarantined bundle
|
|
18
|
+
still need `xattr -cr <app>` once, but the app no longer fails to launch.
|
|
19
|
+
|
|
20
|
+
Best-effort: if `codesign` is missing or fails, warn and return rather than
|
|
21
|
+
abort the bundle, which is otherwise complete and usable on the build host.
|
|
22
|
+
*/
|
|
23
|
+
export async function signMacApp(bundleRoot: string, innerPaths: string[]): Promise<void> {
|
|
24
|
+
try {
|
|
25
|
+
// Inner Mach-O code inside-out, then the bundle, which re-signs the
|
|
26
|
+
// main executable as part of sealing — order matters for nested seals.
|
|
27
|
+
for (const path of innerPaths) {
|
|
28
|
+
await Bun.$`codesign --force --sign - ${path}`.quiet()
|
|
29
|
+
}
|
|
30
|
+
await Bun.$`codesign --force --sign - ${bundleRoot}`.quiet()
|
|
31
|
+
} catch (error) {
|
|
32
|
+
abideLog.warn(
|
|
33
|
+
`could not code-sign ${bundleRoot} — it may not launch when copied to another Mac`,
|
|
34
|
+
)
|
|
35
|
+
abideLog.error(error)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { DEFAULT_PORT } from '../server/runtime/DEFAULT_PORT.ts'
|
|
2
|
+
import { findOpenPort } from '../server/runtime/findOpenPort.ts'
|
|
3
|
+
import { parsePort } from '../server/runtime/parsePort.ts'
|
|
4
|
+
import { binaryDirEnvPath } from '../shared/binaryDirEnvPath.ts'
|
|
5
|
+
import { dataDirEnvPath } from '../shared/dataDirEnvPath.ts'
|
|
6
|
+
import { readEnvFile } from '../shared/readEnvFile.ts'
|
|
7
|
+
import { resolveServerBinary } from './resolveServerBinary.ts'
|
|
8
|
+
import { waitForServer } from './waitForServer.ts'
|
|
9
|
+
|
|
10
|
+
/*
|
|
11
|
+
The port the embedded server binds. A `PORT` from the shell, the data-dir `.env`
|
|
12
|
+
(where the config form writes), or the shipped binary-dir `.env` is honored — so
|
|
13
|
+
the server answers at a fixed, known address another machine can reliably connect
|
|
14
|
+
to. With none set, the first open port at/above 3000 is chosen (matching the
|
|
15
|
+
standalone server's default). Precedence matches the server's own env stack:
|
|
16
|
+
shell > data-dir > binary-dir. A configured port is used as-is — if it's taken,
|
|
17
|
+
the bind failure surfaces rather than silently moving.
|
|
18
|
+
*/
|
|
19
|
+
async function resolveEmbeddedPort(programName: string): Promise<number> {
|
|
20
|
+
const [dataDirEnv, binaryDirEnv] = await Promise.all([
|
|
21
|
+
readEnvFile(dataDirEnvPath(programName)),
|
|
22
|
+
readEnvFile(binaryDirEnvPath()),
|
|
23
|
+
])
|
|
24
|
+
return (
|
|
25
|
+
parsePort(process.env.PORT ?? dataDirEnv.PORT ?? binaryDirEnv.PORT) ??
|
|
26
|
+
findOpenPort(DEFAULT_PORT)
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/*
|
|
31
|
+
Spawns the sibling server binary on a free port and waits for it to answer,
|
|
32
|
+
returning the live URL plus the child so the caller owns its lifetime (reaping on
|
|
33
|
+
disconnect/exit). Readiness is raced against the child's exit so a server that
|
|
34
|
+
crashes on boot (missing config) surfaces immediately instead of stalling out
|
|
35
|
+
waitForServer's full timeout; the loser branch resolves (never rejects) so it
|
|
36
|
+
can't surface as an unhandled rejection once the child is later reaped. Does not
|
|
37
|
+
reap a previous child — the caller owns that.
|
|
38
|
+
*/
|
|
39
|
+
export async function spawnEmbeddedServer({
|
|
40
|
+
programName,
|
|
41
|
+
timeoutMs,
|
|
42
|
+
}: {
|
|
43
|
+
programName: string
|
|
44
|
+
timeoutMs?: number
|
|
45
|
+
}): Promise<{ url: string; child: ReturnType<typeof Bun.spawn> }> {
|
|
46
|
+
const port = await resolveEmbeddedPort(programName)
|
|
47
|
+
const url = `http://localhost:${port}`
|
|
48
|
+
const child = Bun.spawn({
|
|
49
|
+
cmd: [resolveServerBinary()],
|
|
50
|
+
// ABIDE_PARENT_PID lets the child exit if the parent is force-quit (a clean
|
|
51
|
+
// shutdown reaps it directly). The server resolves its own config from its
|
|
52
|
+
// data-dir/binary-dir .env at boot, so nothing else is injected.
|
|
53
|
+
env: { ...process.env, PORT: String(port), ABIDE_PARENT_PID: String(process.pid) },
|
|
54
|
+
stdio: ['inherit', 'inherit', 'inherit'],
|
|
55
|
+
})
|
|
56
|
+
const outcome = await Promise.race([
|
|
57
|
+
waitForServer(url, timeoutMs ? { timeoutMs } : undefined).then(() => undefined),
|
|
58
|
+
child.exited,
|
|
59
|
+
])
|
|
60
|
+
if (outcome !== undefined) {
|
|
61
|
+
throw new Error(`[abide] embedded server exited (code ${outcome}) before binding`)
|
|
62
|
+
}
|
|
63
|
+
return { url, child }
|
|
64
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Derives a deterministic localhost port from the program name so the connect
|
|
3
|
+
screen's origin (and thus its localStorage) stays stable across launches — a
|
|
4
|
+
remembered server URL survives a relaunch only if the page is reloaded from the
|
|
5
|
+
same origin. Hashes the name with FNV-1a (32-bit) and maps it into the
|
|
6
|
+
dynamic/private range (49152–65535). The caller probes availability and falls
|
|
7
|
+
back to a random free port on collision, so determinism is a best effort, not a
|
|
8
|
+
guarantee.
|
|
9
|
+
*/
|
|
10
|
+
export function stableLocalPort(programName: string): number {
|
|
11
|
+
// FNV-1a 32-bit: offset basis 2166136261, prime 16777619. Math.imul keeps
|
|
12
|
+
// the multiply in 32-bit space; `>>> 0` reads the result back as unsigned.
|
|
13
|
+
let hash = 0x811c9dc5
|
|
14
|
+
for (const character of programName) {
|
|
15
|
+
hash ^= character.charCodeAt(0)
|
|
16
|
+
hash = Math.imul(hash, 0x01000193)
|
|
17
|
+
}
|
|
18
|
+
return 49152 + ((hash >>> 0) % 16384)
|
|
19
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Polls an HTTP URL until it answers (any status) or the deadline passes.
|
|
3
|
+
The spawned server child binds asynchronously, so the launcher can't open
|
|
4
|
+
the webview until a request round-trips. A connection refusal throws and
|
|
5
|
+
is swallowed; once Bun.serve is listening the fetch resolves and we
|
|
6
|
+
return. Throws on timeout so the launcher can report a failed boot rather
|
|
7
|
+
than open a blank window.
|
|
8
|
+
*/
|
|
9
|
+
export async function waitForServer(
|
|
10
|
+
url: string,
|
|
11
|
+
{ timeoutMs = 10_000, intervalMs = 50 }: { timeoutMs?: number; intervalMs?: number } = {},
|
|
12
|
+
): Promise<void> {
|
|
13
|
+
const deadline = Bun.nanoseconds() + timeoutMs * 1e6
|
|
14
|
+
while (Bun.nanoseconds() < deadline) {
|
|
15
|
+
try {
|
|
16
|
+
await fetch(url)
|
|
17
|
+
return
|
|
18
|
+
} catch {
|
|
19
|
+
await Bun.sleep(intervalMs)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
throw new Error(`[abide] server did not become ready at ${url} within ${timeoutMs}ms`)
|
|
23
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { join } from 'node:path'
|
|
2
|
+
import { WEBVIEW_BUILD_REVISION } from './WEBVIEW_BUILD_REVISION.ts'
|
|
3
|
+
import { WEBVIEW_VERSION } from './WEBVIEW_VERSION.ts'
|
|
4
|
+
import { webviewLibName } from './webviewLibName.ts'
|
|
5
|
+
|
|
6
|
+
/*
|
|
7
|
+
Absolute path where the locally built webview library is cached. abide
|
|
8
|
+
compiles the vendored `native/webview.h` once per host and reuses the
|
|
9
|
+
result; both buildWebviewLib (the writer) and resolveWebviewLib (a reader)
|
|
10
|
+
derive the location here so they never drift.
|
|
11
|
+
|
|
12
|
+
The cache sits next to the vendored source inside the abide package, so it
|
|
13
|
+
is shared across every project on the machine that uses this abide install
|
|
14
|
+
and survives independently of any consumer's `cwd`. Namespacing by
|
|
15
|
+
platform + arch + upstream version keeps a single cache correct across
|
|
16
|
+
architectures and makes a header bump — or a abide native-build bump — select
|
|
17
|
+
a fresh path automatically.
|
|
18
|
+
*/
|
|
19
|
+
export function webviewCachePath(): string {
|
|
20
|
+
const nativeDir = new URL('./native', import.meta.url).pathname
|
|
21
|
+
const key = `${process.platform}-${process.arch}-${WEBVIEW_VERSION}-${WEBVIEW_BUILD_REVISION}`
|
|
22
|
+
return join(nativeDir, '.cache', key, webviewLibName())
|
|
23
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { suffix } from 'bun:ffi'
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
Native webview shared-library filename for a platform. `suffix` is Bun's
|
|
5
|
+
host shared-library extension (`dylib`/`so`/`dll`). The bundler copies a
|
|
6
|
+
file under this name and the loader looks for it under the same name, so
|
|
7
|
+
both derive it here.
|
|
8
|
+
*/
|
|
9
|
+
export function webviewLibName(platform: NodeJS.Platform = process.platform): string {
|
|
10
|
+
return platform === 'win32' ? `webview.${suffix}` : `libwebview.${suffix}`
|
|
11
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { probeAbideServer } from '../bundle/probeAbideServer.ts'
|
|
2
|
+
import { abideLog } from '../shared/abideLog.ts'
|
|
3
|
+
import { writeLastConnection } from '../shared/writeLastConnection.ts'
|
|
4
|
+
import type { CliTarget } from './types/CliTarget.ts'
|
|
5
|
+
|
|
6
|
+
/*
|
|
7
|
+
Connects to a remote abide server: probes its identity endpoint first so we never
|
|
8
|
+
record or talk to a non-abide URL, then persists the intent so the next bare run
|
|
9
|
+
resumes here. Carries the env bearer token (baked or shell) for authed servers.
|
|
10
|
+
Returns the target, or undefined when nothing abide answers.
|
|
11
|
+
*/
|
|
12
|
+
export async function connectToServer(
|
|
13
|
+
programName: string,
|
|
14
|
+
url: string,
|
|
15
|
+
): Promise<CliTarget | undefined> {
|
|
16
|
+
const identity = await probeAbideServer(url)
|
|
17
|
+
if (!identity) {
|
|
18
|
+
abideLog.warn(`no abide server responded at ${url}`)
|
|
19
|
+
return undefined
|
|
20
|
+
}
|
|
21
|
+
await writeLastConnection(programName, { kind: 'url', url })
|
|
22
|
+
return { url, token: process.env.ABIDE_APP_TOKEN, name: identity.name }
|
|
23
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { dispatchVerbInProcess } from '../server/rpc/dispatchVerbInProcess.ts'
|
|
2
|
+
import { findVerbByCommandName } from '../server/rpc/findVerbByCommandName.ts'
|
|
3
|
+
import { buildRpcProxy } from '../shared/buildRpcProxy.ts'
|
|
4
|
+
import { buildRpcRequest } from '../shared/buildRpcRequest.ts'
|
|
5
|
+
import type { HttpVerb } from '../shared/types/HttpVerb.ts'
|
|
6
|
+
import type { RpcInvoker } from '../shared/types/RpcInvoker.ts'
|
|
7
|
+
import type { CliManifest } from './types/CliManifest.ts'
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
Each property of the client is a callable: invoking it decodes the body
|
|
11
|
+
(plain call), while `.raw(args)` returns the underlying Response without
|
|
12
|
+
decoding or throwing on non-2xx — the escape hatch the CLI uses to sniff
|
|
13
|
+
the Content-Type and stream sse/jsonl bodies frame-by-frame instead of
|
|
14
|
+
buffering through decodeResponse. buildRpcProxy owns that invoker contract.
|
|
15
|
+
*/
|
|
16
|
+
type AnyApi = Record<string, RpcInvoker>
|
|
17
|
+
|
|
18
|
+
/*
|
|
19
|
+
Builds a typed proxy over the project's RPCs for use in scripts, tests,
|
|
20
|
+
server-to-server calls, and the standalone CLI binary. Modes are
|
|
21
|
+
decided at construction:
|
|
22
|
+
|
|
23
|
+
- With `url`: remote-mode. Each property access becomes an HTTP call
|
|
24
|
+
against `<url>/<manifest[name].url>` using the manifest's method.
|
|
25
|
+
Auth header is set from `token` when provided.
|
|
26
|
+
- Without `url`: in-process mode. Each property access looks up the
|
|
27
|
+
verb in the registry (populated by importing the project's rpc
|
|
28
|
+
modules) and calls `verb.fetch(synthesizedRequest)` — same code
|
|
29
|
+
path the HTTP router uses, no network hop.
|
|
30
|
+
|
|
31
|
+
The `manifest` is the bundler-emitted CLI manifest baked into the thin
|
|
32
|
+
binary. In in-process mode it's optional (registry is the source of
|
|
33
|
+
truth); in remote mode it supplies the method + url per command without
|
|
34
|
+
needing the rpc modules loaded. The mode is chosen solely by whether
|
|
35
|
+
`url` is set — the shipped CLI binary (see runCli) always passes `url`,
|
|
36
|
+
so it runs remote-only; in-process mode is for same-project scripts and
|
|
37
|
+
tests that import this directly without a `url`.
|
|
38
|
+
*/
|
|
39
|
+
export function createClient<Api extends AnyApi = AnyApi>(opts?: {
|
|
40
|
+
url?: string
|
|
41
|
+
token?: string
|
|
42
|
+
manifest?: CliManifest
|
|
43
|
+
}): Api {
|
|
44
|
+
const url = opts?.url
|
|
45
|
+
const token = opts?.token
|
|
46
|
+
const manifest = opts?.manifest
|
|
47
|
+
|
|
48
|
+
// Auth + content-negotiation headers both dispatch modes attach.
|
|
49
|
+
function requestHeaders(accept?: string): Headers {
|
|
50
|
+
const headers = new Headers()
|
|
51
|
+
if (token) {
|
|
52
|
+
headers.set('authorization', `Bearer ${token}`)
|
|
53
|
+
}
|
|
54
|
+
if (accept) {
|
|
55
|
+
headers.set('accept', accept)
|
|
56
|
+
}
|
|
57
|
+
return headers
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/*
|
|
61
|
+
Resolves a command name to the closure that issues its wire call, or
|
|
62
|
+
undefined when the name is unknown in the active mode. Remote mode (url set)
|
|
63
|
+
resolves method + url from the baked manifest — registry fallback for
|
|
64
|
+
same-project callers — and sends the synthesized Request over the network.
|
|
65
|
+
In-process mode resolves the verb from the registry and routes through
|
|
66
|
+
dispatchVerbInProcess, the same synthesize-and-fetch the MCP dispatcher
|
|
67
|
+
uses, so the two consumer surfaces can't drift on how a verb is invoked.
|
|
68
|
+
*/
|
|
69
|
+
function resolveSend(name: string): ((args?: unknown) => Promise<Response>) | undefined {
|
|
70
|
+
if (url) {
|
|
71
|
+
const command = manifest?.[name] ?? registryCommand(name)
|
|
72
|
+
if (!command) {
|
|
73
|
+
return undefined
|
|
74
|
+
}
|
|
75
|
+
return (args) =>
|
|
76
|
+
fetch(
|
|
77
|
+
buildRpcRequest({
|
|
78
|
+
method: command.method,
|
|
79
|
+
url: command.url,
|
|
80
|
+
args,
|
|
81
|
+
baseUrl: url,
|
|
82
|
+
headers: requestHeaders(command.accept),
|
|
83
|
+
}),
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
const entry = findVerbByCommandName(name)
|
|
87
|
+
if (!entry) {
|
|
88
|
+
return undefined
|
|
89
|
+
}
|
|
90
|
+
return (args) =>
|
|
91
|
+
dispatchVerbInProcess({
|
|
92
|
+
remote: entry.remote,
|
|
93
|
+
args,
|
|
94
|
+
baseUrl: 'http://localhost/',
|
|
95
|
+
headers: requestHeaders(),
|
|
96
|
+
})
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Remote-mode registry fallback for callers passing a url but no manifest.
|
|
100
|
+
function registryCommand(
|
|
101
|
+
name: string,
|
|
102
|
+
): { method: HttpVerb; url: string; accept?: string } | undefined {
|
|
103
|
+
const found = findVerbByCommandName(name)
|
|
104
|
+
return found ? { method: found.remote.method, url: found.remote.url } : undefined
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return buildRpcProxy<Api>(resolveSend)
|
|
108
|
+
}
|