effective-rsc 0.1.3 → 0.1.4
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/LLMS.md +17 -0
- package/README.md +5 -5
- package/dist/application/routes.d.ts +10 -10
- package/dist/application/routes.js.map +1 -1
- package/dist/build/dev.d.ts +4 -4
- package/dist/build/dev.js +22 -7
- package/dist/build/dev.js.map +1 -1
- package/dist/cli.js +3 -3
- package/dist/cli.js.map +1 -1
- package/dist/client/browser-renderer.d.ts +25 -25
- package/dist/client/browser-renderer.js +80 -94
- package/dist/client/browser-renderer.js.map +1 -1
- package/dist/client/call-server.js +7 -5
- package/dist/client/call-server.js.map +1 -1
- package/dist/client/client-router.js +23 -7
- package/dist/client/client-router.js.map +1 -1
- package/dist/client/flight-client.js +3 -4
- package/dist/client/flight-client.js.map +1 -1
- package/dist/client/react-dom-renderer.js +2 -1
- package/dist/client/react-dom-renderer.js.map +1 -1
- package/dist/client/route-refresh.d.ts +2 -2
- package/dist/client/route-refresh.js +54 -39
- package/dist/client/route-refresh.js.map +1 -1
- package/dist/dev/panel.js +14 -14
- package/dist/dev/panel.js.map +1 -1
- package/dist/server/application.d.ts +2 -1
- package/dist/server/application.js +8 -6
- package/dist/server/application.js.map +1 -1
- package/docs/03-advanced/02-client-navigation/index.md +17 -0
- package/package.json +19 -19
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { Layer } from 'effect';
|
|
2
2
|
import type { PlatformError } from 'effect/PlatformError';
|
|
3
3
|
import { HttpRouter, HttpStaticServer } from 'effect/unstable/http';
|
|
4
|
+
import type { ServeError } from 'effect/unstable/http/HttpServerError';
|
|
4
5
|
import { type ApplicationDefinition } from '../application/definition.js';
|
|
5
6
|
import { HtmlRenderError } from './html-renderer.js';
|
|
6
7
|
import { ServerConfig } from './server-config.js';
|
|
7
8
|
import { type ServerFnRequestFailure } from './server-fn-request.js';
|
|
8
9
|
type HttpApplicationRequirements = ServerConfig | Layer.Services<ReturnType<typeof HttpStaticServer.layer>> | HttpRouter.Request.From<'Error', HtmlRenderError | ServerFnRequestFailure>;
|
|
9
10
|
export type HttpApplicationLayer<ApplicationError> = Layer.Layer<never, ApplicationError | PlatformError, HttpApplicationRequirements>;
|
|
10
|
-
export type ServerApplicationLayer<ApplicationError> = Layer.Layer<never, ApplicationError | PlatformError, ServerConfig>;
|
|
11
|
+
export type ServerApplicationLayer<ApplicationError> = Layer.Layer<never, HttpRouter.Request.Without<ApplicationError> | PlatformError | ServeError, ServerConfig>;
|
|
11
12
|
declare const httpLayer: <Services, ApplicationError>(application: ApplicationDefinition<Services, ApplicationError>) => HttpApplicationLayer<ApplicationError>;
|
|
12
13
|
declare const serverLayer: <Services, ApplicationError>(application: ApplicationDefinition<Services, ApplicationError>) => ServerApplicationLayer<ApplicationError>;
|
|
13
14
|
export declare const ServerApplication: {
|
|
@@ -13,6 +13,9 @@ import { ApplicationIdleTimeoutSeconds, ApplicationMaxRequestBodySizeBytes, Serv
|
|
|
13
13
|
import { prepareServerFnRequest } from "./server-fn-request.js";
|
|
14
14
|
|
|
15
15
|
import * as __rspack_external__effect_platform_bun_BunHttpServer_0e4f7bbb from "@effect/platform-bun/BunHttpServer";
|
|
16
|
+
import * as __rspack_external__effect_platform_bun_BunStream_c9d32906 from "@effect/platform-bun/BunStream";
|
|
17
|
+
|
|
18
|
+
|
|
16
19
|
|
|
17
20
|
|
|
18
21
|
|
|
@@ -72,7 +75,7 @@ const appendAcceptVary = (vary)=>{
|
|
|
72
75
|
return fields.includes('*') || fields.includes('accept') ? vary : `${vary}, Accept`;
|
|
73
76
|
};
|
|
74
77
|
const acceptVaryPreResponseHandler = (_request, response)=>Effect.succeed(HttpServerResponse.setHeader(response, 'vary', appendAcceptVary(response.headers['vary'])));
|
|
75
|
-
const fromWebStream = (stream, options)=>
|
|
78
|
+
const fromWebStream = (stream, options)=>__rspack_external__effect_platform_bun_BunStream_c9d32906.fromReadableStream({
|
|
76
79
|
evaluate: ()=>stream,
|
|
77
80
|
onError: (cause)=>cause,
|
|
78
81
|
releaseLockOnEnd: options?.releaseLockOnEnd
|
|
@@ -109,8 +112,7 @@ const httpLayer = (application)=>{
|
|
|
109
112
|
}).pipe(Stream.ensuring(flight.release)), {
|
|
110
113
|
contentType: `${FlightMediaType};charset=utf-8`,
|
|
111
114
|
headers: {
|
|
112
|
-
...DynamicResponseHeaders
|
|
113
|
-
'content-location': requestUrl.value.href
|
|
115
|
+
...DynamicResponseHeaders
|
|
114
116
|
},
|
|
115
117
|
status
|
|
116
118
|
});
|
|
@@ -161,8 +163,8 @@ const httpLayer = (application)=>{
|
|
|
161
163
|
return applyMiddleware(prepared.middleware, response);
|
|
162
164
|
};
|
|
163
165
|
const RequestLayer = Layer.mergeAll(RenderersLayer, applicationState.layer);
|
|
164
|
-
const ApplicationRoutesLayer = Layer.unwrap(Effect.map(
|
|
165
|
-
const RequestContextMiddleware = HttpRouter.middleware()((httpEffect)=>httpEffect.pipe(Effect.provideContext(
|
|
166
|
+
const ApplicationRoutesLayer = Layer.unwrap(Effect.map(Layer.build(RequestLayer), (applicationServices)=>{
|
|
167
|
+
const RequestContextMiddleware = HttpRouter.middleware()((httpEffect)=>httpEffect.pipe(Effect.provideContext(applicationServices)));
|
|
166
168
|
const makeRouteLayer = (destination)=>{
|
|
167
169
|
const GetLayer = HttpRouter.add('GET', destination.pattern, (request)=>render({
|
|
168
170
|
destination,
|
|
@@ -183,7 +185,7 @@ const httpLayer = (application)=>{
|
|
|
183
185
|
};
|
|
184
186
|
const [firstDestination, ...remainingDestinations] = applicationState.routes;
|
|
185
187
|
return Layer.mergeAll(makeRouteLayer(firstDestination), ...remainingDestinations.map(makeRouteLayer));
|
|
186
|
-
}))
|
|
188
|
+
}));
|
|
187
189
|
return Layer.mergeAll(StaticAssetsLayer, PublicAssetsLayer).pipe(Layer.provideMerge(ApplicationRoutesLayer));
|
|
188
190
|
};
|
|
189
191
|
const serverLayer = (application)=>HttpRouter.serve(httpLayer(application)).pipe(Layer.provide(BunServerLayer));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server/application.js","sources":["../../src/server/application.ts"],"sourcesContent":["import * as BunHttpServer from '@effect/platform-bun/BunHttpServer';\nimport { Effect, Layer, Option, Schema, Stream, type Types } from 'effect';\nimport type { PlatformError } from 'effect/PlatformError';\nimport {\n HttpEffect,\n HttpRouter,\n HttpServerRequest,\n HttpServerResponse,\n HttpStaticServer,\n} from 'effect/unstable/http';\n\nimport { type ApplicationDefinition, getApplicationState } from '../application/definition';\nimport { getERSCIdentity } from '../application/ersc-identity';\nimport {\n applyMiddleware,\n type AnyMiddleware,\n getScopedHttpMiddleware,\n} from '../application/middleware';\nimport type { EncodedPageParams, PageParams } from '../application/page';\nimport type { CompiledDestination } from '../application/route-graph';\nimport { FrameworkAssetNamespace, isAbsolutePath } from '../application/route-path';\nimport { FlightMediaType } from '../rsc/flight';\nimport { renderRouteTree } from '../rsc/render-route-tree';\nimport { FlightHtmlInjector } from './flight-html-stream';\nimport { FlightRenderer } from './flight-renderer';\nimport { HtmlRenderError, HtmlRenderer } from './html-renderer';\nimport type { RequestOutcome } from './request-outcome';\nimport {\n ApplicationIdleTimeoutSeconds,\n ApplicationMaxRequestBodySizeBytes,\n ServerConfig,\n} from './server-config';\nimport {\n prepareServerFnRequest,\n type PreparedServerFnRequest,\n type ServerFnRequestFailure,\n} from './server-fn-request';\n\nconst RenderersLayer = Layer.mergeAll(FlightRenderer.layer, HtmlRenderer.layer).pipe(\n Layer.provide(FlightHtmlInjector.layer),\n);\n\nconst StaticAssetsLayer = Layer.unwrap(\n Effect.map(ServerConfig, ({ clientAssetsCacheControl, clientAssetsRoot }) =>\n HttpStaticServer.layer({\n cacheControl: clientAssetsCacheControl,\n prefix: FrameworkAssetNamespace,\n root: clientAssetsRoot,\n }).pipe(Layer.provide(HttpRouter.disableLogger)),\n ),\n);\n\nconst PublicAssetsLayer = Layer.unwrap(\n Effect.map(ServerConfig, ({ publicAssetsRoot }) =>\n HttpStaticServer.layer({\n cacheControl: 'public, max-age=0',\n root: publicAssetsRoot,\n }),\n ),\n);\n\n// Bun derives `development` from NODE_ENV, which `ersc start` does not set, and its error page\n// carries the failure message and source stack.\nconst BunServerLayer = Layer.unwrap(\n Effect.map(ServerConfig, ({ hostname, port }) =>\n BunHttpServer.layer({\n development: false,\n hostname,\n idleTimeout: ApplicationIdleTimeoutSeconds,\n maxRequestBodySize: ApplicationMaxRequestBodySizeBytes,\n port,\n }),\n ),\n);\n\nconst EmptyEncodedPageParams: EncodedPageParams = Object.freeze({});\nconst DynamicResponseHeaders = {\n 'cache-control': 'private, no-store',\n} as const;\n\nconst appendAcceptVary = (vary: string | undefined) => {\n if (vary === undefined || vary.trim() === '') {\n return 'Accept';\n }\n\n const fields = vary.split(',').map((field) => field.trim().toLowerCase());\n return fields.includes('*') || fields.includes('accept') ? vary : `${vary}, Accept`;\n};\n\nconst acceptVaryPreResponseHandler: HttpEffect.PreResponseHandler = (_request, response) =>\n Effect.succeed(\n HttpServerResponse.setHeader(response, 'vary', appendAcceptVary(response.headers['vary'])),\n );\n\ntype RenderOptions<Services> = RequestOutcome & {\n readonly destination: CompiledDestination<Services>;\n readonly middleware: ReadonlyArray<AnyMiddleware<Services>>;\n readonly request: HttpServerRequest.HttpServerRequest;\n};\n\nconst fromWebStream = (\n stream: ReadableStream<Uint8Array>,\n options?: { readonly releaseLockOnEnd?: boolean },\n) =>\n Stream.fromReadableStream({\n evaluate: () => stream,\n onError: (cause) => cause,\n releaseLockOnEnd: options?.releaseLockOnEnd,\n });\n\nconst combinePageMiddleware = <Services>(\n middleware: ReadonlyArray<AnyMiddleware<Services>>,\n last: AnyMiddleware<Services>,\n) =>\n middleware\n .slice(0, -1)\n .reduceRight(\n (combined, current) => combined.combine(getScopedHttpMiddleware(current)),\n getScopedHttpMiddleware(last),\n );\n\ntype HttpApplicationRequirements =\n | ServerConfig\n | Layer.Services<ReturnType<typeof HttpStaticServer.layer>>\n | HttpRouter.Request.From<'Error', HtmlRenderError | ServerFnRequestFailure>;\n\nexport type HttpApplicationLayer<ApplicationError> = Layer.Layer<\n never,\n ApplicationError | PlatformError,\n HttpApplicationRequirements\n>;\n\nexport type ServerApplicationLayer<ApplicationError> = Layer.Layer<\n never,\n ApplicationError | PlatformError,\n ServerConfig\n>;\n\nconst httpLayer = <Services, ApplicationError>(\n application: ApplicationDefinition<Services, ApplicationError>,\n): HttpApplicationLayer<ApplicationError> => {\n const applicationState = getApplicationState(application);\n const identity = getERSCIdentity(application);\n const render = Effect.fnUntraced(function* ({\n destination,\n formState,\n middleware,\n request,\n serverFnResult,\n status,\n temporaryReferences,\n }: RenderOptions<Services>) {\n const requestUrl = HttpServerRequest.toURL(request);\n if (Option.isNone(requestUrl) || !isAbsolutePath(requestUrl.value.pathname)) {\n return yield* Effect.die(\n new TypeError(`Expected request URL \"${request.originalUrl}\" to contain an absolute path.`),\n );\n }\n\n const pathname = requestUrl.value.pathname;\n const encodedParams = yield* destination.page.paramsSchema === null\n ? Effect.succeed(EmptyEncodedPageParams)\n : HttpRouter.params;\n const renderResponse = Effect.fnUntraced(function* (params: PageParams) {\n const routeTree = renderRouteTree({\n destination,\n params,\n pathname,\n });\n const flightRenderer = yield* FlightRenderer;\n const flight = yield* flightRenderer.render({\n formState,\n middleware,\n renderRuntime: identity.renderRuntime,\n routeTree,\n serverFnResult,\n temporaryReferences,\n });\n\n if (request.headers['accept'] === FlightMediaType) {\n return HttpServerResponse.stream(\n fromWebStream(flight.stream, { releaseLockOnEnd: true }).pipe(\n Stream.ensuring(flight.release),\n ),\n {\n contentType: `${FlightMediaType};charset=utf-8`,\n headers: {\n ...DynamicResponseHeaders,\n 'content-location': requestUrl.value.href,\n },\n status,\n },\n );\n }\n\n const htmlRenderer = yield* HtmlRenderer;\n const htmlStream = yield* htmlRenderer\n .render({ flight, formState })\n .pipe(Effect.onError(() => flight.release));\n\n return HttpServerResponse.stream(\n fromWebStream(htmlStream).pipe(Stream.ensuring(flight.release)),\n {\n contentType: 'text/html;charset=utf-8',\n headers: DynamicResponseHeaders,\n status,\n },\n );\n });\n\n if (request.method !== 'POST' && destination.page.paramsSchema !== null) {\n return yield* Schema.decodeEffect(destination.page.paramsSchema)(encodedParams).pipe(\n Effect.matchEffect({\n onFailure: () =>\n Effect.succeed(\n HttpServerResponse.empty({ status: 404, headers: DynamicResponseHeaders }),\n ),\n onSuccess: (value) => renderResponse({ _tag: 'Decoded', value }),\n }),\n );\n }\n return yield* renderResponse({ _tag: 'Encoded', value: encodedParams });\n });\n\n const executeServerFnAndRefresh = (\n prepared: PreparedServerFnRequest<Services>,\n destination: CompiledDestination<Services>,\n request: HttpServerRequest.HttpServerRequest,\n ) => {\n const refreshMiddleware = destination.middleware.filter(\n (middleware) => !prepared.middleware.includes(middleware),\n );\n const renderMiddleware =\n refreshMiddleware.length === 0\n ? prepared.middleware\n : Object.freeze([...prepared.middleware, ...refreshMiddleware]);\n const response = prepared.execute.pipe(\n Effect.flatMap((outcome) => {\n const refresh = render({\n ...outcome,\n destination,\n middleware: renderMiddleware,\n request,\n });\n return applyMiddleware(refreshMiddleware, refresh);\n }),\n );\n\n return applyMiddleware(prepared.middleware, response);\n };\n\n const RequestLayer = Layer.mergeAll(RenderersLayer, applicationState.layer);\n const ApplicationRoutesLayer = Layer.unwrap(\n Effect.map(Effect.context<Services | FlightRenderer | HtmlRenderer>(), (requestContext) => {\n const RequestContextMiddleware = HttpRouter.middleware<{\n provides: Services | FlightRenderer | HtmlRenderer;\n }>()((httpEffect): Effect.Effect<HttpServerResponse.HttpServerResponse, Types.unhandled> =>\n httpEffect.pipe(Effect.provideContext(requestContext)),\n );\n const makeRouteLayer = (destination: CompiledDestination<Services>) => {\n const GetLayer = HttpRouter.add('GET', destination.pattern, (request) =>\n render({\n destination,\n formState: null,\n middleware: destination.middleware,\n request,\n serverFnResult: null,\n status: 200,\n }).pipe(HttpEffect.withPreResponseHandler(acceptVaryPreResponseHandler)),\n );\n const lastPageMiddleware = destination.middleware.at(-1);\n const PageMiddleware =\n lastPageMiddleware === undefined\n ? RequestContextMiddleware\n : combinePageMiddleware(destination.middleware, lastPageMiddleware).combine(\n RequestContextMiddleware,\n );\n const PageLayer = GetLayer.pipe(Layer.provide(PageMiddleware.layer));\n const ServerFnLayer = HttpRouter.add('POST', destination.pattern, (request) =>\n prepareServerFnRequest(request, identity).pipe(\n Effect.flatMap((prepared) => executeServerFnAndRefresh(prepared, destination, request)),\n Effect.catchTag('ServerFnRequestError', (error) =>\n Effect.succeed(\n HttpServerResponse.text(error.message, {\n headers: DynamicResponseHeaders,\n status: error.status,\n }),\n ),\n ),\n HttpEffect.withPreResponseHandler(acceptVaryPreResponseHandler),\n ),\n ).pipe(Layer.provide(RequestContextMiddleware.layer));\n\n return Layer.mergeAll(PageLayer, ServerFnLayer);\n };\n const [firstDestination, ...remainingDestinations] = applicationState.routes;\n return Layer.mergeAll(\n makeRouteLayer(firstDestination),\n ...remainingDestinations.map(makeRouteLayer),\n );\n }),\n ).pipe(Layer.provide(RequestLayer));\n\n return Layer.mergeAll(StaticAssetsLayer, PublicAssetsLayer).pipe(\n Layer.provideMerge(ApplicationRoutesLayer),\n );\n};\n\nconst serverLayer = <Services, ApplicationError>(\n application: ApplicationDefinition<Services, ApplicationError>,\n): ServerApplicationLayer<ApplicationError> =>\n HttpRouter.serve(httpLayer(application)).pipe(Layer.provide(BunServerLayer));\n\nexport const ServerApplication = { httpLayer, serverLayer };\n"],"names":["BunHttpServer","Effect","Layer","Option","Schema","Stream","HttpEffect","HttpRouter","HttpServerRequest","HttpServerResponse","HttpStaticServer","getApplicationState","getERSCIdentity","applyMiddleware","getScopedHttpMiddleware","FrameworkAssetNamespace","isAbsolutePath","FlightMediaType","renderRouteTree","FlightHtmlInjector","FlightRenderer","HtmlRenderer","ApplicationIdleTimeoutSeconds","ApplicationMaxRequestBodySizeBytes","ServerConfig","prepareServerFnRequest","RenderersLayer","StaticAssetsLayer","clientAssetsCacheControl","clientAssetsRoot","PublicAssetsLayer","publicAssetsRoot","BunServerLayer","hostname","port","EmptyEncodedPageParams","Object","DynamicResponseHeaders","appendAcceptVary","vary","undefined","fields","field","acceptVaryPreResponseHandler","_request","response","fromWebStream","stream","options","cause","combinePageMiddleware","middleware","last","combined","current","httpLayer","application","applicationState","identity","render","destination","formState","request","serverFnResult","status","temporaryReferences","requestUrl","TypeError","pathname","encodedParams","renderResponse","params","routeTree","flightRenderer","flight","htmlRenderer","htmlStream","value","executeServerFnAndRefresh","prepared","refreshMiddleware","renderMiddleware","outcome","refresh","RequestLayer","ApplicationRoutesLayer","requestContext","RequestContextMiddleware","httpEffect","makeRouteLayer","GetLayer","lastPageMiddleware","PageMiddleware","PageLayer","ServerFnLayer","error","firstDestination","remainingDestinations","serverLayer","ServerApplication"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"server/application.js","sources":["../../src/server/application.ts"],"sourcesContent":["import * as BunHttpServer from '@effect/platform-bun/BunHttpServer';\nimport * as BunStream from '@effect/platform-bun/BunStream';\nimport { Effect, Layer, Option, Schema, Stream, type Types } from 'effect';\nimport type { PlatformError } from 'effect/PlatformError';\nimport {\n HttpEffect,\n HttpRouter,\n HttpServerRequest,\n HttpServerResponse,\n HttpStaticServer,\n} from 'effect/unstable/http';\nimport type { ServeError } from 'effect/unstable/http/HttpServerError';\n\nimport { type ApplicationDefinition, getApplicationState } from '../application/definition';\nimport { getERSCIdentity } from '../application/ersc-identity';\nimport {\n applyMiddleware,\n type AnyMiddleware,\n getScopedHttpMiddleware,\n} from '../application/middleware';\nimport type { EncodedPageParams, PageParams } from '../application/page';\nimport type { CompiledDestination } from '../application/route-graph';\nimport { FrameworkAssetNamespace, isAbsolutePath } from '../application/route-path';\nimport { FlightMediaType } from '../rsc/flight';\nimport { renderRouteTree } from '../rsc/render-route-tree';\nimport { FlightHtmlInjector } from './flight-html-stream';\nimport { FlightRenderer } from './flight-renderer';\nimport { HtmlRenderError, HtmlRenderer } from './html-renderer';\nimport type { RequestOutcome } from './request-outcome';\nimport {\n ApplicationIdleTimeoutSeconds,\n ApplicationMaxRequestBodySizeBytes,\n ServerConfig,\n} from './server-config';\nimport {\n prepareServerFnRequest,\n type PreparedServerFnRequest,\n type ServerFnRequestFailure,\n} from './server-fn-request';\n\nconst RenderersLayer = Layer.mergeAll(FlightRenderer.layer, HtmlRenderer.layer).pipe(\n Layer.provide(FlightHtmlInjector.layer),\n);\n\nconst StaticAssetsLayer = Layer.unwrap(\n Effect.map(ServerConfig, ({ clientAssetsCacheControl, clientAssetsRoot }) =>\n HttpStaticServer.layer({\n cacheControl: clientAssetsCacheControl,\n prefix: FrameworkAssetNamespace,\n root: clientAssetsRoot,\n }).pipe(Layer.provide(HttpRouter.disableLogger)),\n ),\n);\n\nconst PublicAssetsLayer = Layer.unwrap(\n Effect.map(ServerConfig, ({ publicAssetsRoot }) =>\n HttpStaticServer.layer({\n cacheControl: 'public, max-age=0',\n root: publicAssetsRoot,\n }),\n ),\n);\n\n// Bun derives `development` from NODE_ENV, which `ersc start` does not set, and its error page\n// carries the failure message and source stack.\nconst BunServerLayer = Layer.unwrap(\n Effect.map(ServerConfig, ({ hostname, port }) =>\n BunHttpServer.layer({\n development: false,\n hostname,\n idleTimeout: ApplicationIdleTimeoutSeconds,\n maxRequestBodySize: ApplicationMaxRequestBodySizeBytes,\n port,\n }),\n ),\n);\n\nconst EmptyEncodedPageParams: EncodedPageParams = Object.freeze({});\nconst DynamicResponseHeaders = {\n 'cache-control': 'private, no-store',\n} as const;\n\nconst appendAcceptVary = (vary: string | undefined) => {\n if (vary === undefined || vary.trim() === '') {\n return 'Accept';\n }\n\n const fields = vary.split(',').map((field) => field.trim().toLowerCase());\n return fields.includes('*') || fields.includes('accept') ? vary : `${vary}, Accept`;\n};\n\nconst acceptVaryPreResponseHandler: HttpEffect.PreResponseHandler = (_request, response) =>\n Effect.succeed(\n HttpServerResponse.setHeader(response, 'vary', appendAcceptVary(response.headers['vary'])),\n );\n\ntype RenderOptions<Services> = RequestOutcome & {\n readonly destination: CompiledDestination<Services>;\n readonly middleware: ReadonlyArray<AnyMiddleware<Services>>;\n readonly request: HttpServerRequest.HttpServerRequest;\n};\n\nconst fromWebStream = (\n stream: ReadableStream<Uint8Array>,\n options?: { readonly releaseLockOnEnd?: boolean },\n) =>\n BunStream.fromReadableStream({\n evaluate: () => stream,\n onError: (cause) => cause,\n releaseLockOnEnd: options?.releaseLockOnEnd,\n });\n\nconst combinePageMiddleware = <Services>(\n middleware: ReadonlyArray<AnyMiddleware<Services>>,\n last: AnyMiddleware<Services>,\n) =>\n middleware\n .slice(0, -1)\n .reduceRight(\n (combined, current) => combined.combine(getScopedHttpMiddleware(current)),\n getScopedHttpMiddleware(last),\n );\n\ntype HttpApplicationRequirements =\n | ServerConfig\n | Layer.Services<ReturnType<typeof HttpStaticServer.layer>>\n | HttpRouter.Request.From<'Error', HtmlRenderError | ServerFnRequestFailure>;\n\nexport type HttpApplicationLayer<ApplicationError> = Layer.Layer<\n never,\n ApplicationError | PlatformError,\n HttpApplicationRequirements\n>;\n\nexport type ServerApplicationLayer<ApplicationError> = Layer.Layer<\n never,\n HttpRouter.Request.Without<ApplicationError> | PlatformError | ServeError,\n ServerConfig\n>;\n\nconst httpLayer = <Services, ApplicationError>(\n application: ApplicationDefinition<Services, ApplicationError>,\n): HttpApplicationLayer<ApplicationError> => {\n const applicationState = getApplicationState(application);\n const identity = getERSCIdentity(application);\n const render = Effect.fnUntraced(function* ({\n destination,\n formState,\n middleware,\n request,\n serverFnResult,\n status,\n temporaryReferences,\n }: RenderOptions<Services>) {\n const requestUrl = HttpServerRequest.toURL(request);\n if (Option.isNone(requestUrl) || !isAbsolutePath(requestUrl.value.pathname)) {\n return yield* Effect.die(\n new TypeError(`Expected request URL \"${request.originalUrl}\" to contain an absolute path.`),\n );\n }\n\n const pathname = requestUrl.value.pathname;\n const encodedParams = yield* destination.page.paramsSchema === null\n ? Effect.succeed(EmptyEncodedPageParams)\n : HttpRouter.params;\n const renderResponse = Effect.fnUntraced(function* (params: PageParams) {\n const routeTree = renderRouteTree({\n destination,\n params,\n pathname,\n });\n const flightRenderer = yield* FlightRenderer;\n const flight = yield* flightRenderer.render({\n formState,\n middleware,\n renderRuntime: identity.renderRuntime,\n routeTree,\n serverFnResult,\n temporaryReferences,\n });\n\n if (request.headers['accept'] === FlightMediaType) {\n return HttpServerResponse.stream(\n fromWebStream(flight.stream, { releaseLockOnEnd: true }).pipe(\n Stream.ensuring(flight.release),\n ),\n {\n contentType: `${FlightMediaType};charset=utf-8`,\n headers: {\n ...DynamicResponseHeaders,\n },\n status,\n },\n );\n }\n\n const htmlRenderer = yield* HtmlRenderer;\n const htmlStream = yield* htmlRenderer\n .render({ flight, formState })\n .pipe(Effect.onError(() => flight.release));\n\n return HttpServerResponse.stream(\n fromWebStream(htmlStream).pipe(Stream.ensuring(flight.release)),\n {\n contentType: 'text/html;charset=utf-8',\n headers: DynamicResponseHeaders,\n status,\n },\n );\n });\n\n if (request.method !== 'POST' && destination.page.paramsSchema !== null) {\n return yield* Schema.decodeEffect(destination.page.paramsSchema)(encodedParams).pipe(\n Effect.matchEffect({\n onFailure: () =>\n Effect.succeed(\n HttpServerResponse.empty({ status: 404, headers: DynamicResponseHeaders }),\n ),\n onSuccess: (value) => renderResponse({ _tag: 'Decoded', value }),\n }),\n );\n }\n return yield* renderResponse({ _tag: 'Encoded', value: encodedParams });\n });\n\n const executeServerFnAndRefresh = (\n prepared: PreparedServerFnRequest<Services>,\n destination: CompiledDestination<Services>,\n request: HttpServerRequest.HttpServerRequest,\n ) => {\n const refreshMiddleware = destination.middleware.filter(\n (middleware) => !prepared.middleware.includes(middleware),\n );\n const renderMiddleware =\n refreshMiddleware.length === 0\n ? prepared.middleware\n : Object.freeze([...prepared.middleware, ...refreshMiddleware]);\n const response = prepared.execute.pipe(\n Effect.flatMap((outcome) => {\n const refresh = render({\n ...outcome,\n destination,\n middleware: renderMiddleware,\n request,\n });\n return applyMiddleware(refreshMiddleware, refresh);\n }),\n );\n\n return applyMiddleware(prepared.middleware, response);\n };\n\n const RequestLayer = Layer.mergeAll(RenderersLayer, applicationState.layer);\n const ApplicationRoutesLayer = Layer.unwrap(\n Effect.map(Layer.build(RequestLayer), (applicationServices) => {\n const RequestContextMiddleware = HttpRouter.middleware<{\n provides: Services | FlightRenderer | HtmlRenderer;\n }>()((httpEffect): Effect.Effect<HttpServerResponse.HttpServerResponse, Types.unhandled> =>\n httpEffect.pipe(Effect.provideContext(applicationServices)),\n );\n const makeRouteLayer = (destination: CompiledDestination<Services>) => {\n const GetLayer = HttpRouter.add('GET', destination.pattern, (request) =>\n render({\n destination,\n formState: null,\n middleware: destination.middleware,\n request,\n serverFnResult: null,\n status: 200,\n }).pipe(HttpEffect.withPreResponseHandler(acceptVaryPreResponseHandler)),\n );\n const lastPageMiddleware = destination.middleware.at(-1);\n const PageMiddleware =\n lastPageMiddleware === undefined\n ? RequestContextMiddleware\n : combinePageMiddleware(destination.middleware, lastPageMiddleware).combine(\n RequestContextMiddleware,\n );\n const PageLayer = GetLayer.pipe(Layer.provide(PageMiddleware.layer));\n const ServerFnLayer = HttpRouter.add('POST', destination.pattern, (request) =>\n prepareServerFnRequest(request, identity).pipe(\n Effect.flatMap((prepared) => executeServerFnAndRefresh(prepared, destination, request)),\n Effect.catchTag('ServerFnRequestError', (error) =>\n Effect.succeed(\n HttpServerResponse.text(error.message, {\n headers: DynamicResponseHeaders,\n status: error.status,\n }),\n ),\n ),\n HttpEffect.withPreResponseHandler(acceptVaryPreResponseHandler),\n ),\n ).pipe(Layer.provide(RequestContextMiddleware.layer));\n\n return Layer.mergeAll(PageLayer, ServerFnLayer);\n };\n const [firstDestination, ...remainingDestinations] = applicationState.routes;\n return Layer.mergeAll(\n makeRouteLayer(firstDestination),\n ...remainingDestinations.map(makeRouteLayer),\n );\n }),\n );\n\n return Layer.mergeAll(StaticAssetsLayer, PublicAssetsLayer).pipe(\n Layer.provideMerge(ApplicationRoutesLayer),\n );\n};\n\nconst serverLayer = <Services, ApplicationError>(\n application: ApplicationDefinition<Services, ApplicationError>,\n): ServerApplicationLayer<ApplicationError> =>\n HttpRouter.serve(httpLayer(application)).pipe(Layer.provide(BunServerLayer));\n\nexport const ServerApplication = { httpLayer, serverLayer };\n"],"names":["BunHttpServer","BunStream","Effect","Layer","Option","Schema","Stream","HttpEffect","HttpRouter","HttpServerRequest","HttpServerResponse","HttpStaticServer","getApplicationState","getERSCIdentity","applyMiddleware","getScopedHttpMiddleware","FrameworkAssetNamespace","isAbsolutePath","FlightMediaType","renderRouteTree","FlightHtmlInjector","FlightRenderer","HtmlRenderer","ApplicationIdleTimeoutSeconds","ApplicationMaxRequestBodySizeBytes","ServerConfig","prepareServerFnRequest","RenderersLayer","StaticAssetsLayer","clientAssetsCacheControl","clientAssetsRoot","PublicAssetsLayer","publicAssetsRoot","BunServerLayer","hostname","port","EmptyEncodedPageParams","Object","DynamicResponseHeaders","appendAcceptVary","vary","undefined","fields","field","acceptVaryPreResponseHandler","_request","response","fromWebStream","stream","options","cause","combinePageMiddleware","middleware","last","combined","current","httpLayer","application","applicationState","identity","render","destination","formState","request","serverFnResult","status","temporaryReferences","requestUrl","TypeError","pathname","encodedParams","renderResponse","params","routeTree","flightRenderer","flight","htmlRenderer","htmlStream","value","executeServerFnAndRefresh","prepared","refreshMiddleware","renderMiddleware","outcome","refresh","RequestLayer","ApplicationRoutesLayer","applicationServices","RequestContextMiddleware","httpEffect","makeRouteLayer","GetLayer","lastPageMiddleware","PageMiddleware","PageLayer","ServerFnLayer","error","firstDestination","remainingDestinations","serverLayer","ServerApplication"],"mappings":"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"}
|
|
@@ -62,3 +62,20 @@ but ERSC does not impose that policy.
|
|
|
62
62
|
These types describe only the first publication. Suspense content that resolves later renders in a
|
|
63
63
|
separate, untyped React Transition. Applications should use their own Suspense-specific
|
|
64
64
|
`<ViewTransition>` boundaries and styling for those reveals.
|
|
65
|
+
|
|
66
|
+
#### Application transition types
|
|
67
|
+
|
|
68
|
+
Add whitespace-separated application transition types to a native link with
|
|
69
|
+
`data-ersc-transition-types`:
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
<a href='/photos/2' data-ersc-transition-types='photo-next'>
|
|
73
|
+
Next photo
|
|
74
|
+
</a>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
These are added alongside ERSC's built-in types for that push or replace navigation and can be
|
|
78
|
+
used in your `<ViewTransition>` type maps. They are not replayed on Back/Forward.
|
|
79
|
+
|
|
80
|
+
The names `navigation`, `navigation-*`, `server-function`, and `hmr-refresh` are reserved for ERSC
|
|
81
|
+
and ignored in the attribute.
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "effective-rsc",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "An experimental, Effect-native React Server Components framework for Bun.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bun",
|
|
7
7
|
"effect",
|
|
8
8
|
"react-server-components"
|
|
9
9
|
],
|
|
10
|
-
"homepage": "https://
|
|
10
|
+
"homepage": "https://effective-rsc.nikhilsnayak.dev/",
|
|
11
11
|
"bugs": {
|
|
12
12
|
"url": "https://github.com/nikhilsnayak/effective-rsc/issues"
|
|
13
13
|
},
|
|
@@ -58,34 +58,34 @@
|
|
|
58
58
|
"test:watch": "bun run --bun vitest"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@rspack/core": "2.2.
|
|
61
|
+
"@rspack/core": "2.2.3",
|
|
62
62
|
"@rspack/plugin-react-refresh": "2.0.2",
|
|
63
63
|
"@tailwindcss/webpack": "4.3.3",
|
|
64
|
-
"react-refresh": "0.
|
|
64
|
+
"react-refresh": "0.19.0"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
67
|
"@base-ui/react": "^1.8.0",
|
|
68
|
-
"@effect/platform-browser": "4.0.0-rc.
|
|
69
|
-
"@effect/platform-bun": "4.0.0-rc.
|
|
70
|
-
"@effect/vitest": "4.0.0-rc.
|
|
68
|
+
"@effect/platform-browser": "4.0.0-rc.113",
|
|
69
|
+
"@effect/platform-bun": "4.0.0-rc.113",
|
|
70
|
+
"@effect/vitest": "4.0.0-rc.113",
|
|
71
71
|
"@rsbuild/plugin-react": "2.1.0",
|
|
72
72
|
"@rslib/core": "1.0.0",
|
|
73
|
-
"@types/bun": "^1.4.
|
|
74
|
-
"@types/react": "19.
|
|
75
|
-
"@types/react-dom": "19.
|
|
76
|
-
"effect": "4.0.0-rc.
|
|
77
|
-
"react": "19.3.0-canary-
|
|
78
|
-
"react-dom": "19.3.0-canary-
|
|
73
|
+
"@types/bun": "^1.4.2",
|
|
74
|
+
"@types/react": "19.3.0",
|
|
75
|
+
"@types/react-dom": "19.3.0",
|
|
76
|
+
"effect": "4.0.0-rc.113",
|
|
77
|
+
"react": "19.3.0-canary-1d34f91d-20260909",
|
|
78
|
+
"react-dom": "19.3.0-canary-1d34f91d-20260909",
|
|
79
79
|
"react-server-dom-rspack": "0.1.0",
|
|
80
80
|
"typescript": "7.0.2",
|
|
81
|
-
"vitest": "^
|
|
81
|
+
"vitest": "^5.0.0"
|
|
82
82
|
},
|
|
83
83
|
"peerDependencies": {
|
|
84
|
-
"@effect/platform-browser": "4.0.0-rc.
|
|
85
|
-
"@effect/platform-bun": "4.0.0-rc.
|
|
86
|
-
"effect": "4.0.0-rc.
|
|
87
|
-
"react": "19.3.0-canary-
|
|
88
|
-
"react-dom": "19.3.0-canary-
|
|
84
|
+
"@effect/platform-browser": "4.0.0-rc.113",
|
|
85
|
+
"@effect/platform-bun": "4.0.0-rc.113",
|
|
86
|
+
"effect": "4.0.0-rc.113",
|
|
87
|
+
"react": "19.3.0-canary-1d34f91d-20260909",
|
|
88
|
+
"react-dom": "19.3.0-canary-1d34f91d-20260909",
|
|
89
89
|
"react-server-dom-rspack": "0.1.0"
|
|
90
90
|
},
|
|
91
91
|
"engines": {
|