@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
|
@@ -1,30 +1,32 @@
|
|
|
1
1
|
// node:fs existsSync — Bun plugin onResolve is sync-only; Bun.file().exists() is async
|
|
2
2
|
import { existsSync, statSync } from 'node:fs'
|
|
3
|
-
import { dirname, join } from 'node:path'
|
|
4
3
|
import type { BunPlugin } from 'bun'
|
|
5
4
|
import { Glob } from 'bun'
|
|
6
5
|
import { abideImportName } from './lib/shared/abideImportName.ts'
|
|
7
6
|
import { abideLog } from './lib/shared/abideLog.ts'
|
|
7
|
+
import { bundleGraphFromMetafile } from './lib/shared/bundleGraphFromMetafile.ts'
|
|
8
|
+
import type { RpcServerProgram } from './lib/shared/createRpcServerProgram.ts'
|
|
8
9
|
import { escapeRegex } from './lib/shared/escapeRegex.ts'
|
|
9
|
-
import { fileName } from './lib/shared/fileName.ts'
|
|
10
10
|
import { fileStem } from './lib/shared/fileStem.ts'
|
|
11
11
|
import { jsonSchemaForPromptArguments } from './lib/shared/jsonSchemaForPromptArguments.ts'
|
|
12
12
|
import { manifestModule } from './lib/shared/manifestModule.ts'
|
|
13
|
+
import { PROXIED_SERVER_SUBDIRS } from './lib/shared/PROXIED_SERVER_SUBDIRS.ts'
|
|
13
14
|
import { pageUrlForFile } from './lib/shared/pageUrlForFile.ts'
|
|
14
15
|
import { parsePromptMarkdown } from './lib/shared/parsePromptMarkdown.ts'
|
|
15
16
|
import { prepareRpcModule } from './lib/shared/prepareRpcModule.ts'
|
|
16
17
|
import { prepareSocketModule } from './lib/shared/prepareSocketModule.ts'
|
|
17
18
|
import { programNameForPackage } from './lib/shared/programNameForPackage.ts'
|
|
18
19
|
import { promptNameForFile } from './lib/shared/promptNameForFile.ts'
|
|
20
|
+
import {
|
|
21
|
+
DEFINE_RPC_GLOBAL,
|
|
22
|
+
DEFINE_SOCKET_GLOBAL,
|
|
23
|
+
REMOTE_PROXY_GLOBAL,
|
|
24
|
+
} from './lib/shared/RPC_SHIM_GLOBALS.ts'
|
|
19
25
|
import { readPackageJson } from './lib/shared/readPackageJson.ts'
|
|
26
|
+
import { rpcServerForRoot } from './lib/shared/rpcServerForRoot.ts'
|
|
20
27
|
import { rpcUrlForFile } from './lib/shared/rpcUrlForFile.ts'
|
|
28
|
+
import { scanPages } from './lib/shared/scanPages.ts'
|
|
21
29
|
import { socketNameForFile } from './lib/shared/socketNameForFile.ts'
|
|
22
|
-
import { writeHealthDts } from './lib/shared/writeHealthDts.ts'
|
|
23
|
-
import { writePublicAssetsDts } from './lib/shared/writePublicAssetsDts.ts'
|
|
24
|
-
import { writeRoutesDts } from './lib/shared/writeRoutesDts.ts'
|
|
25
|
-
import { writeRpcDts } from './lib/shared/writeRpcDts.ts'
|
|
26
|
-
import { writeTestRpcDts } from './lib/shared/writeTestRpcDts.ts'
|
|
27
|
-
import { writeTestSocketsDts } from './lib/shared/writeTestSocketsDts.ts'
|
|
28
30
|
|
|
29
31
|
/*
|
|
30
32
|
Resolves a bare directory or extensionless path to a concrete file. Mirrors
|
|
@@ -68,6 +70,13 @@ function resolveExtensionUncached(path: string): string {
|
|
|
68
70
|
|
|
69
71
|
const NS = 'abide-virtual'
|
|
70
72
|
|
|
73
|
+
/* Per-input source-byte budget for the client bundle-hygiene diagnostic (ADR-0031 D2): a single
|
|
74
|
+
project module that SURVIVES tree-shaking into the client bundle heavier than this earns a
|
|
75
|
+
non-blocking build warning, so an accidentally-huge module (an inlined dataset, a fat vendored
|
|
76
|
+
dep pulled into src) is observable without a new bundler pass. Never fails the build — the only
|
|
77
|
+
hard onEnd failure stays the real side-crossing violation. */
|
|
78
|
+
const CLIENT_BUNDLE_INPUT_BUDGET_BYTES = 512 * 1024
|
|
79
|
+
|
|
71
80
|
/* Memoises a zero-arg async producer so repeat calls reuse the first in-flight promise. */
|
|
72
81
|
function once<T>(produce: () => Promise<T>): () => Promise<T> {
|
|
73
82
|
let promise: Promise<T> | undefined
|
|
@@ -144,57 +153,19 @@ export function abideResolverPlugin({
|
|
|
144
153
|
re-globbing the trees. The shell read is memoised the same way so two
|
|
145
154
|
passes don't re-read app.html from disk.
|
|
146
155
|
*/
|
|
147
|
-
const scanPagesOnce = once(() =>
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
cwd,
|
|
151
|
-
pageFiles: scan.pageFiles,
|
|
152
|
-
importName: await abideImportNameOnce(),
|
|
153
|
-
})
|
|
154
|
-
return scan
|
|
155
|
-
}),
|
|
156
|
-
)
|
|
157
|
-
const scanRpcOnce = once(() =>
|
|
158
|
-
scanDir(rpcDir, '**/*.ts').then(async (rpcFiles) => {
|
|
159
|
-
const importName = await abideImportNameOnce()
|
|
160
|
-
await writeRpcDts({ cwd, rpcDir, rpcFiles, importName })
|
|
161
|
-
/* Typed createTestApp `app.rpc.<rpc>` surface. */
|
|
162
|
-
await writeTestRpcDts({ cwd, rpcFiles, importName })
|
|
163
|
-
return rpcFiles
|
|
164
|
-
}),
|
|
165
|
-
)
|
|
166
|
-
const scanSocketsOnce = once(() =>
|
|
167
|
-
scanDir(socketsDir, '**/*.ts').then(async (socketFiles) => {
|
|
168
|
-
/* Typed createTestApp `app.sockets.<name>` surface. */
|
|
169
|
-
await writeTestSocketsDts({
|
|
170
|
-
cwd,
|
|
171
|
-
socketFiles,
|
|
172
|
-
importName: await abideImportNameOnce(),
|
|
173
|
-
})
|
|
174
|
-
return socketFiles
|
|
175
|
-
}),
|
|
176
|
-
)
|
|
177
|
-
/* One write per build, from the abide:app loader (the seam that already knows whether src/app.ts exists). */
|
|
178
|
-
let healthDtsWritten: Promise<void> | undefined
|
|
179
|
-
const writeHealthDtsOnce = (hasAppModule: boolean): Promise<void> => {
|
|
180
|
-
healthDtsWritten ??= abideImportNameOnce().then((importName) =>
|
|
181
|
-
writeHealthDts({ cwd, hasAppModule, importName }),
|
|
182
|
-
)
|
|
183
|
-
return healthDtsWritten
|
|
184
|
-
}
|
|
156
|
+
const scanPagesOnce = once(() => scanPages(pagesDir))
|
|
157
|
+
const scanRpcOnce = once(() => scanDir(rpcDir, '**/*.ts'))
|
|
158
|
+
const scanSocketsOnce = once(() => scanDir(socketsDir, '**/*.ts'))
|
|
185
159
|
/*
|
|
186
|
-
Globs public/ once per build
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
the returned list for its embed.
|
|
160
|
+
Globs public/ once per build; the public-assets virtual reuses the returned
|
|
161
|
+
list for its embed. (.d.ts codegen — publicAssets.d.ts and its siblings —
|
|
162
|
+
moved to generateDeclarations, owned by build().)
|
|
190
163
|
*/
|
|
191
|
-
const scanPublicOnce = once(async () =>
|
|
192
|
-
|
|
164
|
+
const scanPublicOnce = once(async () =>
|
|
165
|
+
existsSync(publicDir)
|
|
193
166
|
? await Array.fromAsync(new Glob('**/*').scan({ cwd: publicDir, onlyFiles: true }))
|
|
194
|
-
: []
|
|
195
|
-
|
|
196
|
-
return publicFiles
|
|
197
|
-
})
|
|
167
|
+
: [],
|
|
168
|
+
)
|
|
198
169
|
const scanPromptsOnce = once(() => scanDir(promptsDir, '**/*.md'))
|
|
199
170
|
const loadShellOnce = once(() => loadShell(cwd))
|
|
200
171
|
/* Project package.json read once per build — three virtuals (cli-name,
|
|
@@ -206,53 +177,46 @@ export function abideResolverPlugin({
|
|
|
206
177
|
const promptsFilter = new RegExp(`^${escapeRegex(promptsDir)}/.*\\.md$`)
|
|
207
178
|
|
|
208
179
|
/*
|
|
209
|
-
Side-crossing guard (client target only). The client bundle must never
|
|
210
|
-
|
|
211
|
-
`$server/
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
180
|
+
Side-crossing guard (client target only). The client bundle must never ship server-only
|
|
181
|
+
code to the browser. A registered rpc/socket is the carve-out — `$server/rpc/*` and
|
|
182
|
+
`$server/sockets/*` are replaced with remoteProxy/socketProxy stubs by the onLoad hooks —
|
|
183
|
+
so a violation is a SURVIVING module under src/server/ that isn't one of those, or the
|
|
184
|
+
public `abide/server/*` names.
|
|
185
|
+
|
|
186
|
+
ADR-0022 D3 makes the project-server edge REACHABILITY-based rather than
|
|
187
|
+
presence-at-resolve: the D2 client rpc transform keeps the real module (handler elided),
|
|
188
|
+
so the elided handler's now-dead `$server/*` / `abide/server/*` imports are textually
|
|
189
|
+
present until tree-shaking removes them. A resolve-time throw would false-positive on
|
|
190
|
+
those. So the authority is a post-bundle `build.onEnd` pass that walks `metafile.inputs`
|
|
191
|
+
(the DCE-accurate graph) and flags any server-only module that SURVIVED. The one guard
|
|
192
|
+
that still fires at resolve is the public `abide/server/*` names reaching a genuine client
|
|
193
|
+
module — those live in node_modules, outside `serverDir`, so the metafile classifier can't
|
|
194
|
+
see them; the kept rpc module (proxied) is exempted so its dead handler imports don't
|
|
195
|
+
reject before DCE.
|
|
216
196
|
*/
|
|
217
|
-
|
|
197
|
+
/* Absolute proxied-server dirs, derived from the shared PROXIED_SERVER_SUBDIRS authority so this
|
|
198
|
+
resolver and the dev orchestrator's changeAffectsClient classify the same set — adding a
|
|
199
|
+
proxied dir is one edit there, not a silent lockstep across both. */
|
|
200
|
+
const proxiedServerDirPrefixes = PROXIED_SERVER_SUBDIRS.map(
|
|
201
|
+
(subdir) => `${serverDir}/${subdir}/`,
|
|
202
|
+
)
|
|
218
203
|
const isProxiedServerModule = (path: string): boolean =>
|
|
219
|
-
|
|
204
|
+
proxiedServerDirPrefixes.some((prefix) => path.startsWith(prefix))
|
|
220
205
|
const isServerOnlyModule = (path: string): boolean =>
|
|
221
206
|
path.startsWith(`${serverDir}/`) && !isProxiedServerModule(path)
|
|
222
207
|
const showPath = (path: string): string =>
|
|
223
208
|
path.startsWith(`${cwd}/`) ? path.slice(cwd.length + 1) : path
|
|
224
|
-
/*
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
seen.add(cursor)
|
|
236
|
-
chain.push(cursor)
|
|
237
|
-
}
|
|
238
|
-
return chain.reverse().map(showPath).join('\n → ')
|
|
239
|
-
}
|
|
240
|
-
function throwSideCrossing(leaf: string, label: string, importer: string): never {
|
|
241
|
-
throw new Error(
|
|
242
|
-
`[abide] a client module imports the server-only name \`${label}\` — server code must not reach the browser bundle. Move it to src/shared/ or behind an RPC. Import chain:\n ${sideCrossingChain(leaf, importer)}`,
|
|
243
|
-
)
|
|
244
|
-
}
|
|
245
|
-
/* Records the edge and, on the client target, rejects a non-server module reaching a
|
|
246
|
-
server-only one. Shared by the relative-import and `$server` alias resolvers. */
|
|
247
|
-
function recordAndGuard(resolved: string, label: string, importer: string | undefined): void {
|
|
248
|
-
if (importer === undefined) {
|
|
249
|
-
return
|
|
250
|
-
}
|
|
251
|
-
importerOf.set(resolved, importer)
|
|
252
|
-
if (target === 'client' && isServerOnlyModule(resolved) && !isServerOnlyModule(importer)) {
|
|
253
|
-
throwSideCrossing(resolved, label, importer)
|
|
254
|
-
}
|
|
255
|
-
}
|
|
209
|
+
/* Renders a root→offender absolute-path chain (from the bundle graph seam) as the cwd-relative
|
|
210
|
+
`a\n → b\n → c` evidence the onEnd diagnostics print — the same shape the resolve-time guard
|
|
211
|
+
gives. */
|
|
212
|
+
const formatChain = (chain: string[]): string => chain.map(showPath).join('\n → ')
|
|
213
|
+
|
|
214
|
+
/* Warm per-root rpc server program (ADR-0025 D1). Lives in the setup closure so one build
|
|
215
|
+
reuses a single `ts.Program` across every rpc transform (streaming/method queries);
|
|
216
|
+
built lazily on the first rpc onLoad (so a build with no rpc modules never pays for it) and
|
|
217
|
+
failing open to undefined, in which case each query stays on its char-scan/regex. (The
|
|
218
|
+
rpc.d.ts codegen builds its own program in generateDeclarations, owned by build().) */
|
|
219
|
+
const rpcServerByRoot = new Map<string, RpcServerProgram | undefined>()
|
|
256
220
|
|
|
257
221
|
return {
|
|
258
222
|
name: 'abide-resolver',
|
|
@@ -264,33 +228,74 @@ export function abideResolverPlugin({
|
|
|
264
228
|
build, so a freshly-created file resolves instead of staying "not found".
|
|
265
229
|
onStart is build-time only — absent in the runtime/preload plugin context. */
|
|
266
230
|
build.onStart?.(() => {
|
|
267
|
-
importerOf.clear()
|
|
268
231
|
resolveExtensionCache.clear()
|
|
269
232
|
})
|
|
270
233
|
|
|
271
234
|
/*
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
235
|
+
Reachability-based side-crossing guard (client target, ADR-0022 D3). After the
|
|
236
|
+
bundle is built, `metafile.inputs` is the post-DCE module graph: a textually-imported
|
|
237
|
+
but tree-shaken module is ABSENT, a surviving one PRESENT. So walk it, flag any
|
|
238
|
+
server-only module that survived (the elided rpc handler's dead `$server/*` imports
|
|
239
|
+
are gone by now; a policy or page that LIVE-reaches server-only code is not), and on a
|
|
240
|
+
hit reconstruct the import chain from the graph's own edges. This is the sole authority
|
|
241
|
+
for the project-server edge — the resolve-time throw was relaxed so the kept rpc module
|
|
242
|
+
can carry its handler's imports until DCE. metafile.inputs keys are relative to
|
|
243
|
+
process.cwd(); edge `path`s are absolute — resolve both to absolute to match serverDir.
|
|
276
244
|
*/
|
|
277
|
-
build.
|
|
278
|
-
if (
|
|
279
|
-
|
|
280
|
-
|
|
245
|
+
build.onEnd?.((result) => {
|
|
246
|
+
if (target !== 'client' || !result.metafile) {
|
|
247
|
+
return
|
|
248
|
+
}
|
|
249
|
+
/* The post-DCE graph, walked once (ADR-0031 D2). Both consumers below read it — the
|
|
250
|
+
side-crossing guard and the bundle-budget diagnostic — instead of each re-walking
|
|
251
|
+
the metafile. */
|
|
252
|
+
const graph = bundleGraphFromMetafile(result.metafile, process.cwd())
|
|
253
|
+
|
|
254
|
+
/* Side-crossing guard (ADR-0022 D3): the FIRST surviving server-only module is a real
|
|
255
|
+
violation — throw with its import chain. The sole hard onEnd failure. */
|
|
256
|
+
const offender = graph.modules.find((module) => isServerOnlyModule(module.path))
|
|
257
|
+
if (offender !== undefined) {
|
|
258
|
+
throw new Error(
|
|
259
|
+
`[abide] a client module reaches the server-only name \`${showPath(offender.path)}\` — server code must not reach the browser bundle. Move it to src/shared/ or behind an RPC. Import chain:\n ${formatChain(graph.importerChain(offender.path))}`,
|
|
260
|
+
)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/* Bundle-budget diagnostic (ADR-0031 D2), first consumer of the seam: a project src
|
|
264
|
+
module that survived DCE heavier than the budget earns a NON-BLOCKING warn with its
|
|
265
|
+
import chain — never fails the build. Scoped to files under cwd (excluding
|
|
266
|
+
node_modules) so the warning is about code the author owns and can act on. */
|
|
267
|
+
for (const module of graph.modules) {
|
|
268
|
+
if (
|
|
269
|
+
module.bytes > CLIENT_BUNDLE_INPUT_BUDGET_BYTES &&
|
|
270
|
+
module.path.startsWith(`${cwd}/`) &&
|
|
271
|
+
!module.path.includes('/node_modules/')
|
|
272
|
+
) {
|
|
273
|
+
abideLog.warn(
|
|
274
|
+
`client bundle input \`${showPath(module.path)}\` is ${(module.bytes / 1024).toFixed(1)} KiB (over the ${CLIENT_BUNDLE_INPUT_BUDGET_BYTES / 1024} KiB budget) — consider splitting or lazy-loading it. Import chain:\n ${formatChain(graph.importerChain(module.path))}`,
|
|
275
|
+
)
|
|
276
|
+
}
|
|
281
277
|
}
|
|
282
|
-
return undefined
|
|
283
278
|
})
|
|
284
279
|
|
|
285
280
|
/*
|
|
286
|
-
The public `abide/server/*` names are server-only
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
281
|
+
The public `abide/server/*` names are server-only and live in node_modules — outside
|
|
282
|
+
`serverDir`, so the onEnd metafile classifier can't see them; this stays the resolve-time
|
|
283
|
+
guard for them (the canonical `abide` and `@abide/abide` specifiers; a custom package
|
|
284
|
+
alias falls through to the reachability guard). A genuine client module importing one is a
|
|
285
|
+
side-crossing. The kept rpc/socket module (proxied) is EXEMPTED: the D2 client transform
|
|
286
|
+
leaves its elided handler's `abide/server/*` imports textually present until DCE drops
|
|
287
|
+
them, so rejecting here would false-positive. The server target resolves these normally.
|
|
290
288
|
*/
|
|
291
289
|
build.onResolve({ filter: /(^|\/)abide\/server\// }, (args) => {
|
|
292
|
-
if (
|
|
293
|
-
|
|
290
|
+
if (
|
|
291
|
+
target === 'client' &&
|
|
292
|
+
args.importer &&
|
|
293
|
+
!isServerOnlyModule(args.importer) &&
|
|
294
|
+
!isProxiedServerModule(args.importer)
|
|
295
|
+
) {
|
|
296
|
+
throw new Error(
|
|
297
|
+
`[abide] a client module imports the server-only name \`${args.path}\` — server code must not reach the browser bundle. Move it to src/shared/ or behind an RPC. Import chain:\n ${showPath(args.importer)}\n → ${args.path}`,
|
|
298
|
+
)
|
|
294
299
|
}
|
|
295
300
|
return undefined
|
|
296
301
|
})
|
|
@@ -325,9 +330,10 @@ export function abideResolverPlugin({
|
|
|
325
330
|
build.onResolve({ filter: new RegExp(`^\\${alias}(\\/.*)?$`) }, (args) => {
|
|
326
331
|
const subpath = args.path.slice(alias.length)
|
|
327
332
|
const resolved = resolveExtension(subpath ? `${baseDir}${subpath}` : baseDir)
|
|
328
|
-
/*
|
|
329
|
-
|
|
330
|
-
|
|
333
|
+
/* No resolve-time side-crossing throw: a `$server/*` import that only the
|
|
334
|
+
elided rpc handler reaches is dead code DCE removes. Whether server-only
|
|
335
|
+
code actually survives into the client bundle is decided post-bundle by the
|
|
336
|
+
onEnd metafile reachability guard (ADR-0022 D3). */
|
|
331
337
|
return { path: resolved }
|
|
332
338
|
})
|
|
333
339
|
}
|
|
@@ -361,7 +367,50 @@ export function abideResolverPlugin({
|
|
|
361
367
|
const source = await Bun.file(args.path).text()
|
|
362
368
|
const url = rpcUrlForFile(relativePath)
|
|
363
369
|
const importName = await abideImportNameOnce()
|
|
364
|
-
|
|
370
|
+
/* Ask the warm server program for this handler's streaming verdict (return-type
|
|
371
|
+
query — a stream returned via a wrapper function is seen); undefined when no
|
|
372
|
+
program built or the node didn't resolve, so prepareRpcModule falls open to its
|
|
373
|
+
char-scan (ADR-0025 D2). */
|
|
374
|
+
const rpcServerProgram = rpcServerForRoot(rpcServerByRoot, cwd, rpcDir)
|
|
375
|
+
const streamingOverride = rpcServerProgram?.streamingForModule(args.path)
|
|
376
|
+
/* The numeric/boolean input fields the server rewrite stamps as a `coerce` plan so
|
|
377
|
+
parseArgs turns a string query/form value into the typed value the schema
|
|
378
|
+
expects (ADR-0028). undefined (no program / unresolvable Args / no coercible
|
|
379
|
+
field) stamps no plan — a GET field stays a string, exactly as today. */
|
|
380
|
+
const coercion = rpcServerProgram?.inputCoercionForModule(args.path)
|
|
381
|
+
/* The handler's return type projected to JSON Schema, stamped as `outputJsonSchema` so
|
|
382
|
+
the runtime OpenAPI 200 / MCP outputSchema / inspector surface renders the real
|
|
383
|
+
response shape without an author-declared `schemas.output` (ADR-0030 D2). undefined
|
|
384
|
+
(no program / unprojectable body / an explicit override wins at runtime) stamps
|
|
385
|
+
nothing — the surface falls back to today's behavior. */
|
|
386
|
+
const returnBodySchema = rpcServerProgram?.returnBodySchemaForModule(args.path)
|
|
387
|
+
/* The handler's typed-error branches projected to a status-keyed JSON-Schema map,
|
|
388
|
+
stamped as `errorJsonSchemas` so the runtime OpenAPI surface documents each typed
|
|
389
|
+
error's status + data payload alongside the 200 (ADR-0030). undefined (no program /
|
|
390
|
+
no typed errors / unresolvable branch) stamps nothing — the surface omits the error
|
|
391
|
+
responses exactly as today. */
|
|
392
|
+
const errorSchemas = rpcServerProgram?.errorSchemasForModule(args.path)
|
|
393
|
+
/* The handler's structured success fields, baked onto the CLIENT stub as
|
|
394
|
+
`outputWirePlan` so the proxy revives a `Set`/`Map`/`bigint`/`Date` off a decoded
|
|
395
|
+
response the server encoded to honest JSON (ADR-0029 output path). undefined (no
|
|
396
|
+
program / unresolvable body / no structured field) bakes nothing — a response array
|
|
397
|
+
stays an array. */
|
|
398
|
+
const outputWirePlan = rpcServerProgram?.outputWirePlanForModule(args.path)
|
|
399
|
+
/* The handler's input args projected to JSON Schema, stamped as `inputJsonSchema` so the
|
|
400
|
+
runtime OpenAPI parameters/body / MCP inputSchema / inspector input surface renders the
|
|
401
|
+
real input shape (and the endpoint becomes advertisable) without an author-declared
|
|
402
|
+
`schemas.input` — mirroring the `outputJsonSchema` output-side path (ADR-0030). A
|
|
403
|
+
declared `schemas.input` VALIDATOR still overrides it at runtime. undefined (no program
|
|
404
|
+
/ unresolvable Args / File-only body) stamps nothing — the surface behaves as today. */
|
|
405
|
+
const inputSchema = rpcServerProgram?.inputSchemaForModule(args.path)
|
|
406
|
+
const prepared = prepareRpcModule(source, importName, {
|
|
407
|
+
streaming: streamingOverride,
|
|
408
|
+
coercion,
|
|
409
|
+
inputSchema,
|
|
410
|
+
outputSchema: returnBodySchema,
|
|
411
|
+
errorSchemas,
|
|
412
|
+
outputWirePlan,
|
|
413
|
+
})
|
|
365
414
|
if (!prepared) {
|
|
366
415
|
throw new Error(
|
|
367
416
|
`[abide] src/server/rpc/${relativePath} has no \`export const <name> = <METHOD>(...)\` — every $rpc module must declare exactly one remote function`,
|
|
@@ -374,25 +423,22 @@ export function abideResolverPlugin({
|
|
|
374
423
|
)
|
|
375
424
|
}
|
|
376
425
|
/*
|
|
377
|
-
|
|
378
|
-
with
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
so
|
|
426
|
+
Client bundle: keep the real module but swap the METHOD( call for a remoteProxy(
|
|
427
|
+
call with the handler ELIDED (ADR-0022 D2), symmetric with the server rewrite
|
|
428
|
+
below. The handler body and the top-level imports only it used become dead code the
|
|
429
|
+
bundler tree-shakes out; the endpoint `opts` (schemas/cache/stream) rides through as
|
|
430
|
+
a LIVE expression, so policy can reference imports and separate modules. The
|
|
431
|
+
surviving-server-module reachability guard (build.onEnd) is the authority that no
|
|
432
|
+
server-only code leaks — resolve-time presence of the elided handler's imports is no
|
|
433
|
+
longer a violation.
|
|
382
434
|
*/
|
|
383
435
|
if (target === 'client') {
|
|
384
|
-
|
|
385
|
-
unreachable calls; `streaming: true` (handler returns jsonl()/sse())
|
|
386
|
-
makes the bare call return the Subscribable directly. */
|
|
387
|
-
const flags = [
|
|
388
|
-
prepared.durable ? 'outbox: true' : undefined,
|
|
389
|
-
prepared.streaming ? 'streaming: true' : undefined,
|
|
390
|
-
].filter(Boolean)
|
|
391
|
-
const optsArg = flags.length > 0 ? `, { ${flags.join(', ')} }` : ''
|
|
392
|
-
const contents = `import { remoteProxy as __abideRemoteProxy__ } from '${importName}/ui/remoteProxy';
|
|
393
|
-
export const ${prepared.exportName} = __abideRemoteProxy__(${JSON.stringify(prepared.method)}, ${JSON.stringify(url)}${optsArg});
|
|
436
|
+
const banner = `import { remoteProxy as ${REMOTE_PROXY_GLOBAL} } from '${importName}/ui/remoteProxy';
|
|
394
437
|
`
|
|
395
|
-
return {
|
|
438
|
+
return {
|
|
439
|
+
contents: `${banner}${prepared.rewriteForClient(url)}`,
|
|
440
|
+
loader: 'ts',
|
|
441
|
+
}
|
|
396
442
|
}
|
|
397
443
|
/*
|
|
398
444
|
Server target: strip the user's rpc import, then rewrite
|
|
@@ -404,7 +450,7 @@ export const ${prepared.exportName} = __abideRemoteProxy__(${JSON.stringify(prep
|
|
|
404
450
|
tokenizer-driven so `GET` mentions inside strings and
|
|
405
451
|
comments are left alone.
|
|
406
452
|
*/
|
|
407
|
-
const banner = `import { defineRpc as
|
|
453
|
+
const banner = `import { defineRpc as ${DEFINE_RPC_GLOBAL} } from '${importName}/server/rpc/defineRpc';
|
|
408
454
|
`
|
|
409
455
|
return { contents: `${banner}${prepared.rewriteForServer(url)}`, loader: 'ts' }
|
|
410
456
|
})
|
|
@@ -440,7 +486,7 @@ export const ${prepared.exportName} = __abideSocketProxy__(${JSON.stringify(name
|
|
|
440
486
|
`
|
|
441
487
|
return { contents, loader: 'ts' }
|
|
442
488
|
}
|
|
443
|
-
const banner = `import { defineSocket as
|
|
489
|
+
const banner = `import { defineSocket as ${DEFINE_SOCKET_GLOBAL} } from '${importName}/server/sockets/defineSocket';
|
|
444
490
|
`
|
|
445
491
|
return {
|
|
446
492
|
contents: `${banner}${prepared.rewriteForServer(name)}`,
|
|
@@ -545,8 +591,6 @@ ${optionLines}
|
|
|
545
591
|
if (args.path === 'abide:app') {
|
|
546
592
|
const userApp = `${cwd}/src/app.ts`
|
|
547
593
|
const hasAppModule = await Bun.file(userApp).exists()
|
|
548
|
-
/* health.d.ts keys the client health() read to the app hook's return type. */
|
|
549
|
-
await writeHealthDtsOnce(hasAppModule)
|
|
550
594
|
if (hasAppModule) {
|
|
551
595
|
abideLog.info('using custom src/app.ts')
|
|
552
596
|
return {
|
|
@@ -882,30 +926,6 @@ ${encoded.map((entry) => entry.line).join('\n')}
|
|
|
882
926
|
`
|
|
883
927
|
}
|
|
884
928
|
|
|
885
|
-
type PagesScan = {
|
|
886
|
-
pageFiles: string[]
|
|
887
|
-
layoutFiles: string[]
|
|
888
|
-
}
|
|
889
|
-
|
|
890
|
-
/*
|
|
891
|
-
Walks src/ui/pages once and classifies each `.abide` leaf by filename: a
|
|
892
|
-
`page.abide` is a route (its URL is the folder path), a `layout.abide` is a
|
|
893
|
-
layout that wraps every page at or below its folder (keyed by the same folder
|
|
894
|
-
URL). Any other `.abide` file (a shared component) is ignored here — free to
|
|
895
|
-
live anywhere and be imported relatively.
|
|
896
|
-
*/
|
|
897
|
-
async function scanPages(pagesDir: string): Promise<PagesScan> {
|
|
898
|
-
if (!existsSync(pagesDir)) {
|
|
899
|
-
return { pageFiles: [], layoutFiles: [] }
|
|
900
|
-
}
|
|
901
|
-
const allFiles = await Array.fromAsync(new Glob('**/*.abide').scan({ cwd: pagesDir }))
|
|
902
|
-
const leafIs = (name: string) => (file: string) => fileName(file) === name
|
|
903
|
-
return {
|
|
904
|
-
pageFiles: allFiles.filter(leafIs('page.abide')),
|
|
905
|
-
layoutFiles: allFiles.filter(leafIs('layout.abide')),
|
|
906
|
-
}
|
|
907
|
-
}
|
|
908
|
-
|
|
909
929
|
/*
|
|
910
930
|
Walks one registry directory once: src/server/rpc (every `.ts` file is an
|
|
911
931
|
HTTP-method rpc handler), src/server/sockets (each `.ts` file declares one
|
|
@@ -1005,16 +1025,24 @@ function injectBeforeTag(
|
|
|
1005
1025
|
}
|
|
1006
1026
|
|
|
1007
1027
|
/*
|
|
1008
|
-
Scans
|
|
1009
|
-
build.ts (e.g. `client-abc12345.js`, `client-abc12345.css`) and swaps the
|
|
1010
|
-
shell's literal `/_app/client.js` and `/_app/client.css` references for
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1028
|
+
Scans the client-bundle directory for the hashed client entry filenames produced
|
|
1029
|
+
by build.ts (e.g. `client-abc12345.js`, `client-abc12345.css`) and swaps the
|
|
1030
|
+
shell's literal `/_app/client.js` and `/_app/client.css` references for them. The
|
|
1031
|
+
js reference appears twice (the modulepreload <link> and the entry <script>), so
|
|
1032
|
+
replaceAll covers both. When the directory is missing (someone running the server
|
|
1033
|
+
before a build) the shell is returned unchanged so the existing broken-asset
|
|
1034
|
+
behaviour is preserved.
|
|
1035
|
+
|
|
1036
|
+
The directory is `dist/_app` for a production build, but under `abide dev` the
|
|
1037
|
+
orchestrator serves each build generation from its own `_app.gen-<id>` dir and
|
|
1038
|
+
passes it as `ABIDE_APP_DIR` (this runs in the worker, which resolves `abide:shell`
|
|
1039
|
+
at boot). Reading that env keeps the shell's entry ref, the preload manifest, and
|
|
1040
|
+
the asset server all pointed at the one generation this worker owns — never a
|
|
1041
|
+
sibling generation a concurrent worker is serving. Each generation dir holds
|
|
1042
|
+
exactly one entry, so `.find` is unambiguous.
|
|
1015
1043
|
*/
|
|
1016
1044
|
async function rewriteHashedClientEntries(shell: string, cwd: string): Promise<string> {
|
|
1017
|
-
const appDir = `${cwd}/dist/_app`
|
|
1045
|
+
const appDir = process.env.ABIDE_APP_DIR ?? `${cwd}/dist/_app`
|
|
1018
1046
|
if (!existsSync(appDir)) {
|
|
1019
1047
|
return shell
|
|
1020
1048
|
}
|