@belte/belte 0.19.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 +313 -0
- package/LICENSE +21 -0
- package/README.md +559 -0
- package/bin/belte.ts +183 -0
- package/package.json +110 -0
- package/src/App.svelte +31 -0
- package/src/appEntry.ts +151 -0
- package/src/assets/app.html +14 -0
- package/src/belteResolverPlugin.ts +858 -0
- package/src/build.ts +147 -0
- package/src/buildCli.ts +129 -0
- package/src/buildDisconnected.ts +122 -0
- package/src/bundleApp.ts +149 -0
- package/src/bundleDisconnectedEntry.ts +17 -0
- package/src/cliEntry.ts +25 -0
- package/src/clientBuildPlugins.ts +41 -0
- package/src/clientEntry.ts +7 -0
- package/src/compile.ts +64 -0
- package/src/controlServerWorker.ts +422 -0
- package/src/dedupeSveltePlugin.ts +66 -0
- package/src/devEntry.ts +169 -0
- package/src/discoveryEntry.ts +81 -0
- package/src/lib/browser/applyStreamedResolution.ts +33 -0
- package/src/lib/browser/cacheEntryFromSnapshot.ts +48 -0
- package/src/lib/browser/flushUnresolvedPlaceholders.ts +16 -0
- package/src/lib/browser/installStreamingPlaceholders.ts +32 -0
- package/src/lib/browser/openResolveStream.ts +42 -0
- package/src/lib/browser/page.svelte.ts +258 -0
- package/src/lib/browser/pageStreamController.ts +17 -0
- package/src/lib/browser/refetchPlaceholder.ts +12 -0
- package/src/lib/browser/remoteProxy.ts +37 -0
- package/src/lib/browser/socketChannel.ts +192 -0
- package/src/lib/browser/socketProxy.ts +57 -0
- package/src/lib/browser/startClient.ts +153 -0
- package/src/lib/browser/subscribe.ts +131 -0
- package/src/lib/browser/types/Errors.ts +9 -0
- package/src/lib/browser/types/Layouts.ts +7 -0
- package/src/lib/browser/types/Pages.ts +7 -0
- package/src/lib/browser/types/StreamingDeferred.ts +9 -0
- package/src/lib/bundle/BundleMenu.ts +11 -0
- package/src/lib/bundle/BundleMenuItem.ts +24 -0
- package/src/lib/bundle/BundleWindow.ts +36 -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 +31 -0
- package/src/lib/bundle/buildWebviewLib.ts +111 -0
- package/src/lib/bundle/disconnected.css +9 -0
- package/src/lib/bundle/disconnected.svelte +386 -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/belteMenu.mm +422 -0
- package/src/lib/bundle/native/webview.h +4557 -0
- package/src/lib/bundle/onMenu.ts +41 -0
- package/src/lib/bundle/openWebview.ts +104 -0
- package/src/lib/bundle/pngToIcns.ts +47 -0
- package/src/lib/bundle/probeBelteServer.ts +34 -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 +35 -0
- package/src/lib/bundle/spawnEmbeddedServer.ts +65 -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 +170 -0
- package/src/lib/cli/dispatchCommand.ts +71 -0
- package/src/lib/cli/loadEnvFromBinaryDir.ts +16 -0
- package/src/lib/cli/parseArgvForRpc.ts +97 -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 +139 -0
- package/src/lib/cli/runSession.ts +105 -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 +101 -0
- package/src/lib/mcp/createMcpServer.ts +42 -0
- package/src/lib/mcp/dispatchMcpRequest.ts +146 -0
- package/src/lib/mcp/mcpResourceServerSlot.ts +18 -0
- package/src/lib/mcp/mcpSurface.ts +265 -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 +33 -0
- package/src/lib/server/DELETE.ts +9 -0
- package/src/lib/server/GET.ts +9 -0
- package/src/lib/server/HEAD.ts +9 -0
- package/src/lib/server/PATCH.ts +9 -0
- package/src/lib/server/POST.ts +9 -0
- package/src/lib/server/PUT.ts +9 -0
- package/src/lib/server/agent.ts +76 -0
- package/src/lib/server/appDataDir.ts +15 -0
- package/src/lib/server/cli/buildEnvContent.ts +19 -0
- package/src/lib/server/cli/createTarGz.ts +76 -0
- package/src/lib/server/cli/handleCliDownload.ts +153 -0
- package/src/lib/server/cli/handleCliInstall.ts +37 -0
- package/src/lib/server/cli/installScript.ts +29 -0
- package/src/lib/server/cli/maxSourceMtime.ts +26 -0
- package/src/lib/server/cookies.ts +29 -0
- package/src/lib/server/env.ts +50 -0
- package/src/lib/server/error.ts +70 -0
- package/src/lib/server/json.ts +28 -0
- package/src/lib/server/jsonl.ts +46 -0
- package/src/lib/server/prompts/definePrompt.ts +20 -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 +16 -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/redirect.ts +42 -0
- package/src/lib/server/request.ts +18 -0
- package/src/lib/server/rpc/defineVerb.ts +133 -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 +95 -0
- package/src/lib/server/rpc/registerVerb.ts +6 -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 +68 -0
- package/src/lib/server/rpc/types/VerbRegistryEntry.ts +29 -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_REBUILD_MESSAGE.ts +4 -0
- package/src/lib/server/runtime/DEV_RELOAD_CLIENT_SCRIPT.ts +29 -0
- package/src/lib/server/runtime/acceptsZstd.ts +8 -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/createAssetHeaderCache.ts +35 -0
- package/src/lib/server/runtime/createPublicAssetServer.ts +63 -0
- package/src/lib/server/runtime/createRouteDispatcher.ts +100 -0
- package/src/lib/server/runtime/createServer.ts +692 -0
- package/src/lib/server/runtime/devReloadResponse.ts +35 -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 +35 -0
- package/src/lib/server/runtime/getActiveServer.ts +6 -0
- package/src/lib/server/runtime/globToPathSet.ts +29 -0
- package/src/lib/server/runtime/inProcessServer.ts +20 -0
- package/src/lib/server/runtime/internalErrorResponse.ts +25 -0
- package/src/lib/server/runtime/isCrossOriginUpgrade.ts +19 -0
- package/src/lib/server/runtime/listenOnOpenPort.ts +36 -0
- package/src/lib/server/runtime/logExposedSurfaces.ts +162 -0
- package/src/lib/server/runtime/mimeForExtension.ts +20 -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/resolveStreamResponse.ts +29 -0
- package/src/lib/server/runtime/runWithRequestScope.ts +57 -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 +81 -0
- package/src/lib/server/runtime/streamCacheResolutions.ts +37 -0
- package/src/lib/server/runtime/streamFromIterator.ts +86 -0
- package/src/lib/server/runtime/streamStash.ts +64 -0
- package/src/lib/server/runtime/types/Assets.ts +1 -0
- package/src/lib/server/runtime/types/RequestStore.ts +27 -0
- package/src/lib/server/runtime/withResponseDefaults.ts +24 -0
- package/src/lib/server/server.ts +32 -0
- package/src/lib/server/socket.ts +31 -0
- package/src/lib/server/sockets/createSocketDispatcher.ts +311 -0
- package/src/lib/server/sockets/defineSocket.ts +167 -0
- package/src/lib/server/sockets/lookupSocket.ts +6 -0
- package/src/lib/server/sockets/recentHistory.ts +11 -0
- package/src/lib/server/sockets/registerSocket.ts +6 -0
- package/src/lib/server/sockets/socketOperations.ts +35 -0
- package/src/lib/server/sockets/socketRegistry.ts +9 -0
- package/src/lib/server/sockets/types/Socket.ts +21 -0
- package/src/lib/server/sockets/types/SocketClientFrame.ts +18 -0
- package/src/lib/server/sockets/types/SocketOperation.ts +22 -0
- package/src/lib/server/sockets/types/SocketOptions.ts +22 -0
- package/src/lib/server/sockets/types/SocketRegistryEntry.ts +17 -0
- package/src/lib/server/sockets/types/SocketRoutes.ts +10 -0
- package/src/lib/server/sockets/types/SocketServerFrame.ts +15 -0
- package/src/lib/server/sse.ts +53 -0
- package/src/lib/shared/BELTE_PACKAGE_NAME.ts +7 -0
- package/src/lib/shared/CACHE_CONTROL_VALUES.ts +16 -0
- package/src/lib/shared/HttpError.ts +19 -0
- package/src/lib/shared/RESOLVE_STREAM_PATH.ts +7 -0
- package/src/lib/shared/STREAMING_CONTENT_TYPES.ts +11 -0
- package/src/lib/shared/activeCacheStore.ts +20 -0
- package/src/lib/shared/appDataDir.ts +34 -0
- package/src/lib/shared/belteImportName.ts +44 -0
- package/src/lib/shared/browserClientFlags.ts +10 -0
- package/src/lib/shared/buildRpcRequest.ts +70 -0
- package/src/lib/shared/bundleLayout.ts +36 -0
- package/src/lib/shared/bundled.ts +34 -0
- package/src/lib/shared/cache.ts +559 -0
- package/src/lib/shared/cacheStoreSlot.ts +16 -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 +75 -0
- package/src/lib/shared/createPushIterator.ts +93 -0
- package/src/lib/shared/createRemoteFunction.ts +99 -0
- package/src/lib/shared/decodeResponse.ts +47 -0
- package/src/lib/shared/detectTarget.ts +27 -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 +479 -0
- package/src/lib/shared/forwardHeaders.ts +41 -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/importNamesToStrip.ts +13 -0
- package/src/lib/shared/invalidateEvent.ts +11 -0
- package/src/lib/shared/isCompileTarget.ts +15 -0
- package/src/lib/shared/isDebugEnabled.ts +23 -0
- package/src/lib/shared/isModuleNotFound.ts +16 -0
- package/src/lib/shared/isReadOnlyMethod.ts +14 -0
- package/src/lib/shared/isStreamingResponse.ts +11 -0
- package/src/lib/shared/jsonSchemaForPromptArguments.ts +29 -0
- package/src/lib/shared/jsonSchemaForSchema.ts +32 -0
- package/src/lib/shared/jsonlErrorFrame.ts +24 -0
- package/src/lib/shared/keyForRemoteCall.ts +29 -0
- package/src/lib/shared/lastConnectionPath.ts +7 -0
- package/src/lib/shared/loadEnvFile.ts +17 -0
- package/src/lib/shared/loadEnvFromDataDir.ts +15 -0
- package/src/lib/shared/loadSvelteConfig.ts +18 -0
- package/src/lib/shared/log.ts +104 -0
- package/src/lib/shared/manifestModule.ts +39 -0
- package/src/lib/shared/memoizeByKey.ts +24 -0
- package/src/lib/shared/nearestLayoutPrefix.ts +36 -0
- package/src/lib/shared/normalizeTarget.ts +10 -0
- package/src/lib/shared/pageUrlForFile.ts +14 -0
- package/src/lib/shared/parseBoundedEnvInt.ts +20 -0
- package/src/lib/shared/parseEnv.ts +30 -0
- package/src/lib/shared/parsePromptMarkdown.ts +34 -0
- package/src/lib/shared/parseRouteSegments.ts +22 -0
- package/src/lib/shared/prepareRpcModule.ts +59 -0
- package/src/lib/shared/prepareSocketModule.ts +49 -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/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/remoteMetaStore.ts +16 -0
- package/src/lib/shared/resolveClientFlags.ts +20 -0
- package/src/lib/shared/responseErrorText.ts +9 -0
- package/src/lib/shared/rpcUrlForFile.ts +19 -0
- package/src/lib/shared/runningAsStandaloneBinary.ts +13 -0
- package/src/lib/shared/serializeEnv.ts +18 -0
- package/src/lib/shared/setCacheStoreResolver.ts +6 -0
- package/src/lib/shared/setGlobalCacheStoreResolver.ts +6 -0
- package/src/lib/shared/socketNameForFile.ts +11 -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/toBunRoutePattern.ts +28 -0
- package/src/lib/shared/types/CacheEntry.ts +63 -0
- package/src/lib/shared/types/CacheInvalidation.ts +9 -0
- package/src/lib/shared/types/CacheOptions.ts +33 -0
- package/src/lib/shared/types/CacheSnapshot.ts +16 -0
- package/src/lib/shared/types/CacheSnapshotEntry.ts +15 -0
- package/src/lib/shared/types/CacheStore.ts +32 -0
- package/src/lib/shared/types/ClientFlags.ts +11 -0
- package/src/lib/shared/types/CompileTarget.ts +6 -0
- package/src/lib/shared/types/HttpVerb.ts +1 -0
- package/src/lib/shared/types/LastConnection.ts +9 -0
- package/src/lib/shared/types/PromptArgument.ts +12 -0
- package/src/lib/shared/types/RawRemoteFunction.ts +13 -0
- package/src/lib/shared/types/RemoteFunction.ts +42 -0
- package/src/lib/shared/types/StandardSchemaV1.ts +57 -0
- package/src/lib/shared/types/StreamedResolution.ts +10 -0
- package/src/lib/shared/types/StreamingPlaceholder.ts +13 -0
- package/src/lib/shared/types/Subscribable.ts +15 -0
- package/src/lib/shared/types/SvelteConfig.ts +5 -0
- package/src/lib/shared/withJsonSchema.ts +20 -0
- package/src/lib/shared/writeLastConnection.ts +13 -0
- package/src/lib/shared/writeRoutesDts.ts +67 -0
- package/src/lib/test/clearVerbRegistry.ts +11 -0
- package/src/lib/test/createTestClient.ts +78 -0
- package/src/preload.ts +20 -0
- package/src/scaffold.ts +92 -0
- package/src/serverBuildPlugins.ts +25 -0
- package/src/serverEntry.ts +94 -0
- package/src/sveltePlugin.ts +58 -0
- package/src/tailwindStylePreprocessor.ts +62 -0
- package/template/bunfig.toml +4 -0
- package/template/package.json +19 -0
- package/template/src/app.ts +23 -0
- package/template/src/browser/app.css +21 -0
- package/template/src/browser/app.html +24 -0
- package/template/src/browser/pages/about/page.svelte +5 -0
- package/template/src/browser/pages/layout.svelte +26 -0
- package/template/src/browser/pages/page.svelte +20 -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 +35 -0
- package/template/svelte.config.js +12 -0
- package/template/tsconfig.json +18 -0
- package/tsconfig.app.json +16 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Wire frame the server sends over the multiplexed socket connection.
|
|
3
|
+
|
|
4
|
+
`msg` is keyed by socket name (not sub id) because one publish fans
|
|
5
|
+
out to every client subscribed to the socket via Bun's native
|
|
6
|
+
publish — the client demuxes against every local sub of that socket.
|
|
7
|
+
`end` and `err` are per-sub because they're subscription-lifecycle
|
|
8
|
+
events; `err.message` is the only thrown-value field forwarded so the
|
|
9
|
+
wire stays JSON-safe and server-side stack traces never reach the
|
|
10
|
+
client.
|
|
11
|
+
*/
|
|
12
|
+
export type SocketServerFrame =
|
|
13
|
+
| { type: 'msg'; socket: string; message: unknown }
|
|
14
|
+
| { type: 'end'; sub: string }
|
|
15
|
+
| { type: 'err'; sub: string; message: string }
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Wraps an AsyncIterable<Frame> in a Response whose body is
|
|
3
|
+
Server-Sent Events (text/event-stream) — each frame becomes one
|
|
4
|
+
`data: <json>\n\n` event. Used inside an rpc handler to expose a
|
|
5
|
+
generator over plain HTTP so EventSource (or `subscribe(fn.stream)(args)`
|
|
6
|
+
on the client) can consume it frame-by-frame.
|
|
7
|
+
|
|
8
|
+
export const orderFeed = GET<Args>((args) =>
|
|
9
|
+
sse(async function* () {
|
|
10
|
+
for await (const order of db.watchOrders(args)) yield order
|
|
11
|
+
}())
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
A 15s keepalive comment (`: keepalive\n\n`) is sent between frames so
|
|
15
|
+
intermediaries (proxies, load balancers) don't drop an idle connection.
|
|
16
|
+
Comments are ignored by EventSource per the spec, so they're invisible to
|
|
17
|
+
consumers.
|
|
18
|
+
|
|
19
|
+
Cancellation flows from the consumer through ReadableStream's `cancel`
|
|
20
|
+
into `iter.return()` so the handler's `for await` exits via its normal
|
|
21
|
+
control path. Errors are emitted as an `event: error` frame carrying only
|
|
22
|
+
the message (full error logged server-side) before the stream closes;
|
|
23
|
+
EventSource surfaces this via its `error` listener and `subscribe()`
|
|
24
|
+
maps it to the entry's `error` field.
|
|
25
|
+
*/
|
|
26
|
+
import { NO_STORE } from '../shared/CACHE_CONTROL_VALUES.ts'
|
|
27
|
+
import { sseErrorFrame } from '../shared/sseErrorFrame.ts'
|
|
28
|
+
import type { TypedResponse } from './rpc/types/TypedResponse.ts'
|
|
29
|
+
import { streamFromIterator } from './runtime/streamFromIterator.ts'
|
|
30
|
+
import { withResponseDefaults } from './runtime/withResponseDefaults.ts'
|
|
31
|
+
|
|
32
|
+
const KEEPALIVE_INTERVAL_MS = 15000
|
|
33
|
+
|
|
34
|
+
export function sse<Frame>(
|
|
35
|
+
iterable: AsyncIterable<Frame>,
|
|
36
|
+
init?: ResponseInit,
|
|
37
|
+
): TypedResponse<Frame> {
|
|
38
|
+
const body = streamFromIterator(iterable, {
|
|
39
|
+
encodeFrame: (value) => `data: ${JSON.stringify(value)}\n\n`,
|
|
40
|
+
encodeError: (message) => sseErrorFrame.encode(message),
|
|
41
|
+
keepaliveMs: KEEPALIVE_INTERVAL_MS,
|
|
42
|
+
keepalivePayload: ': keepalive\n\n',
|
|
43
|
+
})
|
|
44
|
+
return new Response(
|
|
45
|
+
body,
|
|
46
|
+
withResponseDefaults(init, {
|
|
47
|
+
'Content-Type': 'text/event-stream; charset=utf-8',
|
|
48
|
+
'Cache-Control': NO_STORE,
|
|
49
|
+
'X-Content-Type-Options': 'nosniff',
|
|
50
|
+
Connection: 'keep-alive',
|
|
51
|
+
}),
|
|
52
|
+
) as TypedResponse<Frame>
|
|
53
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/*
|
|
2
|
+
The package's published npm name. The codegen and the import-name resolver
|
|
3
|
+
match a consuming project's dependency (direct or aliased) against this to
|
|
4
|
+
decide which specifier to emit, so keeping it in one place means a future
|
|
5
|
+
rename touches a single constant.
|
|
6
|
+
*/
|
|
7
|
+
export const BELTE_PACKAGE_NAME = '@belte/belte'
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Cache-Control values used by belte's framework responses. Centralised so
|
|
3
|
+
the framework's policy (no-store on errors and rpc dispatch helpers,
|
|
4
|
+
private/no-cache on SSR HTML, the static-asset policies) lives in one place
|
|
5
|
+
and can't drift between the server core, the asset servers, and the respond
|
|
6
|
+
helpers.
|
|
7
|
+
*/
|
|
8
|
+
export const NO_STORE = 'no-store'
|
|
9
|
+
export const SSR_CACHE_CONTROL = 'private, no-cache'
|
|
10
|
+
|
|
11
|
+
// Content-addressed `/_app/` chunks (name carries the hash) — cache forever.
|
|
12
|
+
export const IMMUTABLE_ASSET_CACHE_CONTROL = 'public, max-age=31536000, immutable'
|
|
13
|
+
// Unhashed `/_app/` entries (entry bundle, shell) — must revalidate each time.
|
|
14
|
+
export const REVALIDATE_ASSET_CACHE_CONTROL = 'public, max-age=0, must-revalidate'
|
|
15
|
+
// Files served from public/ at the site root — short shared cache.
|
|
16
|
+
export const PUBLIC_ASSET_CACHE_CONTROL = 'public, max-age=3600'
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Thrown by remote-function calls when the server responds with a non-2xx
|
|
3
|
+
status. Carries the raw Response so callers can inspect body, headers, or
|
|
4
|
+
status text — useful for showing user-friendly error UI without having to
|
|
5
|
+
opt every call site into the `.raw()` escape hatch.
|
|
6
|
+
*/
|
|
7
|
+
export class HttpError extends Error {
|
|
8
|
+
readonly status: number
|
|
9
|
+
readonly statusText: string
|
|
10
|
+
readonly response: Response
|
|
11
|
+
|
|
12
|
+
constructor(response: Response) {
|
|
13
|
+
super(`HTTP ${response.status} ${response.statusText || 'error'}`)
|
|
14
|
+
this.name = 'HttpError'
|
|
15
|
+
this.status = response.status
|
|
16
|
+
this.statusText = response.statusText
|
|
17
|
+
this.response = response
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Path prefix for the out-of-band resolution stream. The SSR document ships a
|
|
3
|
+
single-use token in `__SSR__.streamToken`; the browser opens
|
|
4
|
+
`${RESOLVE_STREAM_PATH}${token}` once to receive its pending {#await} resolutions.
|
|
5
|
+
Shared so the server route and the client fetch agree on the path.
|
|
6
|
+
*/
|
|
7
|
+
export const RESOLVE_STREAM_PATH = '/__belte/resolve/'
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Content-Type prefixes belte treats as streaming bodies — SSE for the
|
|
3
|
+
`sse()` helper, JSONL / NDJSON for the `jsonl()` helper. Used by
|
|
4
|
+
decodeResponse to refuse a buffered decode and by streamResponse to
|
|
5
|
+
choose the frame parser.
|
|
6
|
+
*/
|
|
7
|
+
export const STREAMING_CONTENT_TYPES = [
|
|
8
|
+
'text/event-stream',
|
|
9
|
+
'application/jsonl',
|
|
10
|
+
'application/x-ndjson',
|
|
11
|
+
]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { cacheStoreSlot } from './cacheStoreSlot.ts'
|
|
2
|
+
import { createCacheStore } from './createCacheStore.ts'
|
|
3
|
+
import type { CacheStore } from './types/CacheStore.ts'
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
Resolves the active CacheStore. The runtime is registered via
|
|
7
|
+
`setCacheStoreResolver` from the server entry (request-scoped via ALS)
|
|
8
|
+
or the client entry (module-level singleton). If no resolver is registered,
|
|
9
|
+
a single fallback store is created lazily so isolated tests still work.
|
|
10
|
+
*/
|
|
11
|
+
export function activeCacheStore(): CacheStore {
|
|
12
|
+
const fromResolver = cacheStoreSlot.resolver?.()
|
|
13
|
+
if (fromResolver) {
|
|
14
|
+
return fromResolver
|
|
15
|
+
}
|
|
16
|
+
if (!cacheStoreSlot.fallback) {
|
|
17
|
+
cacheStoreSlot.fallback = createCacheStore()
|
|
18
|
+
}
|
|
19
|
+
return cacheStoreSlot.fallback
|
|
20
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { homedir } from 'node:os'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
Platform-standard per-user data directory for a bundle, keyed by its program
|
|
6
|
+
name. cwd-independent on purpose: the path derives from `programName`, not the
|
|
7
|
+
process working directory — which the OS `open` command sets to `/`, so anything
|
|
8
|
+
relying on cwd (Bun's `.env` autoload, relative paths) finds nothing inside a
|
|
9
|
+
launched `.app`. This is where a bundle keeps what can't be baked at compile time
|
|
10
|
+
— the user's config, DB, and cache. macOS Application Support, Windows %APPDATA%,
|
|
11
|
+
XDG data home elsewhere. Pure: computes the path, never touches the filesystem.
|
|
12
|
+
|
|
13
|
+
`BELTE_DATA_DIR` overrides the lot on every platform, used as-is (no programName
|
|
14
|
+
appended) — a cross-platform `XDG_DATA_HOME` that also works on macOS/Windows. Set
|
|
15
|
+
it to point dev at a throwaway dir without touching app code; leave it unset in
|
|
16
|
+
prod for the platform default. A relative value reintroduces cwd-dependence, so a
|
|
17
|
+
launched `.app` (cwd `/`) needs an absolute path. Must come from a layer above the
|
|
18
|
+
data-dir `.env` (shell, CWD `.env`, or binary-dir `.env`) — it can't be read from
|
|
19
|
+
the very file whose location it decides.
|
|
20
|
+
*/
|
|
21
|
+
export function appDataDir(programName: string): string {
|
|
22
|
+
const override = process.env.BELTE_DATA_DIR
|
|
23
|
+
if (override !== undefined && override !== '') {
|
|
24
|
+
return override
|
|
25
|
+
}
|
|
26
|
+
const home = homedir()
|
|
27
|
+
if (process.platform === 'darwin') {
|
|
28
|
+
return join(home, 'Library', 'Application Support', programName)
|
|
29
|
+
}
|
|
30
|
+
if (process.platform === 'win32') {
|
|
31
|
+
return join(process.env.APPDATA ?? join(home, 'AppData', 'Roaming'), programName)
|
|
32
|
+
}
|
|
33
|
+
return join(process.env.XDG_DATA_HOME ?? join(home, '.local', 'share'), programName)
|
|
34
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { BELTE_PACKAGE_NAME } from './BELTE_PACKAGE_NAME.ts'
|
|
2
|
+
import { readPackageJson } from './readPackageJson.ts'
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
Resolves the bare specifier prefix a consuming project imports belte under —
|
|
6
|
+
the name belte is installed as in its package.json. A project may depend on
|
|
7
|
+
belte directly (`@belte/belte`) or behind a package alias
|
|
8
|
+
(`"belte": "npm:@belte/belte@..."`, or `workspace:@belte/belte@*`
|
|
9
|
+
inside this repo). An alias-only install resolves only under the alias key and
|
|
10
|
+
a direct install only under the canonical name, so the generated rpc / socket
|
|
11
|
+
/ prompt modules must import under whichever name the project
|
|
12
|
+
declared.
|
|
13
|
+
|
|
14
|
+
Prefers a `belte` alias (the ergonomic surface the docs use) when present, then
|
|
15
|
+
a direct canonical dependency, then any other alias targeting belte. Falls back
|
|
16
|
+
to the canonical name when belte isn't found in package.json — the build can't
|
|
17
|
+
resolve belte at all in that case, and the canonical name yields the clearest
|
|
18
|
+
resolution error.
|
|
19
|
+
*/
|
|
20
|
+
export async function belteImportName(cwd: string): Promise<string> {
|
|
21
|
+
const packageJson = (await readPackageJson(cwd)) as
|
|
22
|
+
| { dependencies?: Record<string, string>; devDependencies?: Record<string, string> }
|
|
23
|
+
| undefined
|
|
24
|
+
if (!packageJson) {
|
|
25
|
+
return BELTE_PACKAGE_NAME
|
|
26
|
+
}
|
|
27
|
+
const dependencies = { ...packageJson.devDependencies, ...packageJson.dependencies }
|
|
28
|
+
/*
|
|
29
|
+
Alias entries whose target is belte — `npm:` for a published install,
|
|
30
|
+
`workspace:` for the in-repo examples. The key is the name the project
|
|
31
|
+
imports under; the version suffix (`@^0.2.0`, `@*`) is optional.
|
|
32
|
+
*/
|
|
33
|
+
const aliasPattern = new RegExp(`^(npm|workspace):${BELTE_PACKAGE_NAME}(@.*)?$`)
|
|
34
|
+
const aliasNames = Object.entries(dependencies)
|
|
35
|
+
.filter(([, specifier]) => aliasPattern.test(specifier))
|
|
36
|
+
.map(([name]) => name)
|
|
37
|
+
if (aliasNames.includes('belte')) {
|
|
38
|
+
return 'belte'
|
|
39
|
+
}
|
|
40
|
+
if (BELTE_PACKAGE_NAME in dependencies) {
|
|
41
|
+
return BELTE_PACKAGE_NAME
|
|
42
|
+
}
|
|
43
|
+
return aliasNames[0] ?? BELTE_PACKAGE_NAME
|
|
44
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ClientFlags } from './types/ClientFlags.ts'
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
Client surface flags for a browser-emitted RPC/socket stub. The bundler only
|
|
5
|
+
emits the browser proxy when clients.browser is true, so browser is always true
|
|
6
|
+
here; mcp/cli are server-only discovery state with no meaning in the browser
|
|
7
|
+
bundle, defaulted false so the public RemoteFunction/Socket shape matches the
|
|
8
|
+
server side. Single source shared by remoteProxy and socketProxy.
|
|
9
|
+
*/
|
|
10
|
+
export const browserClientFlags: ClientFlags = { browser: true, mcp: false, cli: false }
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { carriesBodyArgs } from './carriesBodyArgs.ts'
|
|
2
|
+
import { queryStringFromArgs } from './queryStringFromArgs.ts'
|
|
3
|
+
import type { HttpVerb } from './types/HttpVerb.ts'
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
Builds the Request a verb helper uses to invoke its handler. Same shape on
|
|
7
|
+
both sides (server defineVerb + client remoteProxy) so the cache key
|
|
8
|
+
derivation and SSR snapshot round-trip identically. $rpc URLs are flat
|
|
9
|
+
(no `:name` segments): GET/DELETE/HEAD serialise args onto the query
|
|
10
|
+
string; POST/PUT/PATCH send them as application/json.
|
|
11
|
+
|
|
12
|
+
`baseUrl` provides the origin needed by the Request constructor — on the
|
|
13
|
+
server it's the inbound request's URL (so handlers reading `request.url` see
|
|
14
|
+
the caller's host), in the browser it's window.location. `headers` lets the
|
|
15
|
+
server pre-populate the synthetic Request with forwarded session headers;
|
|
16
|
+
the client passes nothing.
|
|
17
|
+
*/
|
|
18
|
+
export function buildRpcRequest({
|
|
19
|
+
method,
|
|
20
|
+
url,
|
|
21
|
+
args,
|
|
22
|
+
baseUrl,
|
|
23
|
+
headers,
|
|
24
|
+
}: {
|
|
25
|
+
method: HttpVerb
|
|
26
|
+
url: string
|
|
27
|
+
args: unknown
|
|
28
|
+
baseUrl: string
|
|
29
|
+
headers?: Headers
|
|
30
|
+
}): Request {
|
|
31
|
+
const requestHeaders = headers ?? new Headers()
|
|
32
|
+
if (!carriesBodyArgs(method)) {
|
|
33
|
+
const target = appendQuery(method, url, args)
|
|
34
|
+
return new Request(new URL(target, baseUrl).href, { method, headers: requestHeaders })
|
|
35
|
+
}
|
|
36
|
+
if (args === undefined) {
|
|
37
|
+
return new Request(new URL(url, baseUrl).href, { method, headers: requestHeaders })
|
|
38
|
+
}
|
|
39
|
+
/*
|
|
40
|
+
A FormData body ships as-is: the Request constructor sets its own
|
|
41
|
+
`multipart/form-data` content-type with a boundary, so the server's
|
|
42
|
+
parseArgs splits text fields into args and File parts into files().
|
|
43
|
+
Setting the header by hand would omit the boundary and break parsing.
|
|
44
|
+
*/
|
|
45
|
+
if (args instanceof FormData) {
|
|
46
|
+
return new Request(new URL(url, baseUrl).href, {
|
|
47
|
+
method,
|
|
48
|
+
headers: requestHeaders,
|
|
49
|
+
body: args,
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
requestHeaders.set('content-type', 'application/json')
|
|
53
|
+
return new Request(new URL(url, baseUrl).href, {
|
|
54
|
+
method,
|
|
55
|
+
headers: requestHeaders,
|
|
56
|
+
body: JSON.stringify(args),
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function appendQuery(method: HttpVerb, url: string, args: unknown): string {
|
|
61
|
+
if (args === undefined) {
|
|
62
|
+
return url
|
|
63
|
+
}
|
|
64
|
+
if (typeof args !== 'object' || args === null || Array.isArray(args)) {
|
|
65
|
+
const got = Array.isArray(args) ? 'array' : typeof args
|
|
66
|
+
throw new Error(`[belte] ${method} ${url} args must be a plain object — got ${got}`)
|
|
67
|
+
}
|
|
68
|
+
const suffix = queryStringFromArgs(args as Record<string, unknown>, false)
|
|
69
|
+
return suffix === '' ? url : `${url}?${suffix}`
|
|
70
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { basename, dirname, join } from 'node:path'
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
Where a bundle's files live relative to its binary directory (the dir holding the
|
|
5
|
+
launcher + server — `dirname(process.execPath)` at runtime). A macOS `.app` nests
|
|
6
|
+
binaries under `Contents/MacOS`, the webview lib under `Contents/Frameworks`, and
|
|
7
|
+
data under `Contents/Resources` — the only one `codesign` seals as a *resource*,
|
|
8
|
+
so the shipped `.env` survives signing. Every other platform keeps everything
|
|
9
|
+
flat beside the binaries. The single source the bundler writes against and the
|
|
10
|
+
boot readers resolve from, so build and runtime can't disagree. Pure: computes
|
|
11
|
+
paths, never touches disk.
|
|
12
|
+
*/
|
|
13
|
+
export function bundleLayout(binaryDir: string): {
|
|
14
|
+
binDir: string
|
|
15
|
+
libDir: string
|
|
16
|
+
resourcesDir: string
|
|
17
|
+
envPath: string
|
|
18
|
+
} {
|
|
19
|
+
const isMacApp = basename(binaryDir) === 'MacOS' && basename(dirname(binaryDir)) === 'Contents'
|
|
20
|
+
if (isMacApp) {
|
|
21
|
+
const contents = dirname(binaryDir)
|
|
22
|
+
const resourcesDir = join(contents, 'Resources')
|
|
23
|
+
return {
|
|
24
|
+
binDir: binaryDir,
|
|
25
|
+
libDir: join(contents, 'Frameworks'),
|
|
26
|
+
resourcesDir,
|
|
27
|
+
envPath: join(resourcesDir, '.env'),
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
binDir: binaryDir,
|
|
32
|
+
libDir: binaryDir,
|
|
33
|
+
resourcesDir: binaryDir,
|
|
34
|
+
envPath: join(binaryDir, '.env'),
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
declare global {
|
|
2
|
+
interface Window {
|
|
3
|
+
// Set by the native webview's init script (openWebview) on every document
|
|
4
|
+
// it loads — local or remote. Absent in a plain browser tab.
|
|
5
|
+
__BELTE_BUNDLE__?: boolean
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
True when this code runs inside the belte desktop bundle rather than a plain web
|
|
11
|
+
app in a browser. Isomorphic: one name, same meaning on both sides — "am I part of
|
|
12
|
+
the bundle" — though each side detects it differently.
|
|
13
|
+
|
|
14
|
+
Client: the native webview runs an init script on every document it loads
|
|
15
|
+
(openWebview's webview_init), so the flag is present whether the page came from the
|
|
16
|
+
bundle's own embedded server or a *remote* one. A plain browser tab never runs that
|
|
17
|
+
script — even when it hits the embedded localhost server — so it reads false there.
|
|
18
|
+
This is the "in a webview" signal, robust to local-or-remote.
|
|
19
|
+
|
|
20
|
+
Server: the launcher sets BELTE_PARENT_PID when it spawns the embedded server (see
|
|
21
|
+
spawnEmbeddedServer), so its presence marks "I am the bundle's embedded server
|
|
22
|
+
process." A remote server is never part of a bundle, so it reads false — matching
|
|
23
|
+
the client view that a remote page's *data source* is outside the bundle even while
|
|
24
|
+
its *rendering context* (the webview) is inside it.
|
|
25
|
+
|
|
26
|
+
Distinct from runningAsStandaloneBinary(), which is also true for a plain compiled
|
|
27
|
+
(install-tarball) server binary — still a web app, not a bundle.
|
|
28
|
+
*/
|
|
29
|
+
export function bundled(): boolean {
|
|
30
|
+
if (typeof window === 'undefined') {
|
|
31
|
+
return Boolean(Bun.env.BELTE_PARENT_PID)
|
|
32
|
+
}
|
|
33
|
+
return window.__BELTE_BUNDLE__ === true
|
|
34
|
+
}
|