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.
@@ -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)=>Stream.fromReadableStream({
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(Effect.context(), (requestContext)=>{
165
- const RequestContextMiddleware = HttpRouter.middleware()((httpEffect)=>httpEffect.pipe(Effect.provideContext(requestContext)));
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
- })).pipe(Layer.provide(RequestLayer));
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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAoE;AACR;AACe;AAQ7C;AAG8D;AAC7B;AAK5B;AAGiD;AACpC;AACW;AACD;AACP;AACa;AAMvC;AAKI;AAE7B,MAAM2B,cAAcA,GAAGxB,cAAc,CAACkB,oBAAoB,EAAEC,kBAAkB,EAAE,IAAI,CAClFnB,aAAa,CAACiB,wBAAwB;AAGxC,MAAMQ,iBAAiBA,GAAGzB,YAAY,CACpCD,UAAU,CAACuB,YAAYA,EAAE,CAAC,EAAEI,wBAAwB,EAAEC,gBAAgB,EAAE,GACtEnB,sBAAsB,CAAC;QACrB,cAAckB;QACd,QAAQb,uBAAuBA;QAC/B,MAAMc;IACR,GAAG,IAAI,CAAC3B,aAAa,CAACK,wBAAwB;AAIlD,MAAMuB,iBAAiBA,GAAG5B,YAAY,CACpCD,UAAU,CAACuB,YAAYA,EAAE,CAAC,EAAEO,gBAAgB,EAAE,GAC5CrB,sBAAsB,CAAC;QACrB,cAAc;QACd,MAAMqB;IACR;AAIJ,+FAA+F;AAC/F,gDAAgD;AAChD,MAAMC,cAAcA,GAAG9B,YAAY,CACjCD,UAAU,CAACuB,YAAYA,EAAE,CAAC,EAAES,QAAQ,EAAEC,IAAI,EAAE,GAC1CnC,mEAAmB,CAAC;QAClB,aAAa;QACbkC;QACA,aAAaX,6BAA6BA;QAC1C,oBAAoBC,kCAAkCA;QACtDW;IACF;AAIJ,MAAMC,sBAAsBA,GAAsBC,OAAO,MAAM,CAAC,CAAC;AACjE,MAAMC,sBAAsBA,GAAG;IAC7B,iBAAiB;AACnB;AAEA,MAAMC,gBAAgBA,GAAG,CAACC;IACxB,IAAIA,SAASC,aAAaD,KAAK,IAAI,OAAO,IAAI;QAC5C,OAAO;IACT;IAEA,MAAME,SAASF,KAAK,KAAK,CAAC,KAAK,GAAG,CAAC,CAACG,QAAUA,MAAM,IAAI,GAAG,WAAW;IACtE,OAAOD,OAAO,QAAQ,CAAC,QAAQA,OAAO,QAAQ,CAAC,YAAYF,OAAO,GAAGA,KAAK,QAAQ,CAAC;AACrF;AAEA,MAAMI,4BAA4BA,GAAkC,CAACC,UAAUC,WAC7E5C,cAAc,CACZQ,4BAA4B,CAACoC,UAAU,QAAQP,gBAAgBA,CAACO,SAAS,OAAO,CAAC,OAAO;AAS5F,MAAMC,aAAaA,GAAG,CACpBC,QACAC,UAEAhD,4EAA4B,CAAC;QAC3B,UAAU,IAAM+C;QAChB,SAAS,CAACE,QAAUA;QACpB,kBAAkBD,SAAS;IAC7B;AAEF,MAAME,qBAAqBA,GAAG,CAC5BC,YACAC,OAEAD,WACG,KAAK,CAAC,GAAG,CAAC,GACV,WAAW,CACV,CAACE,UAAUC,UAAYD,SAAS,OAAO,CAACvC,uBAAuBA,CAACwC,WAChExC,uBAAuBA,CAACsC;AAoB9B,MAAMG,SAASA,GAAG,CAChBC;IAEA,MAAMC,mBAAmB9C,mBAAmBA,CAAC6C;IAC7C,MAAME,WAAW9C,eAAeA,CAAC4C;IACjC,MAAMG,SAAS1D,iBAAiB,CAAC,UAAW,EAC1C2D,WAAW,EACXC,SAAS,EACTV,UAAU,EACVW,OAAO,EACPC,cAAc,EACdC,MAAM,EACNC,mBAAmB,EACK;QACxB,MAAMC,aAAa1D,uBAAuB,CAACsD;QAC3C,IAAI3D,aAAa,CAAC+D,eAAe,CAAClD,cAAcA,CAACkD,WAAW,KAAK,CAAC,QAAQ,GAAG;YAC3E,OAAO,OAAOjE,UAAU,CACtB,IAAIkE,UAAU,CAAC,sBAAsB,EAAEL,QAAQ,WAAW,CAAC,8BAA8B,CAAC;QAE9F;QAEA,MAAMM,WAAWF,WAAW,KAAK,CAAC,QAAQ;QAC1C,MAAMG,gBAAgB,OAAOT,YAAY,IAAI,CAAC,YAAY,KAAK,OAC3D3D,cAAc,CAACkC,sBAAsBA,IACrC5B,iBAAiB;QACrB,MAAM+D,iBAAiBrE,iBAAiB,CAAC,UAAWsE,MAAkB;YACpE,MAAMC,YAAYtD,eAAeA,CAAC;gBAChC0C;gBACAW;gBACAH;YACF;YACA,MAAMK,iBAAiB,OAAOrD,cAAcA;YAC5C,MAAMsD,SAAS,OAAOD,eAAe,MAAM,CAAC;gBAC1CZ;gBACAV;gBACA,eAAeO,SAAS,aAAa;gBACrCc;gBACAT;gBACAE;YACF;YAEA,IAAIH,QAAQ,OAAO,CAAC,SAAS,KAAK7C,eAAeA,EAAE;gBACjD,OAAOR,yBAAyB,CAC9BqC,aAAaA,CAAC4B,OAAO,MAAM,EAAE;oBAAE,kBAAkB;gBAAK,GAAG,IAAI,CAC3DrE,eAAe,CAACqE,OAAO,OAAO,IAEhC;oBACE,aAAa,GAAGzD,eAAeA,CAAC,cAAc,CAAC;oBAC/C,SAAS;wBACP,GAAGoB,sBAAsB;oBAC3B;oBACA2B;gBACF;YAEJ;YAEA,MAAMW,eAAe,OAAOtD,YAAYA;YACxC,MAAMuD,aAAa,OAAOD,aACvB,MAAM,CAAC;gBAAED;gBAAQb;YAAU,GAC3B,IAAI,CAAC5D,cAAc,CAAC,IAAMyE,OAAO,OAAO;YAE3C,OAAOjE,yBAAyB,CAC9BqC,aAAaA,CAAC8B,YAAY,IAAI,CAACvE,eAAe,CAACqE,OAAO,OAAO,IAC7D;gBACE,aAAa;gBACb,SAASrC,sBAAsBA;gBAC/B2B;YACF;QAEJ;QAEA,IAAIF,QAAQ,MAAM,KAAK,UAAUF,YAAY,IAAI,CAAC,YAAY,KAAK,MAAM;YACvE,OAAO,OAAOxD,mBAAmB,CAACwD,YAAY,IAAI,CAAC,YAAY,EAAES,eAAe,IAAI,CAClFpE,kBAAkB,CAAC;gBACjB,WAAW,IACTA,cAAc,CACZQ,wBAAwB,CAAC;wBAAE,QAAQ;wBAAK,SAAS4B,sBAAsBA;oBAAC;gBAE5E,WAAW,CAACwC,QAAUP,eAAe;wBAAE,MAAM;wBAAWO;oBAAM;YAChE;QAEJ;QACA,OAAO,OAAOP,eAAe;YAAE,MAAM;YAAW,OAAOD;QAAc;IACvE;IAEA,MAAMS,4BAA4B,CAChCC,UACAnB,aACAE;QAEA,MAAMkB,oBAAoBpB,YAAY,UAAU,CAAC,MAAM,CACrD,CAACT,aAAe,CAAC4B,SAAS,UAAU,CAAC,QAAQ,CAAC5B;QAEhD,MAAM8B,mBACJD,kBAAkB,MAAM,KAAK,IACzBD,SAAS,UAAU,GACnB3C,OAAO,MAAM,CAAC;eAAI2C,SAAS,UAAU;eAAKC;SAAkB;QAClE,MAAMnC,WAAWkC,SAAS,OAAO,CAAC,IAAI,CACpC9E,cAAc,CAAC,CAACiF;YACd,MAAMC,UAAUxB,OAAO;gBACrB,GAAGuB,OAAO;gBACVtB;gBACA,YAAYqB;gBACZnB;YACF;YACA,OAAOjD,eAAeA,CAACmE,mBAAmBG;QAC5C;QAGF,OAAOtE,eAAeA,CAACkE,SAAS,UAAU,EAAElC;IAC9C;IAEA,MAAMuC,eAAelF,cAAc,CAACwB,cAAcA,EAAE+B,iBAAiB,KAAK;IAC1E,MAAM4B,yBAAyBnF,YAAY,CACzCD,UAAU,CAACC,WAAW,CAACkF,eAAe,CAACE;QACrC,MAAMC,2BAA2BhF,qBAAqB,GAEjD,CAACiF,aACJA,WAAW,IAAI,CAACvF,qBAAqB,CAACqF;QAExC,MAAMG,iBAAiB,CAAC7B;YACtB,MAAM8B,WAAWnF,cAAc,CAAC,OAAOqD,YAAY,OAAO,EAAE,CAACE,UAC3DH,OAAO;oBACLC;oBACA,WAAW;oBACX,YAAYA,YAAY,UAAU;oBAClCE;oBACA,gBAAgB;oBAChB,QAAQ;gBACV,GAAG,IAAI,CAACxD,iCAAiC,CAACqC,4BAA4BA;YAExE,MAAMgD,qBAAqB/B,YAAY,UAAU,CAAC,EAAE,CAAC,CAAC;YACtD,MAAMgC,iBACJD,uBAAuBnD,YACnB+C,2BACArC,qBAAqBA,CAACU,YAAY,UAAU,EAAE+B,oBAAoB,OAAO,CACvEJ;YAER,MAAMM,YAAYH,SAAS,IAAI,CAACxF,aAAa,CAAC0F,eAAe,KAAK;YAClE,MAAME,gBAAgBvF,cAAc,CAAC,QAAQqD,YAAY,OAAO,EAAE,CAACE,UACjErC,sBAAsBA,CAACqC,SAASJ,UAAU,IAAI,CAC5CzD,cAAc,CAAC,CAAC8E,WAAaD,0BAA0BC,UAAUnB,aAAaE,WAC9E7D,eAAe,CAAC,wBAAwB,CAAC8F,QACvC9F,cAAc,CACZQ,uBAAuB,CAACsF,MAAM,OAAO,EAAE;wBACrC,SAAS1D,sBAAsBA;wBAC/B,QAAQ0D,MAAM,MAAM;oBACtB,MAGJzF,iCAAiC,CAACqC,4BAA4BA,IAEhE,IAAI,CAACzC,aAAa,CAACqF,yBAAyB,KAAK;YAEnD,OAAOrF,cAAc,CAAC2F,WAAWC;QACnC;QACA,MAAM,CAACE,kBAAkB,GAAGC,sBAAsB,GAAGxC,iBAAiB,MAAM;QAC5E,OAAOvD,cAAc,CACnBuF,eAAeO,sBACZC,sBAAsB,GAAG,CAACR;IAEjC;IAGF,OAAOvF,cAAc,CAACyB,iBAAiBA,EAAEG,iBAAiBA,EAAE,IAAI,CAC9D5B,kBAAkB,CAACmF;AAEvB;AAEA,MAAMa,WAAWA,GAAG,CAClB1C,cAEAjD,gBAAgB,CAACgD,SAASA,CAACC,cAAc,IAAI,CAACtD,aAAa,CAAC8B,cAAcA;AAErE,MAAMmE,iBAAiBA,GAAG;IAAE5C,oBAASA;IAAE2C,wBAAWA;AAAC,EAAE"}
@@ -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",
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://github.com/nikhilsnayak/effective-rsc#readme",
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.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.18.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.112",
69
- "@effect/platform-bun": "4.0.0-rc.112",
70
- "@effect/vitest": "4.0.0-rc.112",
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.1",
74
- "@types/react": "19.2.18",
75
- "@types/react-dom": "19.2.7",
76
- "effect": "4.0.0-rc.112",
77
- "react": "19.3.0-canary-8425b691-20260904",
78
- "react-dom": "19.3.0-canary-8425b691-20260904",
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": "^4.1.11"
81
+ "vitest": "^5.0.0"
82
82
  },
83
83
  "peerDependencies": {
84
- "@effect/platform-browser": "4.0.0-rc.112",
85
- "@effect/platform-bun": "4.0.0-rc.112",
86
- "effect": "4.0.0-rc.112",
87
- "react": "19.3.0-canary-8425b691-20260904",
88
- "react-dom": "19.3.0-canary-8425b691-20260904",
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": {