@abide/abide 0.49.0 → 0.50.1
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/AGENTS.md +564 -437
- package/CHANGELOG.md +183 -0
- package/README.md +165 -202
- package/package.json +14 -5
- package/src/abideLsp.ts +5 -6
- package/src/abideResolverPlugin.ts +197 -169
- package/src/build.ts +79 -56
- package/src/buildDisconnected.ts +0 -2
- package/src/checkAbide.ts +12 -2
- package/src/devEntry.ts +113 -28
- package/src/discoveryEntry.ts +3 -2
- package/src/lib/bundle/disconnected.abide +69 -73
- package/src/lib/bundle/infoPlist.ts +13 -7
- package/src/lib/bundle/spawnEmbeddedServer.ts +13 -4
- package/src/lib/bundle/waitForServer.ts +6 -1
- package/src/lib/mcp/mcpTools.ts +15 -6
- package/src/lib/server/error.ts +6 -6
- package/src/lib/server/json.ts +17 -3
- package/src/lib/server/rpc/defineRpc.ts +58 -24
- package/src/lib/server/rpc/parseArgs.ts +98 -13
- package/src/lib/server/rpc/resolveRpcJsonSchema.ts +28 -0
- package/src/lib/server/rpc/types/RpcHelper.ts +75 -105
- package/src/lib/server/rpc/types/RpcRegistryEntry.ts +24 -9
- package/src/lib/server/rpc/validationError.ts +1 -1
- package/src/lib/server/runtime/DEV_RELOAD_CLIENT_SCRIPT.ts +0 -15
- package/src/lib/server/runtime/buildCacheSnapshot.ts +10 -9
- package/src/lib/server/runtime/buildInspectorSurface.ts +6 -4
- package/src/lib/server/runtime/buildOpenApiSpec.ts +55 -11
- package/src/lib/server/runtime/buildPreloadManifest.ts +12 -10
- package/src/lib/server/runtime/createAppAssetServer.ts +18 -15
- package/src/lib/server/runtime/createAppRouteResolver.ts +145 -0
- package/src/lib/server/runtime/createPlumbingRouter.ts +212 -0
- package/src/lib/server/runtime/createRouteDispatcher.ts +4 -10
- package/src/lib/server/runtime/createServer.ts +120 -324
- package/src/lib/server/runtime/createUiPageRenderer.ts +137 -26
- package/src/lib/server/runtime/devClientFingerprint.ts +19 -34
- package/src/lib/server/runtime/installAmbientScopeStore.ts +30 -9
- package/src/lib/server/runtime/logExposedSurfaces.ts +8 -7
- package/src/lib/server/runtime/pathStore.ts +15 -0
- package/src/lib/server/runtime/registryManifests.ts +1 -1
- package/src/lib/server/runtime/renderCellBarrierStore.ts +15 -0
- package/src/lib/server/runtime/runWithRequestScope.ts +3 -0
- package/src/lib/server/runtime/serializeCacheSnapshot.ts +6 -4
- package/src/lib/server/runtime/snapshotEntryFromCache.ts +14 -14
- package/src/lib/server/runtime/streamCacheResolutions.ts +14 -7
- package/src/lib/server/runtime/streamFromIterator.ts +30 -2
- package/src/lib/server/runtime/textResponse.ts +23 -0
- package/src/lib/server/runtime/types/DevReloadStamp.ts +6 -10
- package/src/lib/server/runtime/types/InspectorCacheEntry.ts +1 -1
- package/src/lib/server/runtime/types/RequestStore.ts +27 -0
- package/src/lib/server/runtime/warnUnguardedMcp.ts +15 -5
- package/src/lib/server/sockets/createSocketDispatcher.ts +9 -11
- package/src/lib/server/sockets/defineSocket.ts +5 -4
- package/src/lib/server/sse.ts +5 -1
- package/src/lib/shared/ASYNC_CELL.ts +5 -0
- package/src/lib/shared/DEV_REBUILD_PATH.ts +6 -0
- package/src/lib/shared/HTTP_METHODS.ts +6 -0
- package/src/lib/shared/HttpError.ts +1 -5
- package/src/lib/shared/MCP_PATH.ts +6 -0
- package/src/lib/shared/PROXIED_SERVER_SUBDIRS.ts +15 -0
- package/src/lib/shared/REF_JSON_TAGS.ts +13 -1
- package/src/lib/shared/RPC_SHIM_GLOBALS.ts +9 -0
- package/src/lib/shared/activeCacheStore.ts +1 -0
- package/src/lib/shared/activePage.ts +1 -0
- package/src/lib/shared/buildArtifact.ts +4 -1
- package/src/lib/shared/buildSocketOverChannel.ts +4 -3
- package/src/lib/shared/bundleGraphFromMetafile.ts +68 -0
- package/src/lib/shared/cache.ts +156 -131
- package/src/lib/shared/changeAffectsClient.ts +12 -7
- package/src/lib/shared/createCacheStore.ts +31 -8
- package/src/lib/shared/createLifecycleChannel.ts +7 -1
- package/src/lib/shared/createReachable.ts +47 -78
- package/src/lib/shared/createRemoteFunction.ts +52 -30
- package/src/lib/shared/createRpcServerProgram.ts +820 -0
- package/src/lib/shared/decodeRefJson.ts +4 -4
- package/src/lib/shared/decodeResponse.ts +2 -2
- package/src/lib/shared/decodeWireBody.ts +35 -0
- package/src/lib/shared/detectRpcMethod.ts +8 -1
- package/src/lib/shared/done.ts +8 -2
- package/src/lib/shared/encodeRefJson.ts +4 -4
- package/src/lib/shared/encodeWireBody.ts +18 -0
- package/src/lib/{server/rpc → shared}/fieldErrorsFromIssues.ts +5 -1
- package/src/lib/shared/generateDeclarations.ts +72 -0
- package/src/lib/shared/hasSeedableRequest.ts +25 -0
- package/src/lib/shared/hydrationWindow.ts +53 -0
- package/src/lib/shared/isAsyncCell.ts +11 -0
- package/src/lib/shared/isAsyncIterable.ts +8 -0
- package/src/lib/shared/isSubscribable.ts +3 -3
- package/src/lib/shared/isThenable.ts +9 -0
- package/src/lib/shared/jsonSchemaForType.ts +258 -0
- package/src/lib/shared/lenientDecode.ts +15 -0
- package/src/lib/shared/loadProjectTsConfig.ts +28 -0
- package/src/lib/shared/markFrameworkSourcesIgnored.ts +1 -1
- package/src/lib/shared/matchRoute.ts +4 -14
- package/src/lib/shared/peek.ts +14 -0
- package/src/lib/shared/pending.ts +9 -6
- package/src/lib/shared/pendingAsyncCellsSlot.ts +13 -0
- package/src/lib/shared/prepareRpcModule.ts +91 -93
- package/src/lib/shared/prepareSocketModule.ts +3 -2
- package/src/lib/shared/probeRegistries.ts +5 -18
- package/src/lib/shared/reachable.ts +7 -10
- package/src/lib/shared/refresh.ts +12 -2
- package/src/lib/shared/refreshing.ts +8 -2
- package/src/lib/shared/resolvedCellsSlot.ts +13 -0
- package/src/lib/shared/reviveWireField.ts +49 -0
- package/src/lib/shared/reviveWireOutput.ts +36 -0
- package/src/lib/shared/rpcServerForRoot.ts +25 -0
- package/src/lib/shared/scanPages.ts +25 -0
- package/src/lib/shared/snapshotShippable.ts +8 -7
- package/src/lib/shared/streamedCellsSlot.ts +14 -0
- package/src/lib/shared/subscribableFromResponse.ts +4 -4
- package/src/lib/shared/subscribableProbes.ts +1 -1
- package/src/lib/shared/tailProbeSlot.ts +1 -1
- package/src/lib/shared/types/AsyncComputed.ts +20 -0
- package/src/lib/shared/types/AsyncState.ts +13 -0
- package/src/lib/shared/types/CacheEntry.ts +7 -7
- package/src/lib/shared/types/CacheOptions.ts +23 -37
- package/src/lib/shared/types/CachePolicy.ts +25 -0
- package/src/lib/shared/types/CacheSnapshotEntry.ts +6 -5
- package/src/lib/shared/types/ErrorJsonSchemas.ts +8 -0
- package/src/lib/shared/types/HttpMethod.ts +3 -1
- package/src/lib/shared/types/InputCoercion.ts +17 -0
- package/src/lib/shared/types/{Subscribable.ts → NamedAsyncIterable.ts} +1 -1
- package/src/lib/shared/types/OutputWirePlan.ts +17 -0
- package/src/lib/shared/types/PagesScan.ts +7 -0
- package/src/lib/shared/types/PendingAsyncCells.ts +10 -0
- package/src/lib/shared/types/RawRemoteFunction.ts +6 -0
- package/src/lib/shared/types/RemoteCallable.ts +8 -7
- package/src/lib/shared/types/RemoteFunction.ts +16 -15
- package/src/lib/shared/types/ResolvedCells.ts +11 -0
- package/src/lib/shared/types/ReturnBody.ts +15 -0
- package/src/lib/shared/types/RpcBuildStamps.ts +23 -0
- package/src/lib/shared/types/RpcErrorGuard.ts +3 -8
- package/src/lib/shared/types/Socket.ts +4 -4
- package/src/lib/shared/types/SsrPayload.ts +5 -1
- package/src/lib/shared/types/StreamPolicy.ts +11 -0
- package/src/lib/shared/types/StreamedCells.ts +19 -0
- package/src/lib/shared/types/StreamedResolution.ts +24 -6
- package/src/lib/shared/types/TailHooks.ts +1 -1
- package/src/lib/shared/types/WireKind.ts +11 -0
- package/src/lib/shared/validationHttpError.ts +33 -0
- package/src/lib/shared/warmSeedKey.ts +16 -0
- package/src/lib/shared/wireJsonReplacer.ts +30 -0
- package/src/lib/shared/writeRpcDts.ts +11 -1
- package/src/lib/shared/writeTestSocketsDts.ts +1 -1
- package/src/lib/test/createTestApp.ts +19 -1
- package/src/lib/ui/README.md +1 -1
- package/src/lib/ui/activePendingCells.ts +14 -0
- package/src/lib/ui/compile/BLOCK_KEYWORDS.ts +21 -0
- package/src/lib/ui/compile/SSR_ESCAPE.ts +4 -1
- package/src/lib/ui/compile/UI_RUNTIME_IMPORTS.ts +35 -8
- package/src/lib/ui/compile/abideUiPlugin.ts +19 -2
- package/src/lib/ui/compile/analyzeComponent.ts +89 -6
- package/src/lib/ui/compile/assignmentTargetNames.ts +54 -0
- package/src/lib/ui/compile/asyncInterpolationFields.ts +152 -0
- package/src/lib/ui/compile/asyncValuePositionError.ts +21 -0
- package/src/lib/ui/compile/asyncValuePositionInterpolations.ts +64 -0
- package/src/lib/ui/compile/attrLiftPosition.ts +18 -0
- package/src/lib/ui/compile/cachedSourceFile.ts +40 -0
- package/src/lib/ui/compile/catchBinding.ts +7 -5
- package/src/lib/ui/compile/classifyInterpolationType.ts +46 -0
- package/src/lib/ui/compile/collectAbideDiagnostics.ts +96 -0
- package/src/lib/ui/compile/compileComponent.ts +19 -3
- package/src/lib/ui/compile/compileModule.ts +27 -58
- package/src/lib/ui/compile/compileSSR.ts +51 -12
- package/src/lib/ui/compile/compileShadow.ts +145 -18
- package/src/lib/ui/compile/composeProps.ts +12 -2
- package/src/lib/ui/compile/createShadowLanguageService.ts +116 -68
- package/src/lib/ui/compile/createShadowProgram.ts +35 -6
- package/src/lib/ui/compile/declaredNames.ts +36 -0
- package/src/lib/ui/compile/desugarSignals.ts +418 -36
- package/src/lib/ui/compile/expressionIsPrefixEvaluable.ts +19 -0
- package/src/lib/ui/compile/generateBuild.ts +52 -9
- package/src/lib/ui/compile/generateSSR.ts +242 -43
- package/src/lib/ui/compile/hoistableAwaits.ts +193 -0
- package/src/lib/ui/compile/hoistableChildRenders.ts +112 -0
- package/src/lib/ui/compile/interpolatedTemplateLiteral.ts +3 -1
- package/src/lib/ui/compile/interpolationClassifierForRoot.ts +37 -0
- package/src/lib/ui/compile/isSpuriousAsyncReadDiagnostic.ts +174 -0
- package/src/lib/ui/compile/liftAsyncSubExpressions.ts +166 -0
- package/src/lib/ui/compile/lowerAsyncInterpolations.ts +92 -0
- package/src/lib/ui/compile/lowerContext.ts +10 -0
- package/src/lib/ui/compile/lowerDocAccess.ts +26 -23
- package/src/lib/ui/compile/lowerScript.ts +40 -4
- package/src/lib/ui/compile/nodeAtShadowOffset.ts +28 -0
- package/src/lib/ui/compile/parseTemplate.ts +18 -1092
- package/src/lib/ui/compile/parseTemplateRecovering.ts +1385 -0
- package/src/lib/ui/compile/referencedIdentifiers.ts +35 -0
- package/src/lib/ui/compile/renameSignalRefs.ts +21 -22
- package/src/lib/ui/compile/seedTypeClassifierForRoot.ts +65 -0
- package/src/lib/ui/compile/shadowInterpolationClassifier.ts +47 -0
- package/src/lib/ui/compile/sourceFileOptionsSignature.ts +20 -0
- package/src/lib/ui/compile/structuralHeadTokens.ts +107 -0
- package/src/lib/ui/compile/templateSemanticTokens.ts +21 -0
- package/src/lib/ui/compile/templateStartOffset.ts +15 -0
- package/src/lib/ui/compile/tryPlan.ts +4 -3
- package/src/lib/ui/compile/types/AnalyzedComponent.ts +4 -0
- package/src/lib/ui/compile/types/AsyncInterpolationField.ts +19 -0
- package/src/lib/ui/compile/types/InterpolationClassifier.ts +12 -0
- package/src/lib/ui/compile/types/InterpolationKind.ts +7 -0
- package/src/lib/ui/compile/types/ParseDiagnostic.ts +8 -0
- package/src/lib/ui/compile/types/SeedTypeClassifier.ts +15 -0
- package/src/lib/ui/compile/types/TemplateNode.ts +36 -4
- package/src/lib/ui/compile/types/ValuePositionInterpolation.ts +13 -0
- package/src/lib/ui/compile/writtenTemplateNames.ts +84 -0
- package/src/lib/ui/computed.ts +28 -1
- package/src/lib/ui/createScope.ts +35 -68
- package/src/lib/ui/dom/anchoredBranch.ts +142 -0
- package/src/lib/ui/dom/appendText.ts +8 -3
- package/src/lib/ui/dom/awaitBlock.ts +43 -94
- package/src/lib/ui/dom/bindProp.ts +22 -0
- package/src/lib/ui/dom/bindableProp.ts +47 -0
- package/src/lib/ui/dom/cellPending.ts +24 -0
- package/src/lib/ui/dom/disposeRange.ts +2 -1
- package/src/lib/ui/dom/each.ts +26 -4
- package/src/lib/ui/dom/eachAsync.ts +39 -3
- package/src/lib/ui/dom/fillBoundary.ts +2 -3
- package/src/lib/ui/dom/fillRange.ts +4 -4
- package/src/lib/ui/dom/hydrate.ts +6 -12
- package/src/lib/ui/dom/isComment.ts +1 -1
- package/src/lib/ui/dom/matchingRangeClose.ts +29 -0
- package/src/lib/ui/dom/mount.ts +1 -2
- package/src/lib/ui/dom/mountChild.ts +9 -40
- package/src/lib/ui/dom/mountRange.ts +2 -3
- package/src/lib/ui/dom/mountStreamedChild.ts +84 -0
- package/src/lib/ui/dom/mountSwappableRange.ts +46 -4
- package/src/lib/ui/dom/mutateDocContainer.ts +65 -0
- package/src/lib/ui/dom/on.ts +2 -2
- package/src/lib/ui/dom/readCell.ts +40 -0
- package/src/lib/ui/dom/switchBlock.ts +30 -7
- package/src/lib/ui/dom/tryBlock.ts +230 -66
- package/src/lib/ui/dom/types/SwitchCase.ts +5 -1
- package/src/lib/ui/dom/when.ts +12 -2
- package/src/lib/ui/dom/withScope.ts +2 -2
- package/src/lib/ui/finalizeStreamedChildren.ts +89 -0
- package/src/lib/ui/flight.ts +56 -0
- package/src/lib/ui/html.ts +12 -1
- package/src/lib/ui/isolateCellBarrier.ts +17 -0
- package/src/lib/ui/linked.ts +48 -2
- package/src/lib/ui/remoteProxy.ts +84 -159
- package/src/lib/ui/renderChain.ts +49 -13
- package/src/lib/ui/renderToStream.ts +22 -18
- package/src/lib/ui/resumeSeedScript.ts +1 -1
- package/src/lib/ui/router.ts +63 -36
- package/src/lib/ui/runtime/AsyncCellError.ts +20 -0
- package/src/lib/ui/runtime/CELL_SEED.ts +14 -0
- package/src/lib/ui/runtime/CURRENT_BOUNDARY.ts +11 -0
- package/src/lib/ui/runtime/CURRENT_PATH.ts +29 -0
- package/src/lib/ui/runtime/RENDER.ts +10 -7
- package/src/lib/ui/runtime/RESUME.ts +4 -4
- package/src/lib/ui/runtime/STREAMED_CELLS.ts +57 -0
- package/src/lib/ui/runtime/ambientPathBacking.ts +32 -0
- package/src/lib/ui/runtime/applyPatchToTree.ts +1 -1
- package/src/lib/ui/runtime/blockId.ts +31 -0
- package/src/lib/ui/runtime/boundaryFor.ts +11 -0
- package/src/lib/ui/runtime/cellBarrierBacking.ts +30 -0
- package/src/lib/ui/runtime/createAsyncCell.ts +300 -0
- package/src/lib/ui/runtime/createDoc.ts +3 -42
- package/src/lib/ui/runtime/createEffectNode.ts +9 -0
- package/src/lib/ui/runtime/enterRenderPass.ts +5 -4
- package/src/lib/ui/runtime/flushEffects.ts +16 -6
- package/src/lib/ui/runtime/isAsyncFunction.ts +14 -0
- package/src/lib/ui/runtime/nextBlockId.ts +8 -7
- package/src/lib/ui/runtime/renderPath.ts +16 -0
- package/src/lib/ui/runtime/types/Boundary.ts +9 -0
- package/src/lib/ui/runtime/types/RenderContext.ts +9 -7
- package/src/lib/ui/runtime/types/SsrRender.ts +9 -2
- package/src/lib/ui/runtime/types/UiComponent.ts +1 -5
- package/src/lib/ui/runtime/withOptionalPath.ts +8 -0
- package/src/lib/ui/runtime/withPath.ts +16 -0
- package/src/lib/ui/runtime/withPathFrom.ts +20 -0
- package/src/lib/ui/seedStreamedResolution.ts +31 -6
- package/src/lib/ui/settleAsyncCells.ts +24 -0
- package/src/lib/ui/socketProxy.ts +1 -1
- package/src/lib/ui/startClient.ts +16 -31
- package/src/lib/ui/trackedComputed.ts +68 -0
- package/src/lib/ui/types/Scope.ts +8 -24
- package/src/lib/ui/watch.ts +3 -3
- package/src/serverEntry.ts +14 -0
- package/template/src/server/rpc/getHello.ts +15 -13
- package/template/test/app.test.ts +1 -1
- package/src/lib/server/runtime/devHotModuleResponse.ts +0 -41
- package/src/lib/shared/DEV_HOT_PREFIX.ts +0 -7
- package/src/lib/shared/UNREACHABLE_STATUSES.ts +0 -13
- package/src/lib/shared/hasReplayableRequest.ts +0 -17
- package/src/lib/shared/hydratingSlot.ts +0 -12
- package/src/lib/shared/outboxProbeSlot.ts +0 -20
- package/src/lib/shared/types/Outbox.ts +0 -9
- package/src/lib/shared/types/OutboxEntry.ts +0 -27
- package/src/lib/shared/types/SmartReadOptions.ts +0 -36
- package/src/lib/shared/wakeHydrationPeeks.ts +0 -20
- package/src/lib/ui/COMPONENT_WRAPPER_PREFIX.ts +0 -5
- package/src/lib/ui/compile/REACTIVE_CALLEES.ts +0 -11
- package/src/lib/ui/compile/assertRuntimeHelpersBound.ts +0 -80
- package/src/lib/ui/compile/markupTokens.ts +0 -313
- package/src/lib/ui/compile/structuralBlockTokens.ts +0 -100
- package/src/lib/ui/dom/applyResolved.ts +0 -87
- package/src/lib/ui/dom/mutateDocArray.ts +0 -38
- package/src/lib/ui/dom/scopeLabel.ts +0 -21
- package/src/lib/ui/dom/text.ts +0 -20
- package/src/lib/ui/history.ts +0 -108
- package/src/lib/ui/installHotBridge.ts +0 -95
- package/src/lib/ui/installInspectorBridge.ts +0 -140
- package/src/lib/ui/outbox.ts +0 -35
- package/src/lib/ui/persist.ts +0 -115
- package/src/lib/ui/rpcOutbox/createOutboxQueue.ts +0 -281
- package/src/lib/ui/rpcOutbox/outboxRegistry.ts +0 -69
- package/src/lib/ui/runtime/PATCH_BUS.ts +0 -28
- package/src/lib/ui/runtime/captureModelDoc.ts +0 -43
- package/src/lib/ui/runtime/hotInstances.ts +0 -10
- package/src/lib/ui/runtime/hotReloadEnabled.ts +0 -8
- package/src/lib/ui/runtime/hotReplace.ts +0 -38
- package/src/lib/ui/runtime/liveScopes.ts +0 -15
- package/src/lib/ui/runtime/localStoragePersistence.ts +0 -47
- package/src/lib/ui/runtime/registerHotInstance.ts +0 -23
- package/src/lib/ui/runtime/seedModelDoc.ts +0 -26
- package/src/lib/ui/runtime/types/HotInstance.ts +0 -22
- package/src/lib/ui/runtime/types/PatchEvent.ts +0 -16
- package/src/lib/ui/seedResolved.ts +0 -28
- package/src/lib/ui/sync.ts +0 -48
- package/src/lib/ui/types/History.ts +0 -14
- package/src/lib/ui/types/PersistHandle.ts +0 -11
- package/src/lib/ui/types/PersistenceStore.ts +0 -12
- package/src/lib/ui/types/ResolvedFrame.ts +0 -15
- package/src/lib/ui/types/SyncTransport.ts +0 -13
|
@@ -149,72 +149,69 @@ async function saveConfig() {
|
|
|
149
149
|
}
|
|
150
150
|
</script>
|
|
151
151
|
|
|
152
|
-
|
|
152
|
+
{#if phase === 'splash'}
|
|
153
153
|
<div class="flex min-h-screen items-center justify-center bg-gray-50 dark:bg-gray-950">
|
|
154
|
-
|
|
154
|
+
{#if logo}
|
|
155
155
|
<img src={logo} alt="" class="h-16 w-16 rounded-xl object-contain opacity-90" />
|
|
156
|
-
|
|
156
|
+
{/if}
|
|
157
157
|
</div>
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
<form class="flex flex-col gap-3" onsubmit={(event) => { event.preventDefault(); void connect() }}>
|
|
172
|
-
<input
|
|
173
|
-
type="url"
|
|
174
|
-
bind:value={url}
|
|
175
|
-
placeholder={placeholder}
|
|
176
|
-
autocomplete="url"
|
|
177
|
-
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900 focus:ring-1 focus:ring-gray-900 dark:border-gray-700 dark:bg-gray-800 dark:focus:border-gray-100 dark:focus:ring-gray-100" />
|
|
178
|
-
<button
|
|
179
|
-
type="submit"
|
|
180
|
-
class="w-full rounded-lg bg-gray-900 px-3 py-2 text-sm font-medium text-white hover:bg-gray-700 dark:bg-gray-100 dark:text-gray-900 dark:hover:bg-gray-300">
|
|
181
|
-
Connect
|
|
182
|
-
</button>
|
|
183
|
-
</form>
|
|
184
|
-
|
|
185
|
-
<div class="my-5 flex items-center gap-3 text-xs text-gray-400 dark:text-gray-500">
|
|
186
|
-
<span class="h-px flex-1 bg-gray-200 dark:bg-gray-800"></span>
|
|
187
|
-
or
|
|
188
|
-
<span class="h-px flex-1 bg-gray-200 dark:bg-gray-800"></span>
|
|
189
|
-
</div>
|
|
158
|
+
{:else}
|
|
159
|
+
<main
|
|
160
|
+
class="flex min-h-screen items-center justify-center bg-gray-50 p-6 text-gray-900 dark:bg-gray-950 dark:text-gray-100">
|
|
161
|
+
<div
|
|
162
|
+
class="w-full max-w-sm rounded-2xl bg-white p-8 shadow-sm ring-1 ring-gray-200 dark:bg-gray-900 dark:ring-gray-800">
|
|
163
|
+
{#if logo}
|
|
164
|
+
<img
|
|
165
|
+
src={logo}
|
|
166
|
+
alt=""
|
|
167
|
+
class="mx-auto mb-5 h-16 w-16 rounded-xl object-contain" />
|
|
168
|
+
{/if}
|
|
169
|
+
<h1 class="mb-6 text-center text-xl font-semibold tracking-tight">{heading}</h1>
|
|
190
170
|
|
|
171
|
+
<form class="flex flex-col gap-3" onsubmit={(event) => { event.preventDefault(); void connect() }}>
|
|
172
|
+
<input
|
|
173
|
+
type="url"
|
|
174
|
+
bind:value={url}
|
|
175
|
+
placeholder={placeholder}
|
|
176
|
+
autocomplete="url"
|
|
177
|
+
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900 focus:ring-1 focus:ring-gray-900 dark:border-gray-700 dark:bg-gray-800 dark:focus:border-gray-100 dark:focus:ring-gray-100" />
|
|
191
178
|
<button
|
|
192
|
-
type="
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
Start server
|
|
179
|
+
type="submit"
|
|
180
|
+
class="w-full rounded-lg bg-gray-900 px-3 py-2 text-sm font-medium text-white hover:bg-gray-700 dark:bg-gray-100 dark:text-gray-900 dark:hover:bg-gray-300">
|
|
181
|
+
Connect
|
|
196
182
|
</button>
|
|
183
|
+
</form>
|
|
197
184
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
</template>
|
|
203
|
-
|
|
204
|
-
<p class="mt-8 text-center text-xs text-gray-400 dark:text-gray-500">
|
|
205
|
-
made with
|
|
206
|
-
<a
|
|
207
|
-
href="https://github.com/briancray/abide"
|
|
208
|
-
class="underline hover:text-gray-600 dark:hover:text-gray-300"
|
|
209
|
-
>abide</a
|
|
210
|
-
>
|
|
211
|
-
</p>
|
|
185
|
+
<div class="my-5 flex items-center gap-3 text-xs text-gray-400 dark:text-gray-500">
|
|
186
|
+
<span class="h-px flex-1 bg-gray-200 dark:bg-gray-800"></span>
|
|
187
|
+
or
|
|
188
|
+
<span class="h-px flex-1 bg-gray-200 dark:bg-gray-800"></span>
|
|
212
189
|
</div>
|
|
213
|
-
</main>
|
|
214
|
-
</template>
|
|
215
|
-
</template>
|
|
216
190
|
|
|
217
|
-
<
|
|
191
|
+
<button
|
|
192
|
+
type="button"
|
|
193
|
+
onclick={() => void start()}
|
|
194
|
+
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm font-medium hover:bg-gray-50 dark:border-gray-700 dark:hover:bg-gray-800">
|
|
195
|
+
Start server
|
|
196
|
+
</button>
|
|
197
|
+
|
|
198
|
+
{#if error}
|
|
199
|
+
<p class="mt-4 text-center text-sm text-red-600 dark:text-red-400">{error}</p>
|
|
200
|
+
{/if}
|
|
201
|
+
|
|
202
|
+
<p class="mt-8 text-center text-xs text-gray-400 dark:text-gray-500">
|
|
203
|
+
made with
|
|
204
|
+
<a
|
|
205
|
+
href="https://github.com/briancray/abide"
|
|
206
|
+
class="underline hover:text-gray-600 dark:hover:text-gray-300"
|
|
207
|
+
>abide</a
|
|
208
|
+
>
|
|
209
|
+
</p>
|
|
210
|
+
</div>
|
|
211
|
+
</main>
|
|
212
|
+
{/if}
|
|
213
|
+
|
|
214
|
+
{#if showConfig}
|
|
218
215
|
<div
|
|
219
216
|
class="fixed inset-0 z-10 flex items-center justify-center bg-black/40 p-6 text-gray-900 dark:text-gray-100">
|
|
220
217
|
<div
|
|
@@ -222,29 +219,28 @@ async function saveConfig() {
|
|
|
222
219
|
<h2 class="mb-5 text-lg font-semibold tracking-tight">Set up {heading}</h2>
|
|
223
220
|
|
|
224
221
|
<form class="flex flex-col gap-4" onsubmit={(event) => { event.preventDefault(); void saveConfig() }}>
|
|
225
|
-
|
|
222
|
+
{#for field of configFields by field.key}
|
|
226
223
|
<label class="flex flex-col gap-1 text-sm">
|
|
227
224
|
<span class="font-medium">{field.label}</span>
|
|
228
|
-
|
|
225
|
+
{#if field.inputType === 'checkbox'}
|
|
229
226
|
<input
|
|
230
227
|
type="checkbox"
|
|
231
228
|
onchange={(event) => { configValues[field.key] = event.currentTarget.checked ? 'true' : 'false' }}
|
|
232
229
|
class="mt-1 size-4 self-start rounded border-gray-300 dark:border-gray-700" />
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
<template if={field.description}>
|
|
230
|
+
{:else}
|
|
231
|
+
<input
|
|
232
|
+
type={field.inputType}
|
|
233
|
+
value={configValues[field.key]}
|
|
234
|
+
oninput={(event) => { configValues[field.key] = event.currentTarget.value }}
|
|
235
|
+
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900 focus:ring-1 focus:ring-gray-900 dark:border-gray-700 dark:bg-gray-800 dark:focus:border-gray-100 dark:focus:ring-gray-100" />
|
|
236
|
+
{/if}
|
|
237
|
+
{#if field.description}
|
|
242
238
|
<span class="text-xs text-gray-400 dark:text-gray-500"
|
|
243
239
|
>{field.description}</span
|
|
244
240
|
>
|
|
245
|
-
|
|
241
|
+
{/if}
|
|
246
242
|
</label>
|
|
247
|
-
|
|
243
|
+
{/for}
|
|
248
244
|
|
|
249
245
|
<div class="mt-1 flex gap-3">
|
|
250
246
|
<button
|
|
@@ -261,9 +257,9 @@ async function saveConfig() {
|
|
|
261
257
|
</div>
|
|
262
258
|
</form>
|
|
263
259
|
|
|
264
|
-
|
|
260
|
+
{#if error}
|
|
265
261
|
<p class="mt-4 text-center text-sm text-red-600 dark:text-red-400">{error}</p>
|
|
266
|
-
|
|
262
|
+
{/if}
|
|
267
263
|
</div>
|
|
268
264
|
</div>
|
|
269
|
-
|
|
265
|
+
{/if}
|
|
@@ -15,9 +15,15 @@ export function infoPlist({
|
|
|
15
15
|
version: string
|
|
16
16
|
icon?: string
|
|
17
17
|
}): string {
|
|
18
|
+
/* Interpolated values ride inside plist `<string>` elements, so any `&`/`<`/`>` in a
|
|
19
|
+
project name would otherwise emit malformed XML that codesign/Gatekeeper reject. */
|
|
20
|
+
const escapeXml = (value: string): string =>
|
|
21
|
+
value.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>')
|
|
22
|
+
const safeName = escapeXml(name)
|
|
23
|
+
const safeVersion = escapeXml(version)
|
|
18
24
|
const iconEntry = icon
|
|
19
25
|
? ` <key>CFBundleIconFile</key>
|
|
20
|
-
<string>${icon}</string>
|
|
26
|
+
<string>${escapeXml(icon)}</string>
|
|
21
27
|
`
|
|
22
28
|
: ''
|
|
23
29
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
@@ -25,17 +31,17 @@ export function infoPlist({
|
|
|
25
31
|
<plist version="1.0">
|
|
26
32
|
<dict>
|
|
27
33
|
<key>CFBundleName</key>
|
|
28
|
-
<string>${
|
|
34
|
+
<string>${safeName}</string>
|
|
29
35
|
<key>CFBundleDisplayName</key>
|
|
30
|
-
<string>${
|
|
36
|
+
<string>${safeName}</string>
|
|
31
37
|
<key>CFBundleExecutable</key>
|
|
32
|
-
<string>${
|
|
38
|
+
<string>${safeName}</string>
|
|
33
39
|
<key>CFBundleIdentifier</key>
|
|
34
|
-
<string>com.abide.${
|
|
40
|
+
<string>com.abide.${safeName}</string>
|
|
35
41
|
<key>CFBundleVersion</key>
|
|
36
|
-
<string>${
|
|
42
|
+
<string>${safeVersion}</string>
|
|
37
43
|
<key>CFBundleShortVersionString</key>
|
|
38
|
-
<string>${
|
|
44
|
+
<string>${safeVersion}</string>
|
|
39
45
|
${iconEntry} <key>CFBundlePackageType</key>
|
|
40
46
|
<string>APPL</string>
|
|
41
47
|
<key>NSHighResolutionCapable</key>
|
|
@@ -53,10 +53,19 @@ export async function spawnEmbeddedServer({
|
|
|
53
53
|
env: { ...process.env, PORT: String(port), ABIDE_PARENT_PID: String(process.pid) },
|
|
54
54
|
stdio: ['inherit', 'inherit', 'inherit'],
|
|
55
55
|
})
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
let outcome: number | undefined
|
|
57
|
+
try {
|
|
58
|
+
outcome = await Promise.race([
|
|
59
|
+
waitForServer(url, timeoutMs ? { timeoutMs } : undefined).then(() => undefined),
|
|
60
|
+
child.exited,
|
|
61
|
+
])
|
|
62
|
+
} catch (error) {
|
|
63
|
+
/* Readiness timed out (waitForServer threw) — reap the child we spawned so it doesn't
|
|
64
|
+
orphan and hold its fixed PORT, which would then fail the next spawn's bind. The caller
|
|
65
|
+
only owns the child once we successfully return it. */
|
|
66
|
+
child.kill()
|
|
67
|
+
throw error
|
|
68
|
+
}
|
|
60
69
|
if (outcome !== undefined) {
|
|
61
70
|
throw new Error(`[abide] embedded server exited (code ${outcome}) before binding`)
|
|
62
71
|
}
|
|
@@ -13,7 +13,12 @@ export async function waitForServer(
|
|
|
13
13
|
const deadline = Bun.nanoseconds() + timeoutMs * 1e6
|
|
14
14
|
while (Bun.nanoseconds() < deadline) {
|
|
15
15
|
try {
|
|
16
|
-
|
|
16
|
+
/* Bound each probe by the time left to the deadline: a connection that is accepted but
|
|
17
|
+
stalls its HTTP response leaves a bare `fetch(url)` pending forever (it never rejects),
|
|
18
|
+
which would hang the loop past its own timeout. The abort caps a single hung probe at
|
|
19
|
+
the remaining budget so the deadline is always honored. */
|
|
20
|
+
const remainingMs = Math.max(0, (deadline - Bun.nanoseconds()) / 1e6)
|
|
21
|
+
await fetch(url, { signal: AbortSignal.timeout(remainingMs) })
|
|
17
22
|
return
|
|
18
23
|
} catch {
|
|
19
24
|
await Bun.sleep(intervalMs)
|
package/src/lib/mcp/mcpTools.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { dispatchRpcInProcess } from '../server/rpc/dispatchRpcInProcess.ts'
|
|
2
|
+
import {
|
|
3
|
+
resolveInputJsonSchema,
|
|
4
|
+
resolveOutputJsonSchema,
|
|
5
|
+
} from '../server/rpc/resolveRpcJsonSchema.ts'
|
|
2
6
|
import { rpcRegistry } from '../server/rpc/rpcRegistry.ts'
|
|
3
7
|
import type { RpcRegistryEntry } from '../server/rpc/types/RpcRegistryEntry.ts'
|
|
4
8
|
import { socketOperations } from '../server/sockets/socketOperations.ts'
|
|
@@ -37,7 +41,7 @@ RPCs enumerate first, so on a name collision the rpc tool wins.
|
|
|
37
41
|
function mcpToolRefs(): McpToolRef[] {
|
|
38
42
|
const refs: McpToolRef[] = []
|
|
39
43
|
for (const entry of rpcRegistry.values()) {
|
|
40
|
-
if (!entry.clients.mcp) {
|
|
44
|
+
if (!entry.remote.clients.mcp) {
|
|
41
45
|
continue
|
|
42
46
|
}
|
|
43
47
|
refs.push({ kind: 'rpc', name: commandNameForUrl(entry.remote.url), entry })
|
|
@@ -63,7 +67,9 @@ from a write.
|
|
|
63
67
|
*/
|
|
64
68
|
function describeTool(ref: McpToolRef): ToolDescriptor {
|
|
65
69
|
if (ref.kind === 'rpc') {
|
|
66
|
-
|
|
70
|
+
// The declared inputSchema VALIDATOR overrides the build-projected input-type schema
|
|
71
|
+
// (ADR-0030 input side); with neither the tool advertises the opaque fallback, as before.
|
|
72
|
+
const inputSchema = resolveInputJsonSchema(ref.entry) ?? jsonSchemaForSchema(undefined)
|
|
67
73
|
const tool: ToolDescriptor = {
|
|
68
74
|
name: ref.name,
|
|
69
75
|
description:
|
|
@@ -72,8 +78,11 @@ function describeTool(ref: McpToolRef): ToolDescriptor {
|
|
|
72
78
|
inputSchema,
|
|
73
79
|
annotations: annotationsForMethod(ref.entry.remote.method),
|
|
74
80
|
}
|
|
75
|
-
|
|
76
|
-
|
|
81
|
+
// The declared outputSchema VALIDATOR overrides the build-projected return-type schema
|
|
82
|
+
// (ADR-0030 D2); with neither the tool advertises no outputSchema, exactly as before.
|
|
83
|
+
const outputSchema = resolveOutputJsonSchema(ref.entry)
|
|
84
|
+
if (outputSchema) {
|
|
85
|
+
tool.outputSchema = outputSchema
|
|
77
86
|
}
|
|
78
87
|
return tool
|
|
79
88
|
}
|
|
@@ -149,8 +158,8 @@ function callSocketTool(
|
|
|
149
158
|
}
|
|
150
159
|
}
|
|
151
160
|
try {
|
|
152
|
-
//
|
|
153
|
-
entry.socket.
|
|
161
|
+
// publish() validates the payload against the socket schema and throws on failure.
|
|
162
|
+
entry.socket.publish(args)
|
|
154
163
|
} catch (error) {
|
|
155
164
|
return textResult(messageFromError(error), true)
|
|
156
165
|
}
|
package/src/lib/server/error.ts
CHANGED
|
@@ -93,15 +93,15 @@ expose the error on `rpc.isError(e, 'name')` (`.kind` and typed `.data`). No
|
|
|
93
93
|
(a const can't read its own variable name); `schema` types `.data` and is never
|
|
94
94
|
validated at runtime here.
|
|
95
95
|
*/
|
|
96
|
-
function typed<Name extends string, Schema extends StandardSchemaV1>(
|
|
96
|
+
function typed<Name extends string, Status extends number, Schema extends StandardSchemaV1>(
|
|
97
97
|
name: Name,
|
|
98
|
-
status:
|
|
98
|
+
status: Status,
|
|
99
99
|
schema: Schema,
|
|
100
|
-
): (data: StandardSchemaV1.InferInput<Schema>) => TypedError<Name, { status:
|
|
101
|
-
function typed<Name extends string>(
|
|
100
|
+
): (data: StandardSchemaV1.InferInput<Schema>) => TypedError<Name, { status: Status; data: Schema }>
|
|
101
|
+
function typed<Name extends string, Status extends number>(
|
|
102
102
|
name: Name,
|
|
103
|
-
status:
|
|
104
|
-
): () => TypedError<Name, { status:
|
|
103
|
+
status: Status,
|
|
104
|
+
): () => TypedError<Name, { status: Status; data?: undefined }>
|
|
105
105
|
function typed(name: string, status: number, _schema?: StandardSchemaV1) {
|
|
106
106
|
return (data?: unknown) => typedErrorResponse(name, status, data)
|
|
107
107
|
}
|
package/src/lib/server/json.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { NO_STORE } from '../shared/CACHE_CONTROL_VALUES.ts'
|
|
2
|
+
import { encodeWireBody } from '../shared/encodeWireBody.ts'
|
|
2
3
|
import type { TypedResponse } from './rpc/types/TypedResponse.ts'
|
|
3
4
|
import { withResponseDefaults } from './runtime/withResponseDefaults.ts'
|
|
4
5
|
|
|
6
|
+
/* The Content-Type `Response.json` sets — replicated here because the wire-encode step serializes
|
|
7
|
+
with a replacer, so the body is built by hand rather than through `Response.json`. Seeds the
|
|
8
|
+
default header set so an explicit caller `content-type` still wins. */
|
|
9
|
+
const JSON_CONTENT_TYPE = 'application/json;charset=utf-8'
|
|
10
|
+
|
|
5
11
|
/*
|
|
6
12
|
JSON Response with rpc-friendly defaults — same shape as
|
|
7
13
|
`Response.json(data, init)`, except `Cache-Control: no-store` is set
|
|
@@ -36,8 +42,16 @@ export function json<T>(data: T, init?: ResponseInit): TypedResponse<T> {
|
|
|
36
42
|
withResponseDefaults(init, { 'Cache-Control': NO_STORE }, 204),
|
|
37
43
|
) as TypedResponse<T>
|
|
38
44
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
45
|
+
/* Wire-encode the body (ADR-0029 output path) through the shared honest-JSON encoder: a
|
|
46
|
+
value-directed replacer rewrites a `Set` → array, a `Map` → `[K,V]` entries, and a `bigint`
|
|
47
|
+
→ digit string, so a structured return crosses as honest JSON rather than a lost `{}` or a
|
|
48
|
+
500 (plain `Response.json` throws on a bigint). A `Date` already rides as an ISO string via
|
|
49
|
+
its native `toJSON`. */
|
|
50
|
+
return new Response(
|
|
51
|
+
encodeWireBody(data),
|
|
52
|
+
withResponseDefaults(init, {
|
|
53
|
+
'Cache-Control': NO_STORE,
|
|
54
|
+
'Content-Type': JSON_CONTENT_TYPE,
|
|
55
|
+
}),
|
|
42
56
|
) as TypedResponse<T>
|
|
43
57
|
}
|
|
@@ -4,10 +4,14 @@ import { createRemoteFunction } from '../../shared/createRemoteFunction.ts'
|
|
|
4
4
|
import { forwardHeaders } from '../../shared/forwardHeaders.ts'
|
|
5
5
|
import { isReadOnlyMethod } from '../../shared/isReadOnlyMethod.ts'
|
|
6
6
|
import { resolveClientFlags } from '../../shared/resolveClientFlags.ts'
|
|
7
|
+
import type { CachePolicy } from '../../shared/types/CachePolicy.ts'
|
|
7
8
|
import type { ClientFlags } from '../../shared/types/ClientFlags.ts'
|
|
9
|
+
import type { ErrorJsonSchemas } from '../../shared/types/ErrorJsonSchemas.ts'
|
|
8
10
|
import type { HttpMethod } from '../../shared/types/HttpMethod.ts'
|
|
11
|
+
import type { InputCoercion } from '../../shared/types/InputCoercion.ts'
|
|
9
12
|
import type { RemoteFunction } from '../../shared/types/RemoteFunction.ts'
|
|
10
13
|
import type { StandardSchemaV1 } from '../../shared/types/StandardSchemaV1.ts'
|
|
14
|
+
import type { StreamPolicy } from '../../shared/types/StreamPolicy.ts'
|
|
11
15
|
import { requestContext } from '../runtime/requestContext.ts'
|
|
12
16
|
import { parseArgs } from './parseArgs.ts'
|
|
13
17
|
import { registerRpc } from './registerRpc.ts'
|
|
@@ -50,38 +54,57 @@ export function defineRpc<Args, Return>(
|
|
|
50
54
|
url: string,
|
|
51
55
|
handler: RemoteHandler<Args, Return>,
|
|
52
56
|
opts?: {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
/* Namespaced schemas (ADR-0020): `input` types + validates args, `output` is the
|
|
58
|
+
success-body schema (OpenAPI/MCP), `files` validates multipart File parts. */
|
|
59
|
+
schemas?: {
|
|
60
|
+
input?: StandardSchemaV1
|
|
61
|
+
output?: StandardSchemaV1
|
|
62
|
+
files?: StandardSchemaV1
|
|
63
|
+
}
|
|
64
|
+
/* Surface-exposure flags (browser/mcp/cli) — which surfaces advertise this rpc. */
|
|
56
65
|
clients?: Partial<ClientFlags>
|
|
57
66
|
crossOrigin?: boolean
|
|
58
67
|
/* Per-rpc cap on actual received body bytes (413 past it); omitted = Bun's server-wide maxRequestBodySize. */
|
|
59
68
|
maxBodySize?: number
|
|
60
69
|
/* Per-rpc handler deadline (ms): a 504 once exceeded, on every surface (SSR/MCP/CLI/network). */
|
|
61
70
|
timeout?: number
|
|
62
|
-
/*
|
|
63
|
-
the client proxy parks the request for replay instead of just throwing. The
|
|
64
|
-
parked write drains on `rpc.outbox.retry()` (no auto-drain). Mutating methods
|
|
65
|
-
only. */
|
|
66
|
-
outbox?: boolean
|
|
67
|
-
/* Handler returns jsonl()/sse(): the bare call returns the Subscribable directly (for
|
|
71
|
+
/* Handler returns jsonl()/sse(): the bare call returns the NamedAsyncIterable directly (for
|
|
68
72
|
isomorphic `for await (… of fn(args))` in server code). Bundler-stamped; the router's
|
|
69
73
|
wire path (.fetch) is unaffected. */
|
|
70
74
|
streaming?: boolean
|
|
75
|
+
/* Numeric/boolean input fields → parseArgs coerces a string query/form value into the
|
|
76
|
+
typed value the input schema expects (ADR-0028). Bundler-stamped from the endpoint's
|
|
77
|
+
`Args` type; absent on the fail-open path (a GET field then stays a string as before). */
|
|
78
|
+
coerce?: InputCoercion
|
|
79
|
+
/* The handler's input args projected to JSON Schema (ADR-0030 input side). Bundler-stamped
|
|
80
|
+
from the endpoint's input-parameter type; feeds the OpenAPI parameters/body / MCP inputSchema
|
|
81
|
+
/ inspector input surface when no `schemas.input` validator is declared (which still
|
|
82
|
+
overrides it), and makes the endpoint advertisable to MCP/CLI. A SHAPE description only —
|
|
83
|
+
never runtime-validated, so it can't produce a 422. Absent on the fail-open path — the
|
|
84
|
+
surface then omits the input schema exactly as before. */
|
|
85
|
+
inputJsonSchema?: Record<string, unknown>
|
|
86
|
+
/* The handler's return type projected to JSON Schema (ADR-0030 D2). Bundler-stamped from the
|
|
87
|
+
endpoint's success-body type; feeds the OpenAPI 200 / MCP outputSchema / inspector surface
|
|
88
|
+
when no `schemas.output` validator is declared (which still overrides it). Absent on the
|
|
89
|
+
fail-open path — the surface then omits the response schema exactly as before. */
|
|
90
|
+
outputJsonSchema?: Record<string, unknown>
|
|
91
|
+
/* The handler's typed-error branches as a status-keyed JSON-Schema map (ADR-0030). Bundler-
|
|
92
|
+
stamped from the endpoint's `error.typed(...)` return branches; feeds the OpenAPI
|
|
93
|
+
`responses[status]` surface so each typed error's status + data payload is documented
|
|
94
|
+
alongside the 200. Absent on the fail-open path — the surface then omits the error
|
|
95
|
+
responses exactly as before. */
|
|
96
|
+
errorJsonSchemas?: ErrorJsonSchemas
|
|
97
|
+
/* Endpoint cache policy (ADR-0020) — read helpers only; readThrough's bottom layer. */
|
|
98
|
+
cache?: CachePolicy<Args>
|
|
99
|
+
/* Endpoint stream policy (ADR-0020) — streaming read helpers only; replay depth `n`. */
|
|
100
|
+
stream?: StreamPolicy
|
|
71
101
|
},
|
|
72
102
|
): RemoteFunction<Args, Return> {
|
|
73
|
-
/* `outbox: true` is a mutation contract — a read RPC has nothing to durably deliver,
|
|
74
|
-
so reject it at declaration rather than silently ignore. The server handler itself
|
|
75
|
-
is unaffected; durability is a client-proxy concern. */
|
|
76
|
-
if (opts?.outbox === true && isReadOnlyMethod(method)) {
|
|
77
|
-
throw new Error(
|
|
78
|
-
`[abide] outbox: true is only valid on mutating RPCs (POST/PUT/PATCH/DELETE), not ${method}`,
|
|
79
|
-
)
|
|
80
|
-
}
|
|
81
103
|
const timeout = opts?.timeout
|
|
82
|
-
const inputSchema = opts?.
|
|
83
|
-
const
|
|
84
|
-
const
|
|
104
|
+
const inputSchema = opts?.schemas?.input
|
|
105
|
+
const inputJsonSchema = opts?.inputJsonSchema
|
|
106
|
+
const outputSchema = opts?.schemas?.output
|
|
107
|
+
const filesSchema = opts?.schemas?.files
|
|
85
108
|
/*
|
|
86
109
|
An input schema makes the handler safe to advertise to non-browser
|
|
87
110
|
surfaces. CLI flips on for any rpc with one (a human/script invokes it
|
|
@@ -89,8 +112,16 @@ export function defineRpc<Args, Return>(
|
|
|
89
112
|
model shouldn't be able to mutate/delete just because the handler
|
|
90
113
|
carries a schema, so mutating rpcs require an explicit clients.mcp.
|
|
91
114
|
Explicit `clients` always wins.
|
|
115
|
+
|
|
116
|
+
A build-projected `inputJsonSchema` (ADR-0030 input side — the handler's
|
|
117
|
+
input parameter type projected to JSON Schema, present only when the type
|
|
118
|
+
resolved cleanly) counts as a machine-advertisable contract too, so a
|
|
119
|
+
plainly-typed handler auto-exposes without a hand-written `schemas.input`.
|
|
120
|
+
This is SHAPE-only: the projection describes the input, it is NEVER run as
|
|
121
|
+
runtime validation (no 422) — declaring `schemas.input` is still what adds
|
|
122
|
+
the runtime narrowing.
|
|
92
123
|
*/
|
|
93
|
-
const hasSchema = inputSchema !== undefined
|
|
124
|
+
const hasSchema = inputSchema !== undefined || inputJsonSchema !== undefined
|
|
94
125
|
const clients = resolveClientFlags(opts?.clients, {
|
|
95
126
|
mcp: hasSchema && isReadOnlyMethod(method),
|
|
96
127
|
cli: hasSchema,
|
|
@@ -189,10 +220,12 @@ export function defineRpc<Args, Return>(
|
|
|
189
220
|
clients,
|
|
190
221
|
streaming: opts?.streaming ?? false,
|
|
191
222
|
crossOrigin: opts?.crossOrigin,
|
|
223
|
+
cache: opts?.cache,
|
|
224
|
+
stream: opts?.stream,
|
|
192
225
|
buildRequest,
|
|
193
226
|
invoke,
|
|
194
227
|
parseArgsForFetch: async (request) => {
|
|
195
|
-
const args = await parseArgs(method, request, opts?.maxBodySize)
|
|
228
|
+
const args = await parseArgs(method, request, opts?.maxBodySize, opts?.coerce)
|
|
196
229
|
/*
|
|
197
230
|
Compose this rpc's deadline into request().signal so a handler's
|
|
198
231
|
fetch(ext, { signal: request().signal }) is cancelled when the
|
|
@@ -225,12 +258,13 @@ export function defineRpc<Args, Return>(
|
|
|
225
258
|
registerRpc({
|
|
226
259
|
remote: remote as RemoteFunction<unknown, unknown>,
|
|
227
260
|
inputSchema,
|
|
261
|
+
inputJsonSchema,
|
|
228
262
|
outputSchema,
|
|
263
|
+
outputJsonSchema: opts?.outputJsonSchema,
|
|
264
|
+
errorJsonSchemas: opts?.errorJsonSchemas,
|
|
229
265
|
filesSchema,
|
|
230
|
-
clients,
|
|
231
266
|
timeout,
|
|
232
267
|
maxBodySize: opts?.maxBodySize,
|
|
233
|
-
crossOrigin: opts?.crossOrigin,
|
|
234
268
|
})
|
|
235
269
|
return remote
|
|
236
270
|
}
|