effective-rsc 0.1.0 → 0.1.2
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 +54 -10
- package/README.md +3 -3
- package/dist/application/page.d.ts +14 -7
- package/dist/application/page.js +5 -3
- package/dist/application/page.js.map +1 -1
- package/dist/application/route-graph.d.ts +1 -1
- package/dist/application/route-graph.js.map +1 -1
- package/dist/application/server-fn.d.ts +10 -6
- package/dist/application/server-fn.js +9 -4
- package/dist/application/server-fn.js.map +1 -1
- package/dist/build/dev.d.ts +11 -11
- package/dist/build/dev.js +21 -5
- package/dist/build/dev.js.map +1 -1
- package/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -1
- package/dist/client/application.js +12 -9
- package/dist/client/application.js.map +1 -1
- package/dist/client/browser-capabilities.d.ts +2 -9
- package/dist/client/browser-capabilities.js +3 -14
- package/dist/client/browser-capabilities.js.map +1 -1
- package/dist/client/browser-render-status.d.ts +25 -0
- package/dist/client/browser-render-status.js +20 -0
- package/dist/client/browser-render-status.js.map +1 -0
- package/dist/client/call-server.js +7 -2
- package/dist/client/call-server.js.map +1 -1
- package/dist/client/navigation-api.js +5 -4
- package/dist/client/navigation-api.js.map +1 -1
- package/dist/client/react-dom-renderer.d.ts +3 -2
- package/dist/client/react-dom-renderer.js +43 -2
- package/dist/client/react-dom-renderer.js.map +1 -1
- package/dist/client/route-refresh.d.ts +1 -2
- package/dist/client/route-refresh.js +5 -18
- package/dist/client/route-refresh.js.map +1 -1
- package/dist/dev/client.d.ts +2 -1
- package/dist/dev/client.js +46 -6
- package/dist/dev/client.js.map +1 -1
- package/dist/dev/panel.d.ts +12 -1
- package/dist/dev/panel.js +73 -5
- package/dist/dev/panel.js.map +1 -1
- package/dist/dev/runtime-failure.d.ts +1 -0
- package/dist/dev/runtime-failure.js +7 -1
- package/dist/dev/runtime-failure.js.map +1 -1
- package/dist/rsc/render-route-tree.d.ts +3 -3
- package/dist/rsc/render-route-tree.js +2 -2
- package/dist/rsc/render-route-tree.js.map +1 -1
- package/dist/server/application.js +54 -35
- package/dist/server/application.js.map +1 -1
- package/dist/server/server-fn-request.js +3 -1
- package/dist/server/server-fn-request.js.map +1 -1
- package/docs/02-guides/01-server-functions/50_greet.ts +18 -0
- package/docs/02-guides/01-server-functions/60_greeting-form.tsx +23 -0
- package/docs/02-guides/01-server-functions/index.md +7 -0
- package/docs/02-guides/03-routing/index.md +5 -1
- package/docs/03-advanced/02-client-navigation/index.md +6 -3
- package/docs/03-advanced/03-server-function-execution-and-refresh/index.md +3 -1
- package/docs/04-api-reference/02-page/index.md +8 -3
- package/docs/04-api-reference/06-middleware/index.md +2 -2
- package/docs/04-api-reference/08-server-fn/index.md +23 -0
- package/package.json +1 -1
package/LLMS.md
CHANGED
|
@@ -75,12 +75,19 @@ Callers pass the Schema's encoded type and the handler receives its decoded type
|
|
|
75
75
|
input; a function returning `void` can then be passed directly to `<form action>`. Let the Schema
|
|
76
76
|
infer the handler parameter.
|
|
77
77
|
|
|
78
|
+
For form feedback with `useActionState`, use `input: [StateSchema, FormSchema]` and
|
|
79
|
+
`handler: (previousState, form) => ...`. React supplies both arguments; ERSC validates and decodes
|
|
80
|
+
each one. Keep the native Server Function reference intact when passing it to `useActionState`
|
|
81
|
+
to retain progressive enhancement. A single Array or Tuple Schema still describes one argument.
|
|
82
|
+
|
|
78
83
|
A successful invocation refreshes the current route.
|
|
79
84
|
|
|
80
85
|
- **[Creating the Server Function authoring module](./docs/02-guides/01-server-functions/10_ersc.ts)**
|
|
81
86
|
- **[Defining a Server Function](./docs/02-guides/01-server-functions/20_follow-author.ts)**: ERSC decodes FormData before running the Effect handler.
|
|
82
87
|
- **[Rendering a direct form action](./docs/02-guides/01-server-functions/30_follow-author-button.tsx)**: A FormData Server Function can be passed directly to form action.
|
|
83
88
|
- **[Closing the Server Function application](./docs/02-guides/01-server-functions/40_application.tsx)**
|
|
89
|
+
- **[Defining a stateful form action](./docs/02-guides/01-server-functions/50_greet.ts)**: A schema list decodes React's previous state and submitted FormData separately.
|
|
90
|
+
- **[Rendering a stateful form](./docs/02-guides/01-server-functions/60_greeting-form.tsx)**: Pass the native reference to useActionState so React also owns progressive form submission.
|
|
84
91
|
|
|
85
92
|
## Services
|
|
86
93
|
|
|
@@ -101,7 +108,11 @@ renderer's inferred service requirements.
|
|
|
101
108
|
- Routes are immutable and belong to one ERSC identity.
|
|
102
109
|
- `page(path, page)` attaches a Page; `mount(prefix, routes)` nests a route scope.
|
|
103
110
|
- Mounted scopes retain their Layout and Loading ancestry.
|
|
104
|
-
-
|
|
111
|
+
- On GET/HEAD, the request handler decodes Page parameters once before rendering, with services
|
|
112
|
+
from existing route middleware available. Rejected parameters return an empty `404`, including
|
|
113
|
+
navigation Flight.
|
|
114
|
+
- Server Function POST refreshes keep parameter rejection in React's render-error path, preserving
|
|
115
|
+
the completed action result.
|
|
105
116
|
- Effect HTTP owns route matching; ERSC rejects duplicate shapes and invalid composition while
|
|
106
117
|
building the graph.
|
|
107
118
|
|
|
@@ -172,9 +183,12 @@ Give work that must outlive a request an explicit application-owned scope.
|
|
|
172
183
|
|
|
173
184
|
ERSC handles eligible document navigations through the browser Navigation API and
|
|
174
185
|
`NavigationPrecommitController`. There is no History API fallback. A browser missing either one
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
186
|
+
still hydrates Client Components and supports Server Functions and streamed current-page refreshes,
|
|
187
|
+
including HMR. Links use full-page navigation instead of the client router. Without JavaScript,
|
|
188
|
+
the server-rendered document retains working links and natively submitted forms.
|
|
189
|
+
|
|
190
|
+
Development reports a missing navigation API in the console and a dismissible development-panel
|
|
191
|
+
warning. The warning does not block interaction and is absent in production.
|
|
178
192
|
|
|
179
193
|
An intercepted Page navigation has two milestones:
|
|
180
194
|
|
|
@@ -243,7 +257,9 @@ Flight EOF. Disconnecting interrupts unfinished request work and the response st
|
|
|
243
257
|
Hydrated invocations may execute concurrently. Only the latest invocation may apply its response's
|
|
244
258
|
route tree while its original history entry remains current and no navigation is active. Other
|
|
245
259
|
responses trigger a fresh current-route refresh. A response tree interrupts any older current-route
|
|
246
|
-
refresh before rendering.
|
|
260
|
+
refresh before rendering, then rechecks applicability after cleanup completes. Effect owns refresh
|
|
261
|
+
loading and cancellation; the React Transition publishes the tree without waiting for its own
|
|
262
|
+
commit inside an async Action.
|
|
247
263
|
|
|
248
264
|
After a successful mutation, ERSC clears the Back/Forward traversal cache because any route may have
|
|
249
265
|
changed.
|
|
@@ -273,9 +289,14 @@ services and register native Effect HTTP on the framework router.
|
|
|
273
289
|
the Schema's encoded keys must exactly match the path parameters and accept strings. Compose the
|
|
274
290
|
Page with `Routes.page`.
|
|
275
291
|
|
|
276
|
-
Pages produce React output.
|
|
277
|
-
|
|
278
|
-
|
|
292
|
+
Pages produce React output. On GET/HEAD, the request handler decodes parameters once before
|
|
293
|
+
rendering, with services from existing route middleware available. Rejected parameters receive
|
|
294
|
+
an empty `404`, including navigation Flight requests; unmatched routes also receive native `404`
|
|
295
|
+
responses. Other failures keep their existing
|
|
296
|
+
error behavior.
|
|
297
|
+
|
|
298
|
+
Server Function POST refreshes decode parameters inside Page rendering. A rejection follows React's
|
|
299
|
+
render-error path without replacing the completed Server Function result with a `404`.
|
|
279
300
|
|
|
280
301
|
## Layout
|
|
281
302
|
|
|
@@ -318,10 +339,10 @@ middleware across mounted scopes runs once.
|
|
|
318
339
|
| -------------------------------- | ------------------------------------ | --------------------- | ------------------------ |
|
|
319
340
|
| Page GET/HEAD | Matched chain | No | Yes |
|
|
320
341
|
| Hydrated Server Function POST | Remaining route chain around refresh | Server Function chain | Yes |
|
|
321
|
-
| Progressive Server Function POST |
|
|
342
|
+
| Progressive Server Function POST | Remaining route chain around refresh | Server Function chain | Yes |
|
|
322
343
|
| Userland HTTP, assets, unmatched | No | No | Yes |
|
|
323
344
|
|
|
324
|
-
During a
|
|
345
|
+
During a Server Function request, middleware already active for the Server Function is not
|
|
325
346
|
executed again for the refreshed route, even if it appears at another position in that route chain.
|
|
326
347
|
Remaining route middleware wraps refreshed rendering.
|
|
327
348
|
|
|
@@ -350,6 +371,12 @@ decodes the invocation payload and infers the handler parameter; do not annotate
|
|
|
350
371
|
returns an Effect whose requirements fit the ERSC service universe. The client reference accepts the
|
|
351
372
|
Schema's encoded type and resolves `Promise<Output>`; the handler receives its decoded type.
|
|
352
373
|
|
|
374
|
+
For multiple positional arguments, supply a readonly schema list as `input`. Each caller argument
|
|
375
|
+
uses its Schema's encoded type; each handler argument uses its decoded type, in the same order.
|
|
376
|
+
Inline lists infer their tuple shape without `as const`. Use `input: []` for no arguments.
|
|
377
|
+
`input: Schema.Array(...)` and `input: Schema.Tuple(...)` still describe one argument, not a
|
|
378
|
+
positional argument list.
|
|
379
|
+
|
|
353
380
|
```ts
|
|
354
381
|
const followAuthor = ERSC.ServerFn.make({
|
|
355
382
|
input: Schema.Struct({ authorId: Schema.NonEmptyString }),
|
|
@@ -375,6 +402,23 @@ const followAuthorForm = ERSC.ServerFn.make({
|
|
|
375
402
|
A ServerFn created from a derived view activates its middleware for the POST. The Middleware
|
|
376
403
|
reference defines refresh reach and ordering.
|
|
377
404
|
|
|
405
|
+
For a `useActionState` form, declare both the previous state and submitted FormData:
|
|
406
|
+
|
|
407
|
+
```ts
|
|
408
|
+
const StateSchema = Schema.Struct({ message: Schema.String });
|
|
409
|
+
const FormSchema = Schema.fromFormData(Schema.Struct({ name: Schema.NonEmptyString }));
|
|
410
|
+
|
|
411
|
+
const greet = ERSC.ServerFn.make({
|
|
412
|
+
input: [StateSchema, FormSchema],
|
|
413
|
+
handler: (_previousState, { name }) => Effect.succeed({ message: `Hello, ${name}` }),
|
|
414
|
+
});
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
Pass the native reference directly to `useActionState(greet, { message: '' })` and its returned
|
|
418
|
+
action to `<form action>`. React supplies previous state and FormData for hydrated and progressive
|
|
419
|
+
submissions. Previous state is client input: validate it, but never trust it for authorization or
|
|
420
|
+
authoritative application state. Native `.bind` can prefill leading arguments.
|
|
421
|
+
|
|
378
422
|
Direct server invocation throws. Encode expected failure in a discriminated output union; unexpected
|
|
379
423
|
failures reject the Promise. Browser requests require an Origin matching the application host and
|
|
380
424
|
may contain at most 10 MiB. See the
|
package/README.md
CHANGED
|
@@ -24,9 +24,9 @@ native RSC support.
|
|
|
24
24
|
## Requirements
|
|
25
25
|
|
|
26
26
|
- Bun 1.4 or newer is the only supported server runtime.
|
|
27
|
-
- Client navigation
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
- Client navigation requires the Navigation API and `NavigationPrecommitController`; there is no
|
|
28
|
+
History API fallback. Browsers without them still hydrate Client Components and support Server
|
|
29
|
+
Functions, but links use full-page navigation. Without JavaScript, links and native forms still work.
|
|
30
30
|
- React, React DOM, Effect, Effect's browser and Bun platforms, and
|
|
31
31
|
`react-server-dom-rspack` must use the exact compatible versions shown below.
|
|
32
32
|
|
|
@@ -25,19 +25,26 @@ export type PageConcern<out ParamNames extends string, out Mode extends 'Paramet
|
|
|
25
25
|
readonly paramNames: Types.Covariant<ParamNames>;
|
|
26
26
|
};
|
|
27
27
|
};
|
|
28
|
-
export type
|
|
29
|
-
export type
|
|
30
|
-
readonly
|
|
28
|
+
export type EncodedPageParams = Readonly<Record<string, string | undefined>>;
|
|
29
|
+
export type PageParams = {
|
|
30
|
+
readonly _tag: 'Encoded';
|
|
31
|
+
readonly value: EncodedPageParams;
|
|
32
|
+
} | {
|
|
33
|
+
readonly _tag: 'Decoded';
|
|
34
|
+
readonly value: Readonly<Record<string, unknown>>;
|
|
31
35
|
};
|
|
32
|
-
export type
|
|
36
|
+
export type PageRuntimeProps = {
|
|
37
|
+
readonly params: PageParams;
|
|
38
|
+
};
|
|
39
|
+
export type PageComponent = (props: PageRuntimeProps) => Promise<Awaited<ReactNode>>;
|
|
33
40
|
export type StaticPageDefinition<Services> = ERSCStatefulMember<Services, 'Page', PageImplementationState> & PageConcern<never, 'Static'>;
|
|
34
41
|
export type ParameterizedPageDefinition<Services, ParamNames extends string = string> = ERSCStatefulMember<Services, 'Page', PageImplementationState> & PageConcern<ParamNames, 'Parameterized'>;
|
|
35
42
|
export type AnyPageDefinition<Services> = StaticPageDefinition<Services> | ParameterizedPageDefinition<Services>;
|
|
36
|
-
export type PageImplementationState = {
|
|
43
|
+
export type PageImplementationState<Services = unknown> = {
|
|
37
44
|
readonly component: PageComponent;
|
|
38
|
-
readonly paramsSchema:
|
|
45
|
+
readonly paramsSchema: PageParamsSchema<Services> | null;
|
|
39
46
|
};
|
|
40
|
-
export declare
|
|
47
|
+
export declare function getPageState<Services>(page: AnyPageDefinition<Services>): PageImplementationState<Services>;
|
|
41
48
|
type StaticPageOptions<Error, Services> = {
|
|
42
49
|
readonly params?: never;
|
|
43
50
|
readonly render: () => Effect.Effect<Awaited<ReactNode>, Error, Services>;
|
package/dist/application/page.js
CHANGED
|
@@ -20,18 +20,20 @@ class PageDefinitionImpl {
|
|
|
20
20
|
Object.freeze(this);
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
-
|
|
23
|
+
// The compiled destination installs the Page's complete middleware chain before decoding.
|
|
24
|
+
// As with scoped middleware, its provided services are erased from the application contract.
|
|
25
|
+
function getPageState(page) {
|
|
24
26
|
if (!isERSCMember(page, 'Page')) {
|
|
25
27
|
throw new TypeError('Page must be created with ERSC.Page.make.');
|
|
26
28
|
}
|
|
27
29
|
return page[ERSCStateTypeId];
|
|
28
|
-
}
|
|
30
|
+
}
|
|
29
31
|
const makePageFactory = (identity, middleware)=>{
|
|
30
32
|
function make(options) {
|
|
31
33
|
if ('params' in options) {
|
|
32
34
|
const { params: paramsSchema, render } = options;
|
|
33
35
|
const decodeParams = Schema.decodeUnknownEffect(paramsSchema);
|
|
34
|
-
const component = ({ params })=>identity.renderRuntime.run('Page', decodeParams(params).pipe(Effect.flatMap((decodedParams)=>Effect.suspend(()=>render({
|
|
36
|
+
const component = ({ params })=>identity.renderRuntime.run('Page', (params._tag === 'Decoded' ? Effect.succeed(params.value) : decodeParams(params.value)).pipe(Effect.flatMap((decodedParams)=>Effect.suspend(()=>render({
|
|
35
37
|
params: decodedParams
|
|
36
38
|
})))), middleware);
|
|
37
39
|
return new PageDefinitionImpl(identity, component, paramsSchema);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"application/page.js","sources":["../../src/application/page.ts"],"sourcesContent":["import { Effect, Schema, type Types } from 'effect';\nimport type { ReactNode } from 'react';\n\nimport {\n type ERSCIdentity,\n ERSCIdentityTypeId,\n isERSCMember,\n ERSCMemberKindTypeId,\n type ERSCStatefulMember,\n ERSCStateTypeId,\n} from './ersc-identity';\nimport type { AnyMiddleware } from './middleware';\nimport type { ValidRouteParamName } from './route-path';\n\ndeclare const PageContractTypeId: unique symbol;\n\nexport type PageParamsSchema<Services> = Schema.ConstraintCodec<\n Readonly<Record<string, unknown>>,\n Readonly<Record<string, unknown>>,\n Services,\n unknown\n>;\n\ntype PageParamKeys<ParamsSchema> = ParamsSchema extends { readonly Encoded: infer Encoded }\n ? Extract<keyof Encoded, string>\n : never;\ntype NonStringPageParamKeys<ParamsSchema> = ParamsSchema extends {\n readonly Encoded: infer Encoded;\n}\n ? Exclude<keyof Encoded, string>\n : never;\ntype InvalidPageParamName<Name extends string> =\n Name extends ValidRouteParamName<Name> ? never : Name;\ntype InvalidPageParamValueKeys<ParamsSchema> = ParamsSchema extends {\n readonly Encoded: infer Encoded;\n}\n ? {\n [Key in Extract<keyof Encoded, string>]-?: unknown extends Encoded[Key]\n ? never\n : [Extract<Encoded[Key], string>] extends [never]\n ? Key\n : never;\n }[Extract<keyof Encoded, string>]\n : never;\ntype InvalidPageParamsSchema<ParamsSchema> =\n | NonStringPageParamKeys<ParamsSchema>\n | InvalidPageParamName<PageParamKeys<ParamsSchema>>\n | InvalidPageParamValueKeys<ParamsSchema>;\ntype ValidPageParamsSchema<ParamsSchema> = [PageParamKeys<ParamsSchema>] extends [never]\n ? never\n : string extends PageParamKeys<ParamsSchema>\n ? never\n : [InvalidPageParamsSchema<ParamsSchema>] extends [never]\n ? unknown\n : never;\n\nexport type PageConcern<\n out ParamNames extends string,\n out Mode extends 'Parameterized' | 'Static',\n> = {\n readonly [PageContractTypeId]: {\n readonly mode: Types.Covariant<Mode>;\n readonly paramNames: Types.Covariant<ParamNames>;\n };\n};\n\nexport type
|
|
1
|
+
{"version":3,"file":"application/page.js","sources":["../../src/application/page.ts"],"sourcesContent":["import { Effect, Schema, type Types } from 'effect';\nimport type { ReactNode } from 'react';\n\nimport {\n type ERSCIdentity,\n ERSCIdentityTypeId,\n isERSCMember,\n ERSCMemberKindTypeId,\n type ERSCStatefulMember,\n ERSCStateTypeId,\n} from './ersc-identity';\nimport type { AnyMiddleware } from './middleware';\nimport type { ValidRouteParamName } from './route-path';\n\ndeclare const PageContractTypeId: unique symbol;\n\nexport type PageParamsSchema<Services> = Schema.ConstraintCodec<\n Readonly<Record<string, unknown>>,\n Readonly<Record<string, unknown>>,\n Services,\n unknown\n>;\n\ntype PageParamKeys<ParamsSchema> = ParamsSchema extends { readonly Encoded: infer Encoded }\n ? Extract<keyof Encoded, string>\n : never;\ntype NonStringPageParamKeys<ParamsSchema> = ParamsSchema extends {\n readonly Encoded: infer Encoded;\n}\n ? Exclude<keyof Encoded, string>\n : never;\ntype InvalidPageParamName<Name extends string> =\n Name extends ValidRouteParamName<Name> ? never : Name;\ntype InvalidPageParamValueKeys<ParamsSchema> = ParamsSchema extends {\n readonly Encoded: infer Encoded;\n}\n ? {\n [Key in Extract<keyof Encoded, string>]-?: unknown extends Encoded[Key]\n ? never\n : [Extract<Encoded[Key], string>] extends [never]\n ? Key\n : never;\n }[Extract<keyof Encoded, string>]\n : never;\ntype InvalidPageParamsSchema<ParamsSchema> =\n | NonStringPageParamKeys<ParamsSchema>\n | InvalidPageParamName<PageParamKeys<ParamsSchema>>\n | InvalidPageParamValueKeys<ParamsSchema>;\ntype ValidPageParamsSchema<ParamsSchema> = [PageParamKeys<ParamsSchema>] extends [never]\n ? never\n : string extends PageParamKeys<ParamsSchema>\n ? never\n : [InvalidPageParamsSchema<ParamsSchema>] extends [never]\n ? unknown\n : never;\n\nexport type PageConcern<\n out ParamNames extends string,\n out Mode extends 'Parameterized' | 'Static',\n> = {\n readonly [PageContractTypeId]: {\n readonly mode: Types.Covariant<Mode>;\n readonly paramNames: Types.Covariant<ParamNames>;\n };\n};\n\nexport type EncodedPageParams = Readonly<Record<string, string | undefined>>;\nexport type PageParams =\n | { readonly _tag: 'Encoded'; readonly value: EncodedPageParams }\n | { readonly _tag: 'Decoded'; readonly value: Readonly<Record<string, unknown>> };\nexport type PageRuntimeProps = {\n readonly params: PageParams;\n};\nexport type PageComponent = (props: PageRuntimeProps) => Promise<Awaited<ReactNode>>;\n\nexport type StaticPageDefinition<Services> = ERSCStatefulMember<\n Services,\n 'Page',\n PageImplementationState\n> &\n PageConcern<never, 'Static'>;\nexport type ParameterizedPageDefinition<\n Services,\n ParamNames extends string = string,\n> = ERSCStatefulMember<Services, 'Page', PageImplementationState> &\n PageConcern<ParamNames, 'Parameterized'>;\nexport type AnyPageDefinition<Services> =\n | StaticPageDefinition<Services>\n | ParameterizedPageDefinition<Services>;\n\nexport type PageImplementationState<Services = unknown> = {\n readonly component: PageComponent;\n readonly paramsSchema: PageParamsSchema<Services> | null;\n};\n\nclass PageDefinitionImpl<\n Services,\n ParamNames extends string,\n Mode extends 'Parameterized' | 'Static',\n ParamsSchema extends PageParamsSchema<unknown> | null,\n>\n implements\n ERSCStatefulMember<Services, 'Page', PageImplementationState>,\n PageConcern<ParamNames, Mode>\n{\n declare readonly [PageContractTypeId]: {\n readonly mode: Types.Covariant<Mode>;\n readonly paramNames: Types.Covariant<ParamNames>;\n };\n readonly [ERSCIdentityTypeId]: ERSCIdentity<Services>;\n readonly [ERSCMemberKindTypeId] = 'Page' as const;\n get [ERSCStateTypeId](): PageImplementationState {\n return this;\n }\n readonly component: PageComponent;\n readonly paramsSchema: ParamsSchema;\n\n constructor(\n identity: ERSCIdentity<Services>,\n component: PageComponent,\n paramsSchema: ParamsSchema,\n ) {\n this[ERSCIdentityTypeId] = identity;\n this.component = component;\n this.paramsSchema = paramsSchema;\n Object.freeze(this);\n }\n}\n\nexport function getPageState<Services>(\n page: AnyPageDefinition<Services>,\n): PageImplementationState<Services>;\n// The compiled destination installs the Page's complete middleware chain before decoding.\n// As with scoped middleware, its provided services are erased from the application contract.\nexport function getPageState(page: AnyPageDefinition<unknown>): PageImplementationState {\n if (!isERSCMember(page, 'Page')) {\n throw new TypeError('Page must be created with ERSC.Page.make.');\n }\n return page[ERSCStateTypeId];\n}\n\ntype StaticPageOptions<Error, Services> = {\n readonly params?: never;\n readonly render: () => Effect.Effect<Awaited<ReactNode>, Error, Services>;\n};\ntype ParameterizedPageOptions<ParamsSchema extends PageParamsSchema<Services>, Error, Services> = {\n readonly params: ParamsSchema;\n readonly render: (props: {\n readonly params: ParamsSchema['Type'];\n }) => Effect.Effect<Awaited<ReactNode>, Error, Services>;\n};\n\nexport type PageFactory<ApplicationServices, AvailableServices> = {\n readonly make: {\n <ParamsSchema extends PageParamsSchema<AvailableServices>, Error>(\n options: ParameterizedPageOptions<ParamsSchema, Error, AvailableServices> &\n ValidPageParamsSchema<ParamsSchema>,\n ): ParameterizedPageDefinition<ApplicationServices, PageParamKeys<ParamsSchema>>;\n <Error>(\n options: StaticPageOptions<Error, AvailableServices>,\n ): StaticPageDefinition<ApplicationServices>;\n };\n};\n\nexport const makePageFactory = <ApplicationServices, AvailableServices>(\n identity: ERSCIdentity<ApplicationServices>,\n middleware: ReadonlyArray<AnyMiddleware<ApplicationServices>>,\n): PageFactory<ApplicationServices, AvailableServices> => {\n function make<ParamsSchema extends PageParamsSchema<AvailableServices>, Error>(\n options: ParameterizedPageOptions<ParamsSchema, Error, AvailableServices> &\n ValidPageParamsSchema<ParamsSchema>,\n ): ParameterizedPageDefinition<ApplicationServices, PageParamKeys<ParamsSchema>>;\n function make<Error>(\n options: StaticPageOptions<Error, AvailableServices>,\n ): StaticPageDefinition<ApplicationServices>;\n function make<Error>(\n options:\n | Omit<StaticPageOptions<Error, AvailableServices>, 'params'>\n | ParameterizedPageOptions<PageParamsSchema<AvailableServices>, Error, AvailableServices>,\n ): AnyPageDefinition<ApplicationServices> {\n if ('params' in options) {\n const { params: paramsSchema, render } = options;\n const decodeParams = Schema.decodeUnknownEffect(paramsSchema);\n const component: PageComponent = ({ params }) =>\n identity.renderRuntime.run(\n 'Page',\n (params._tag === 'Decoded'\n ? Effect.succeed(params.value)\n : decodeParams(params.value)\n ).pipe(\n Effect.flatMap((decodedParams) =>\n Effect.suspend(() => render({ params: decodedParams })),\n ),\n ),\n middleware,\n );\n return new PageDefinitionImpl<\n ApplicationServices,\n PageParamKeys<typeof paramsSchema>,\n 'Parameterized',\n typeof paramsSchema\n >(identity, component, paramsSchema);\n }\n\n const { render } = options;\n const component: PageComponent = () =>\n identity.renderRuntime.run('Page', Effect.suspend(render), middleware);\n return new PageDefinitionImpl<ApplicationServices, never, 'Static', null>(\n identity,\n component,\n null,\n );\n }\n\n return { make };\n};\n"],"names":["Effect","Schema","ERSCIdentityTypeId","isERSCMember","ERSCMemberKindTypeId","ERSCStateTypeId","PageDefinitionImpl","identity","component","paramsSchema","Object","getPageState","page","TypeError","makePageFactory","middleware","make","options","render","decodeParams","params","decodedParams"],"mappings":";;;;;AAAoD;AAU3B;AAqFzB,MAAMM,kBAAkBA;IAcb,CAACJ,kBAAkBA,CAAC,CAAyB;IAC7C,CAACE,oBAAoBA,CAAC,GAAG,OAAgB;IAClD,IAAI,CAACC,eAAeA,CAAC,GAA4B;QAC/C,OAAO,IAAI;IACb;IACS,UAAyB;IACzB,aAA2B;IAEpC,YACEE,QAAgC,EAChCC,SAAwB,EACxBC,YAA0B,CAC1B;QACA,IAAI,CAACP,kBAAkBA,CAAC,GAAGK;QAC3B,IAAI,CAAC,SAAS,GAAGC;QACjB,IAAI,CAAC,YAAY,GAAGC;QACpBC,OAAO,MAAM,CAAC,IAAI;IACpB;AACF;AAKA,0FAA0F;AAC1F,6FAA6F;AACtF,SAASC,YAAYA,CAACC,IAAgC;IAC3D,IAAI,CAACT,YAAYA,CAACS,MAAM,SAAS;QAC/B,MAAM,IAAIC,UAAU;IACtB;IACA,OAAOD,IAAI,CAACP,eAAeA,CAAC;AAC9B;AAyBO,MAAMS,eAAeA,GAAG,CAC7BP,UACAQ;IASA,SAASC,KACPC,OAE2F;QAE3F,IAAI,YAAYA,SAAS;YACvB,MAAM,EAAE,QAAQR,YAAY,EAAES,MAAM,EAAE,GAAGD;YACzC,MAAME,eAAelB,0BAA0B,CAACQ;YAChD,MAAMD,YAA2B,CAAC,EAAEY,MAAM,EAAE,GAC1Cb,SAAS,aAAa,CAAC,GAAG,CACxB,QACCa,CAAAA,OAAO,IAAI,KAAK,YACbpB,cAAc,CAACoB,OAAO,KAAK,IAC3BD,aAAaC,OAAO,KAAK,GAC3B,IAAI,CACJpB,cAAc,CAAC,CAACqB,gBACdrB,cAAc,CAAC,IAAMkB,OAAO;4BAAE,QAAQG;wBAAc,OAGxDN;YAEJ,OAAO,IAAIT,kBAAkBA,CAK3BC,UAAUC,WAAWC;QACzB;QAEA,MAAM,EAAES,MAAM,EAAE,GAAGD;QACnB,MAAMT,YAA2B,IAC/BD,SAAS,aAAa,CAAC,GAAG,CAAC,QAAQP,cAAc,CAACkB,SAASH;QAC7D,OAAO,IAAIT,kBAAkBA,CAC3BC,UACAC,WACA;IAEJ;IAEA,OAAO;QAAEQ;IAAK;AAChB,EAAE"}
|
|
@@ -11,7 +11,7 @@ export type RouteScope<Services> = {
|
|
|
11
11
|
};
|
|
12
12
|
export type CompiledDestination<Services> = {
|
|
13
13
|
readonly middleware: ReadonlyArray<AnyMiddleware<Services>>;
|
|
14
|
-
readonly page: PageImplementationState
|
|
14
|
+
readonly page: PageImplementationState<Services>;
|
|
15
15
|
readonly pattern: AbsolutePath;
|
|
16
16
|
readonly scopes: ReadonlyArray<RouteScope<Services>>;
|
|
17
17
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"application/route-graph.js","sources":["../../src/application/route-graph.ts"],"sourcesContent":["import type { LayoutComponent } from './layout';\nimport type { LoadingComponent } from './loading';\nimport type { AnyMiddleware } from './middleware';\nimport { getPageState, type PageImplementationState } from './page';\nimport { type AbsolutePath, joinRoutePaths, validateUnreservedPath } from './route-path';\nimport { type AnyRoutes, getRoutesState } from './routes';\n\nexport type RouteScope<Services> = {\n readonly id: string;\n readonly layout: LayoutComponent<Services> | null;\n readonly loading: LoadingComponent<Services> | null;\n};\n\nexport type CompiledDestination<Services> = {\n readonly middleware: ReadonlyArray<AnyMiddleware<Services>>;\n readonly page: PageImplementationState
|
|
1
|
+
{"version":3,"file":"application/route-graph.js","sources":["../../src/application/route-graph.ts"],"sourcesContent":["import type { LayoutComponent } from './layout';\nimport type { LoadingComponent } from './loading';\nimport type { AnyMiddleware } from './middleware';\nimport { getPageState, type PageImplementationState } from './page';\nimport { type AbsolutePath, joinRoutePaths, validateUnreservedPath } from './route-path';\nimport { type AnyRoutes, getRoutesState } from './routes';\n\nexport type RouteScope<Services> = {\n readonly id: string;\n readonly layout: LayoutComponent<Services> | null;\n readonly loading: LoadingComponent<Services> | null;\n};\n\nexport type CompiledDestination<Services> = {\n readonly middleware: ReadonlyArray<AnyMiddleware<Services>>;\n readonly page: PageImplementationState<Services>;\n readonly pattern: AbsolutePath;\n readonly scopes: ReadonlyArray<RouteScope<Services>>;\n};\n\nexport type CompiledRouteGraph<Services> = readonly [\n CompiledDestination<Services>,\n ...Array<CompiledDestination<Services>>,\n];\n\nconst resolveRouteMiddleware = <Services>(\n inherited: ReadonlyArray<AnyMiddleware<Services>>,\n declared: ReadonlyArray<AnyMiddleware<Services>>,\n) => {\n let sharedCount = 0;\n while (sharedCount < inherited.length && inherited[sharedCount] === declared[sharedCount]) {\n sharedCount += 1;\n }\n\n return sharedCount === inherited.length\n ? declared\n : Object.freeze([...inherited, ...declared.slice(sharedCount)]);\n};\n\nexport const compileRouteGraph = <Services>(\n routes: AnyRoutes<Services>,\n): CompiledRouteGraph<Services> => {\n const rootState = getRoutesState(routes);\n if (rootState.layout === null) {\n throw new TypeError('The root Routes passed to ERSC.make must define a Layout.');\n }\n\n const destinations: Array<CompiledDestination<Services>> = [];\n const visit = (\n current: AnyRoutes<Services>,\n prefix: AbsolutePath,\n inheritedScopes: ReadonlyArray<RouteScope<Services>>,\n inheritedMiddleware: ReadonlyArray<AnyMiddleware<Services>>,\n ): void => {\n const currentState = getRoutesState(current);\n const middleware = resolveRouteMiddleware(inheritedMiddleware, currentState.middleware);\n if (new Set(middleware).size !== middleware.length) {\n throw new TypeError(\n `Middleware beneath route prefix \"${prefix}\" appears more than once in its resolved chain.`,\n );\n }\n const scopes =\n currentState.layout === null && currentState.loading === null\n ? inheritedScopes\n : Object.freeze([\n ...inheritedScopes,\n Object.freeze({\n id: `${currentState.scopeId}:${prefix}`,\n layout: currentState.layout,\n loading: currentState.loading,\n }),\n ]);\n\n for (const route of currentState.pages) {\n const pattern = joinRoutePaths(prefix, route.path);\n validateUnreservedPath(pattern);\n destinations.push(\n Object.freeze({ middleware, page: getPageState(route.page), pattern, scopes }),\n );\n }\n\n for (const mount of currentState.mounts) {\n visit(mount.routes, joinRoutePaths(prefix, mount.path), scopes, middleware);\n }\n };\n\n visit(routes, '/', [], []);\n const [firstDestination, ...remainingDestinations] = destinations;\n if (firstDestination === undefined) {\n throw new TypeError('The root Routes passed to ERSC.make must contain a Page.');\n }\n\n return Object.freeze([firstDestination, ...remainingDestinations]);\n};\n"],"names":["getPageState","joinRoutePaths","validateUnreservedPath","getRoutesState","resolveRouteMiddleware","inherited","declared","sharedCount","Object","compileRouteGraph","routes","rootState","TypeError","destinations","visit","current","prefix","inheritedScopes","inheritedMiddleware","currentState","middleware","Set","scopes","route","pattern","mount","firstDestination","remainingDestinations","undefined"],"mappings":";;;;;;;AAGoE;AACqB;AAC/B;AAoB1D,MAAMI,sBAAsBA,GAAG,CAC7BC,WACAC;IAEA,IAAIC,cAAc;IAClB,MAAOA,cAAcF,UAAU,MAAM,IAAIA,SAAS,CAACE,YAAY,KAAKD,QAAQ,CAACC,YAAY,CAAE;QACzFA,eAAe;IACjB;IAEA,OAAOA,gBAAgBF,UAAU,MAAM,GACnCC,WACAE,OAAO,MAAM,CAAC;WAAIH;WAAcC,SAAS,KAAK,CAACC;KAAa;AAClE;AAEO,MAAME,iBAAiBA,GAAG,CAC/BC;IAEA,MAAMC,YAAYR,cAAcA,CAACO;IACjC,IAAIC,UAAU,MAAM,KAAK,MAAM;QAC7B,MAAM,IAAIC,UAAU;IACtB;IAEA,MAAMC,eAAqD,EAAE;IAC7D,MAAMC,QAAQ,CACZC,SACAC,QACAC,iBACAC;QAEA,MAAMC,eAAehB,cAAcA,CAACY;QACpC,MAAMK,aAAahB,sBAAsBA,CAACc,qBAAqBC,aAAa,UAAU;QACtF,IAAI,IAAIE,IAAID,YAAY,IAAI,KAAKA,WAAW,MAAM,EAAE;YAClD,MAAM,IAAIR,UACR,CAAC,iCAAiC,EAAEI,OAAO,+CAA+C,CAAC;QAE/F;QACA,MAAMM,SACJH,aAAa,MAAM,KAAK,QAAQA,aAAa,OAAO,KAAK,OACrDF,kBACAT,OAAO,MAAM,CAAC;eACTS;YACHT,OAAO,MAAM,CAAC;gBACZ,IAAI,GAAGW,aAAa,OAAO,CAAC,CAAC,EAAEH,QAAQ;gBACvC,QAAQG,aAAa,MAAM;gBAC3B,SAASA,aAAa,OAAO;YAC/B;SACD;QAEP,KAAK,MAAMI,SAASJ,aAAa,KAAK,CAAE;YACtC,MAAMK,UAAUvB,cAAcA,CAACe,QAAQO,MAAM,IAAI;YACjDrB,sBAAsBA,CAACsB;YACvBX,aAAa,IAAI,CACfL,OAAO,MAAM,CAAC;gBAAEY;gBAAY,MAAMpB,YAAYA,CAACuB,MAAM,IAAI;gBAAGC;gBAASF;YAAO;QAEhF;QAEA,KAAK,MAAMG,SAASN,aAAa,MAAM,CAAE;YACvCL,MAAMW,MAAM,MAAM,EAAExB,cAAcA,CAACe,QAAQS,MAAM,IAAI,GAAGH,QAAQF;QAClE;IACF;IAEAN,MAAMJ,QAAQ,KAAK,EAAE,EAAE,EAAE;IACzB,MAAM,CAACgB,kBAAkB,GAAGC,sBAAsB,GAAGd;IACrD,IAAIa,qBAAqBE,WAAW;QAClC,MAAM,IAAIhB,UAAU;IACtB;IAEA,OAAOJ,OAAO,MAAM,CAAC;QAACkB;WAAqBC;KAAsB;AACnE,EAAE"}
|
|
@@ -15,15 +15,19 @@ type ServerFnInvocationMatch<ApplicationServices> = {
|
|
|
15
15
|
readonly effect: Effect.Effect<unknown, ServerFnOperationError, ApplicationServices>;
|
|
16
16
|
readonly middleware: ReadonlyArray<AnyMiddleware<ApplicationServices>>;
|
|
17
17
|
};
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
type ServerFnInput<Services> = Schema.ConstraintDecoder<unknown, Services> | ReadonlyArray<Schema.ConstraintDecoder<unknown, Services>>;
|
|
19
|
+
type ServerFnArguments<Input, Side extends 'Type' | 'Encoded'> = Input extends ReadonlyArray<Schema.Constraint> ? {
|
|
20
|
+
-readonly [Key in keyof Input]: Input[Key] extends Schema.Constraint ? Input[Key][Side] : never;
|
|
21
|
+
} : Input extends Schema.Constraint ? [Input[Side]] : never;
|
|
22
|
+
interface ServerFunction<Args extends ReadonlyArray<unknown>, Output, ApplicationServices> extends ERSCMember<ApplicationServices, 'ServerFn'> {
|
|
23
|
+
(...args: Args): Promise<Output>;
|
|
20
24
|
}
|
|
21
|
-
type ServerFnOptions<
|
|
22
|
-
readonly input:
|
|
23
|
-
readonly handler: (
|
|
25
|
+
type ServerFnOptions<Input, Output, Error, Services> = {
|
|
26
|
+
readonly input: Input;
|
|
27
|
+
readonly handler: (...args: ServerFnArguments<Input, 'Type'>) => Effect.Effect<Output, Error, Services>;
|
|
24
28
|
};
|
|
25
29
|
export type ServerFnFactory<ApplicationServices, AvailableServices> = {
|
|
26
|
-
readonly make: <
|
|
30
|
+
readonly make: <const Input extends ServerFnInput<AvailableServices>, Output, Error>(options: ServerFnOptions<Input, Output, Error, AvailableServices>) => ServerFunction<ServerFnArguments<Input, 'Encoded'>, Output, ApplicationServices>;
|
|
27
31
|
};
|
|
28
32
|
export declare const matchServerFnInvocation: <ApplicationServices>(value: unknown, identity: ERSCIdentity<ApplicationServices>) => ServerFnInvocationMatch<ApplicationServices>;
|
|
29
33
|
export declare const makeServerFnFactory: <ApplicationServices, AvailableServices>(identity: ERSCIdentity<ApplicationServices>, middleware: ReadonlyArray<AnyMiddleware<ApplicationServices>>) => ServerFnFactory<ApplicationServices, AvailableServices>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Effect, Predicate, Schema } from "effect";
|
|
1
|
+
import { Array as external_effect_Array, Effect, Predicate, Schema } from "effect";
|
|
2
2
|
import { attachERSCMember } from "./ersc-identity.js";
|
|
3
3
|
|
|
4
4
|
|
|
@@ -34,9 +34,14 @@ const matchServerFnInvocation = (value, identity)=>{
|
|
|
34
34
|
};
|
|
35
35
|
const makeServerFnFactory = (identity, middleware)=>({
|
|
36
36
|
make: ({ input, handler })=>{
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
|
|
37
|
+
const schemas = external_effect_Array.ensure(input);
|
|
38
|
+
const decode = Schema.decodeUnknownEffect(Schema.Tuple(schemas));
|
|
39
|
+
const serverFunction = (...untrustedArgs)=>{
|
|
40
|
+
// Unary functions still ignore extra native arguments and decode undefined when omitted.
|
|
41
|
+
const effect = decode(external_effect_Array.isArray(input) ? untrustedArgs : [
|
|
42
|
+
untrustedArgs[0]
|
|
43
|
+
]).pipe(// Normalization preserves the positional Type mapping, which the generic branch erases.
|
|
44
|
+
Effect.flatMap((args)=>handler(...args)), Effect.mapError((cause)=>new ServerFnOperationError({
|
|
40
45
|
cause
|
|
41
46
|
})));
|
|
42
47
|
const unavailable = Promise.reject(directInvocationError());
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"application/server-fn.js","sources":["../../src/application/server-fn.ts"],"sourcesContent":["import { Effect, Predicate, Schema } from 'effect';\n\nimport { attachERSCMember, type ERSCIdentity, type ERSCMember } from './ersc-identity';\nimport type { AnyMiddleware } from './middleware';\n\nconst ServerFnInvocationTypeId: unique symbol = Symbol.for('ersc/ServerFnInvocation');\n\nclass ServerFnOperationError extends Schema.TaggedError<ServerFnOperationError>()(\n 'ServerFnOperationError',\n { cause: Schema.Defect() },\n) {}\n\ntype ServerFnInvocation<ApplicationServices> = {\n readonly [ServerFnInvocationTypeId]: {\n readonly effect: Effect.Effect<unknown, ServerFnOperationError, ApplicationServices>;\n readonly identity: ERSCIdentity<ApplicationServices>;\n readonly middleware: ReadonlyArray<AnyMiddleware<ApplicationServices>>;\n };\n};\n\ntype ServerFnInvocationMatch<ApplicationServices> =\n | { readonly _tag: 'Native' }\n | { readonly _tag: 'IdentityMismatch' }\n | {\n readonly _tag: 'Match';\n readonly effect: Effect.Effect<unknown, ServerFnOperationError, ApplicationServices>;\n readonly middleware: ReadonlyArray<AnyMiddleware<ApplicationServices>>;\n };\n\
|
|
1
|
+
{"version":3,"file":"application/server-fn.js","sources":["../../src/application/server-fn.ts"],"sourcesContent":["import { Array, Effect, Predicate, Schema } from 'effect';\n\nimport { attachERSCMember, type ERSCIdentity, type ERSCMember } from './ersc-identity';\nimport type { AnyMiddleware } from './middleware';\n\nconst ServerFnInvocationTypeId: unique symbol = Symbol.for('ersc/ServerFnInvocation');\n\nclass ServerFnOperationError extends Schema.TaggedError<ServerFnOperationError>()(\n 'ServerFnOperationError',\n { cause: Schema.Defect() },\n) {}\n\ntype ServerFnInvocation<ApplicationServices> = {\n readonly [ServerFnInvocationTypeId]: {\n readonly effect: Effect.Effect<unknown, ServerFnOperationError, ApplicationServices>;\n readonly identity: ERSCIdentity<ApplicationServices>;\n readonly middleware: ReadonlyArray<AnyMiddleware<ApplicationServices>>;\n };\n};\n\ntype ServerFnInvocationMatch<ApplicationServices> =\n | { readonly _tag: 'Native' }\n | { readonly _tag: 'IdentityMismatch' }\n | {\n readonly _tag: 'Match';\n readonly effect: Effect.Effect<unknown, ServerFnOperationError, ApplicationServices>;\n readonly middleware: ReadonlyArray<AnyMiddleware<ApplicationServices>>;\n };\n\ntype ServerFnInput<Services> =\n | Schema.ConstraintDecoder<unknown, Services>\n | ReadonlyArray<Schema.ConstraintDecoder<unknown, Services>>;\n\ntype ServerFnArguments<Input, Side extends 'Type' | 'Encoded'> =\n Input extends ReadonlyArray<Schema.Constraint>\n ? {\n -readonly [Key in keyof Input]: Input[Key] extends Schema.Constraint\n ? Input[Key][Side]\n : never;\n }\n : Input extends Schema.Constraint\n ? [Input[Side]]\n : never;\n\ninterface ServerFunction<\n Args extends ReadonlyArray<unknown>,\n Output,\n ApplicationServices,\n> extends ERSCMember<ApplicationServices, 'ServerFn'> {\n (...args: Args): Promise<Output>;\n}\n\ntype ServerFnOptions<Input, Output, Error, Services> = {\n readonly input: Input;\n readonly handler: (\n ...args: ServerFnArguments<Input, 'Type'>\n ) => Effect.Effect<Output, Error, Services>;\n};\n\nexport type ServerFnFactory<ApplicationServices, AvailableServices> = {\n readonly make: <const Input extends ServerFnInput<AvailableServices>, Output, Error>(\n options: ServerFnOptions<Input, Output, Error, AvailableServices>,\n ) => ServerFunction<ServerFnArguments<Input, 'Encoded'>, Output, ApplicationServices>;\n};\n\nconst directInvocationError = () =>\n new TypeError(\n 'An ERSC ServerFn is a framework intrinsic and cannot be invoked directly in the server graph.',\n );\n\nconst isServerFnInvocation = <ApplicationServices>(\n value: unknown,\n): value is ServerFnInvocation<ApplicationServices> =>\n Predicate.hasProperty(value, ServerFnInvocationTypeId);\n\nexport const matchServerFnInvocation = <ApplicationServices>(\n value: unknown,\n identity: ERSCIdentity<ApplicationServices>,\n): ServerFnInvocationMatch<ApplicationServices> => {\n if (!isServerFnInvocation<ApplicationServices>(value)) {\n return { _tag: 'Native' };\n }\n\n // The framework-owned brand proves the state shape; matching the opaque identity proves the\n // application service universe erased by the native React invocation.\n const metadata = value[ServerFnInvocationTypeId];\n if (metadata.identity !== identity) {\n return { _tag: 'IdentityMismatch' };\n }\n\n return { _tag: 'Match', effect: metadata.effect, middleware: metadata.middleware };\n};\n\nexport const makeServerFnFactory = <ApplicationServices, AvailableServices>(\n identity: ERSCIdentity<ApplicationServices>,\n middleware: ReadonlyArray<AnyMiddleware<ApplicationServices>>,\n): ServerFnFactory<ApplicationServices, AvailableServices> => ({\n make: ({ input, handler }) => {\n const schemas = Array.ensure<Schema.ConstraintDecoder<unknown, AvailableServices>>(input);\n const decode = Schema.decodeUnknownEffect(Schema.Tuple(schemas));\n const serverFunction = (...untrustedArgs: ServerFnArguments<typeof input, 'Encoded'>) => {\n // Unary functions still ignore extra native arguments and decode undefined when omitted.\n const effect = decode(Array.isArray(input) ? untrustedArgs : [untrustedArgs[0]]).pipe(\n // Normalization preserves the positional Type mapping, which the generic branch erases.\n Effect.flatMap((args: ReadonlyArray<unknown>) =>\n handler(...(args as ServerFnArguments<typeof input, 'Type'>)),\n ),\n Effect.mapError((cause) => new ServerFnOperationError({ cause })),\n );\n const unavailable = Promise.reject<Effect.Success<typeof effect>>(directInvocationError());\n void unavailable.catch(() => undefined);\n\n return Object.assign(unavailable, {\n [ServerFnInvocationTypeId]: Object.freeze({ effect, identity, middleware }),\n });\n };\n\n return attachERSCMember(serverFunction, identity, 'ServerFn');\n },\n});\n"],"names":["Array","Effect","Predicate","Schema","attachERSCMember","ServerFnInvocationTypeId","Symbol","ServerFnOperationError","directInvocationError","TypeError","isServerFnInvocation","value","matchServerFnInvocation","identity","metadata","makeServerFnFactory","middleware","input","handler","schemas","decode","serverFunction","untrustedArgs","effect","args","cause","unavailable","Promise","undefined","Object"],"mappings":";;;;;AAA0D;AAE6B;AAGvF,MAAMK,wBAAwBA,GAAkBC,OAAO,GAAG,CAAC;AAE3D,MAAMC,sBAAsBA,SAASJ,kBAAkB,GACrD,0BACA;IAAE,OAAOA,aAAa;AAAG;AACxB;AAuDH,MAAMK,qBAAqBA,GAAG,IAC5B,IAAIC,UACF;AAGJ,MAAMC,oBAAoBA,GAAG,CAC3BC,QAEAT,qBAAqB,CAACS,OAAON,wBAAwBA;AAEhD,MAAMO,uBAAuBA,GAAG,CACrCD,OACAE;IAEA,IAAI,CAACH,oBAAoBA,CAAsBC,QAAQ;QACrD,OAAO;YAAE,MAAM;QAAS;IAC1B;IAEA,4FAA4F;IAC5F,sEAAsE;IACtE,MAAMG,WAAWH,KAAK,CAACN,wBAAwBA,CAAC;IAChD,IAAIS,SAAS,QAAQ,KAAKD,UAAU;QAClC,OAAO;YAAE,MAAM;QAAmB;IACpC;IAEA,OAAO;QAAE,MAAM;QAAS,QAAQC,SAAS,MAAM;QAAE,YAAYA,SAAS,UAAU;IAAC;AACnF,EAAE;AAEK,MAAMC,mBAAmBA,GAAG,CACjCF,UACAG,aAC6D;QAC7D,MAAM,CAAC,EAAEC,KAAK,EAAEC,OAAO,EAAE;YACvB,MAAMC,UAAUnB,4BAAY,CAAuDiB;YACnF,MAAMG,SAASjB,0BAA0B,CAACA,YAAY,CAACgB;YACvD,MAAME,iBAAiB,CAAC,GAAGC;gBACzB,yFAAyF;gBACzF,MAAMC,SAASH,OAAOpB,6BAAa,CAACiB,SAASK,gBAAgB;oBAACA,aAAa,CAAC,EAAE;iBAAC,EAAE,IAAI,CACnF,wFAAwF;gBACxFrB,cAAc,CAAC,CAACuB,OACdN,WAAYM,QAEdvB,eAAe,CAAC,CAACwB,QAAU,IAAIlB,sBAAsBA,CAAC;wBAAEkB;oBAAM;gBAEhE,MAAMC,cAAcC,QAAQ,MAAM,CAAgCnB,qBAAqBA;gBACvF,KAAKkB,YAAY,KAAK,CAAC,IAAME;gBAE7B,OAAOC,OAAO,MAAM,CAACH,aAAa;oBAChC,CAACrB,wBAAwBA,CAAC,EAAEwB,OAAO,MAAM,CAAC;wBAAEN;wBAAQV;wBAAUG;oBAAW;gBAC3E;YACF;YAEA,OAAOZ,gBAAgBA,CAACiB,gBAAgBR,UAAU;QACpD;IACF,GAAG"}
|
package/dist/build/dev.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Effect, FileSystem, Path, Schema } from 'effect';
|
|
2
|
-
import { HttpServer } from 'effect/unstable/http';
|
|
1
|
+
import { Cause, Effect, FileSystem, Path, Schema, Scope } from 'effect';
|
|
2
|
+
import { HttpServer, HttpServerResponse } from 'effect/unstable/http';
|
|
3
3
|
import { Rspack, type RspackError, type RspackWatchEvent } from './rspack.js';
|
|
4
4
|
type RspackCompilation = Extract<RspackWatchEvent, {
|
|
5
5
|
readonly _tag: 'Compiled';
|
|
@@ -7,7 +7,7 @@ type RspackCompilation = Extract<RspackWatchEvent, {
|
|
|
7
7
|
declare const DevGenerationError_base: Schema.Class<DevGenerationError, Schema.TaggedStruct<"DevGenerationError", {
|
|
8
8
|
readonly message: Schema.String;
|
|
9
9
|
readonly cause: Schema.Defect;
|
|
10
|
-
}>,
|
|
10
|
+
}>, Cause.YieldableError>;
|
|
11
11
|
export declare class DevGenerationError extends DevGenerationError_base {
|
|
12
12
|
}
|
|
13
13
|
type AcquireDevGenerationOptions = {
|
|
@@ -20,22 +20,22 @@ type DevGenerationOptions = Omit<AcquireDevGenerationOptions, 'compilation'>;
|
|
|
20
20
|
export type DevApplicationOptions = DevGenerationOptions;
|
|
21
21
|
export declare const acquireDevGeneration: (args_0: AcquireDevGenerationOptions) => Effect.Effect<{
|
|
22
22
|
hash: string;
|
|
23
|
-
httpEffect: Effect.Effect<
|
|
24
|
-
}, import("./compiled-server.js").CompiledServerError | DevGenerationError, FileSystem.FileSystem | Path.Path |
|
|
23
|
+
httpEffect: Effect.Effect<HttpServerResponse.HttpServerResponse, import("effect/unstable/http/HttpServerError").HttpServerError, import("effect/unstable/http/HttpServerRequest").HttpServerRequest | Scope.Scope>;
|
|
24
|
+
}, import("./compiled-server.js").CompiledServerError | DevGenerationError, FileSystem.FileSystem | Path.Path | Scope.Scope>;
|
|
25
25
|
type DevGenerationFailure = Effect.Error<ReturnType<typeof acquireDevGeneration>> | RspackError;
|
|
26
26
|
export declare const makeDevGenerationStore: (options: DevGenerationOptions) => Effect.Effect<{
|
|
27
|
-
httpEffect: Effect.Effect<
|
|
27
|
+
httpEffect: Effect.Effect<HttpServerResponse.HttpServerResponse, import("effect/unstable/http/HttpServerError").HttpServerError | DevGenerationFailure, import("effect/unstable/http/HttpServerRequest").HttpServerRequest | Scope.Scope>;
|
|
28
28
|
update: (event: RspackWatchEvent) => Effect.Effect<undefined, import("./compiled-server.js").CompiledServerError | DevGenerationError, FileSystem.FileSystem | Path.Path>;
|
|
29
|
-
}, never,
|
|
29
|
+
}, never, Scope.Scope>;
|
|
30
30
|
export declare const makeDevApplication: (args_0: DevGenerationOptions) => Effect.Effect<{
|
|
31
31
|
closeDevChannel: Effect.Effect<void, never, never>;
|
|
32
|
-
httpEffect: Effect.Effect<
|
|
32
|
+
httpEffect: Effect.Effect<HttpServerResponse.HttpServerResponse, import("./compiled-server.js").CompiledServerError | DevGenerationError | import("effect/unstable/http/HttpServerError").HttpServerError | RspackError, import("effect/unstable/http/HttpServerRequest").HttpServerRequest | Scope.Scope>;
|
|
33
33
|
watch: Effect.Effect<void, import("./compiled-server.js").CompiledServerError | DevGenerationError | RspackError, FileSystem.FileSystem | Path.Path>;
|
|
34
|
-
}, import("./build.js").BuildEntryError | import("effect/PlatformError").PlatformError, FileSystem.FileSystem | Path.Path | Rspack |
|
|
34
|
+
}, import("./build.js").BuildEntryError | import("effect/PlatformError").PlatformError, FileSystem.FileSystem | Path.Path | Rspack | Scope.Scope>;
|
|
35
35
|
export declare const launchDevApplication: (application: {
|
|
36
36
|
closeDevChannel: Effect.Effect<void, never, never>;
|
|
37
|
-
httpEffect: Effect.Effect<
|
|
37
|
+
httpEffect: Effect.Effect<HttpServerResponse.HttpServerResponse, import("./compiled-server.js").CompiledServerError | DevGenerationError | import("effect/unstable/http/HttpServerError").HttpServerError | RspackError, import("effect/unstable/http/HttpServerRequest").HttpServerRequest | Scope.Scope>;
|
|
38
38
|
watch: Effect.Effect<void, import("./compiled-server.js").CompiledServerError | DevGenerationError | RspackError, FileSystem.FileSystem | Path.Path>;
|
|
39
39
|
}) => Effect.Effect<void, import("./compiled-server.js").CompiledServerError | DevGenerationError | RspackError, FileSystem.FileSystem | HttpServer.HttpServer | Path.Path>;
|
|
40
|
-
export declare const devApplication: (options: DevGenerationOptions) => Effect.Effect<void, import("./build.js").BuildEntryError | import("./compiled-server.js").CompiledServerError | DevGenerationError | import("effect/PlatformError").PlatformError | RspackError, FileSystem.FileSystem | HttpServer.HttpServer | Path.Path |
|
|
40
|
+
export declare const devApplication: (options: DevGenerationOptions) => Effect.Effect<void, import("./build.js").BuildEntryError | import("./compiled-server.js").CompiledServerError | DevGenerationError | import("effect/PlatformError").PlatformError | RspackError, FileSystem.FileSystem | HttpServer.HttpServer | Path.Path | Scope.Scope>;
|
|
41
41
|
export {};
|
package/dist/build/dev.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Deferred, Effect, Fiber, FileSystem, Layer, Path, Ref, Schema, ScopedRef, Stream } from "effect";
|
|
2
|
-
import { HttpRouter, HttpServer } from "effect/unstable/http";
|
|
1
|
+
import { Cause, Deferred, Effect, Fiber, FileSystem, Layer, Path, Ref, Schema, Scope, ScopedRef, Stream } from "effect";
|
|
2
|
+
import { HttpBody, HttpRouter, HttpServer, HttpServerResponse } from "effect/unstable/http";
|
|
3
3
|
import package_0 from "../../package.json" with {"type":"json"};
|
|
4
4
|
import { DevChannelPath } from "../dev/channel.js";
|
|
5
5
|
import { resolveApplicationBuild } from "./build.js";
|
|
@@ -52,9 +52,25 @@ const acquireDevGeneration = Effect.fnUntraced(function*({ compilation, hostname
|
|
|
52
52
|
message: `Failed to start development generation ${compilation.hash}.`,
|
|
53
53
|
cause
|
|
54
54
|
})));
|
|
55
|
+
// Close request work before the generation's application services.
|
|
56
|
+
const generationScope = yield* Effect.scope;
|
|
57
|
+
const requests = yield* Scope.fork(generationScope, 'parallel');
|
|
58
|
+
const ownRequest = Effect.withFiber((fiber)=>{
|
|
59
|
+
Fiber.runIn(fiber, requests);
|
|
60
|
+
return Effect["void"];
|
|
61
|
+
});
|
|
55
62
|
return {
|
|
56
63
|
hash: compilation.hash,
|
|
57
|
-
httpEffect
|
|
64
|
+
httpEffect: Effect.gen(function*() {
|
|
65
|
+
yield* ownRequest;
|
|
66
|
+
const response = yield* httpEffect;
|
|
67
|
+
const body = response.body;
|
|
68
|
+
if (body._tag !== 'Stream') {
|
|
69
|
+
return response;
|
|
70
|
+
}
|
|
71
|
+
// Bun consumes the response body on a separate fiber after the handler returns.
|
|
72
|
+
return HttpServerResponse.setBody(response, HttpBody.stream(Stream.onStart(body.stream, ownRequest), body.contentType, body.contentLength));
|
|
73
|
+
})
|
|
58
74
|
};
|
|
59
75
|
});
|
|
60
76
|
const makeDevGenerationStore = Effect.fnUntraced(function*(options) {
|
|
@@ -85,7 +101,7 @@ const makeDevGenerationStore = Effect.fnUntraced(function*(options) {
|
|
|
85
101
|
yield* ScopedRef.set(generation, acquireDevGeneration({
|
|
86
102
|
...options,
|
|
87
103
|
compilation: event
|
|
88
|
-
}).pipe(Effect.map((ready)=>({
|
|
104
|
+
}).pipe(Effect.interruptible, Effect.map((ready)=>({
|
|
89
105
|
_tag: 'Ready',
|
|
90
106
|
generation: ready
|
|
91
107
|
})), Effect.tapError((error)=>Deferred.fail(current, error))));
|
|
@@ -148,7 +164,7 @@ const makeDevApplication = Effect.fnUntraced(function*({ hostname, port, root })
|
|
|
148
164
|
const compilers = event.compilers.map(({ duration, name })=>duration === undefined ? name : `${name} ${formatDuration(duration)}`).join(' · ');
|
|
149
165
|
const details = compilers.length === 0 ? '' : ` ${Terminal.dim(compilers)}`;
|
|
150
166
|
return Effect.logInfo(`${Terminal.green('✓')} Ready${duration}${details}`);
|
|
151
|
-
}), Effect["catch"]((error)=>Effect.logError(error)));
|
|
167
|
+
}), Effect["catch"]((error)=>channel.publishBuildFailure(Cause.pretty(Cause.fail(error))).pipe(Effect.andThen(Effect.logError(error)))));
|
|
152
168
|
}
|
|
153
169
|
}
|
|
154
170
|
});
|
package/dist/build/dev.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build/dev.js","sources":["../../src/build/dev.ts"],"sourcesContent":["import {\n Deferred,\n Effect,\n Fiber,\n FileSystem,\n Layer,\n Path,\n Ref,\n Schema,\n ScopedRef,\n Stream,\n} from 'effect';\nimport { HttpRouter, HttpServer } from 'effect/unstable/http';\n\nimport PackageJson from '../../package.json' with { type: 'json' };\nimport { DevChannelPath } from '../dev/channel';\nimport { resolveApplicationBuild } from './build';\nimport { loadServerBundle, makeRunnableHttpLayer } from './compiled-server';\nimport { DevOutputDir, EnvironmentConfig } from './contract';\nimport { makeDevChannel } from './dev-channel';\nimport { Rspack, type RspackError, type RspackWatchEvent } from './rspack';\nimport { makeRspackDevConfig } from './rspack-config';\nimport { formatDuration, Terminal } from './terminal';\n\ntype RspackCompilation = Extract<RspackWatchEvent, { readonly _tag: 'Compiled' }>;\n\nexport class DevGenerationError extends Schema.TaggedError<DevGenerationError>()(\n 'DevGenerationError',\n {\n message: Schema.String,\n cause: Schema.Defect(),\n },\n) {}\n\ntype AcquireDevGenerationOptions = {\n readonly compilation: RspackCompilation;\n readonly hostname: string;\n readonly port: number;\n readonly root: string;\n};\n\ntype DevGenerationOptions = Omit<AcquireDevGenerationOptions, 'compilation'>;\n\nexport type DevApplicationOptions = DevGenerationOptions;\n\nexport const acquireDevGeneration = Effect.fnUntraced(function* ({\n compilation,\n hostname,\n port,\n root,\n}: AcquireDevGenerationOptions) {\n const path = yield* Path.Path;\n const bundle = yield* loadServerBundle(\n path.resolve(compilation.serverBundle.outputPath, compilation.serverBundle.filename),\n );\n const HttpLayer = yield* makeRunnableHttpLayer({\n bundle,\n clientAssetsCacheControl: EnvironmentConfig.development.clientAssetsCacheControl,\n clientOutputDir: EnvironmentConfig.development.clientOutputDir,\n hostname,\n port,\n root,\n });\n const httpEffect = yield* HttpRouter.toHttpEffect(HttpLayer).pipe(\n Effect.mapError(\n (cause) =>\n new DevGenerationError({\n message: `Failed to start development generation ${compilation.hash}.`,\n cause,\n }),\n ),\n );\n\n return {\n hash: compilation.hash,\n httpEffect,\n };\n});\n\ntype DevGeneration = Effect.Success<ReturnType<typeof acquireDevGeneration>>;\ntype DevGenerationFailure = Effect.Error<ReturnType<typeof acquireDevGeneration>> | RspackError;\n\ntype DevGenerationState =\n | { readonly _tag: 'Unavailable' }\n | { readonly _tag: 'Ready'; readonly generation: DevGeneration };\n\nexport const makeDevGenerationStore = Effect.fnUntraced(function* (options: DevGenerationOptions) {\n const generation = yield* ScopedRef.make<DevGenerationState>(() => ({ _tag: 'Unavailable' }));\n const initialCompilation = yield* Deferred.make<DevGeneration, DevGenerationFailure>();\n const compilation = yield* Ref.make(initialCompilation);\n const update = Effect.fnUntraced(function* (event: RspackWatchEvent) {\n const current = yield* Ref.get(compilation);\n\n switch (event._tag) {\n case 'Building': {\n const compilationCompleted = yield* Deferred.isDone(current);\n if (compilationCompleted) {\n const next = yield* Deferred.make<DevGeneration, DevGenerationFailure>();\n yield* Ref.set(compilation, next);\n }\n return;\n }\n case 'Failed': {\n yield* Deferred.fail(current, event.error);\n return;\n }\n case 'Compiled': {\n yield* ScopedRef.set(\n generation,\n acquireDevGeneration({ ...options, compilation: event }).pipe(\n Effect.map((ready): DevGenerationState => ({\n _tag: 'Ready',\n generation: ready,\n })),\n Effect.tapError((error) => Deferred.fail(current, error)),\n ),\n );\n const ready = yield* ScopedRef.get(generation);\n if (ready._tag === 'Unavailable') {\n return yield* Effect.die(\n new TypeError('Expected the completed development generation to be available.'),\n );\n }\n yield* Deferred.succeed(current, ready.generation);\n }\n }\n });\n const httpEffect = Ref.get(compilation).pipe(\n Effect.flatMap(Deferred.await),\n Effect.flatMap((ready) => ready.httpEffect),\n );\n\n return {\n httpEffect,\n update,\n };\n});\n\nexport const makeDevApplication = Effect.fnUntraced(function* ({\n hostname,\n port,\n root,\n}: DevApplicationOptions) {\n const { applicationRoot, entries } = yield* resolveApplicationBuild({ root });\n const fileSystem = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const rspack = yield* Rspack;\n const channel = yield* makeDevChannel;\n\n yield* fileSystem.remove(path.join(applicationRoot, DevOutputDir), {\n force: true,\n recursive: true,\n });\n\n const generationStore = yield* makeDevGenerationStore({\n hostname,\n port,\n root: applicationRoot,\n });\n const update = Effect.fnUntraced(function* (event: RspackWatchEvent) {\n switch (event._tag) {\n case 'Building': {\n yield* generationStore.update(event);\n const firstChangedFile =\n event.changedFiles.find((file) => path.basename(file).includes('.')) ??\n event.changedFiles[0];\n const changedPath =\n firstChangedFile === undefined\n ? undefined\n : path.relative(applicationRoot, firstChangedFile);\n const subject = changedPath ?? 'application';\n\n yield* Effect.logInfo(`${Terminal.cyan('●')} Compiling ${subject}...`);\n return;\n }\n case 'Failed': {\n yield* generationStore.update(event);\n yield* channel.publishBuildFailure(event.diagnostics);\n yield* Effect.logError(event.error);\n return;\n }\n case 'Compiled': {\n if (event.warnings !== undefined) {\n yield* Effect.logWarning(event.warnings);\n }\n yield* generationStore.update(event).pipe(\n Effect.andThen(channel.publishCompilation(event.clientHash)),\n Effect.tap(() => {\n const duration =\n event.duration === undefined ? '' : ` in ${formatDuration(event.duration)}`;\n const compilers = event.compilers\n .map(({ duration, name }) =>\n duration === undefined ? name : `${name} ${formatDuration(duration)}`,\n )\n .join(' · ');\n const details = compilers.length === 0 ? '' : ` ${Terminal.dim(compilers)}`;\n\n return Effect.logInfo(`${Terminal.green('✓')} Ready${duration}${details}`);\n }),\n Effect.catch((error) => Effect.logError(error)),\n );\n }\n }\n });\n const watch = rspack\n .watch(\n makeRspackDevConfig(applicationRoot, entries, {\n onCompilationStart: channel.onCompilationStart,\n onServerComponentChanges: channel.onServerComponentChanges,\n }),\n )\n .pipe(Stream.runForEach(update));\n const httpEffect = yield* HttpRouter.toHttpEffect(\n HttpRouter.addAll([\n HttpRouter.route('GET', DevChannelPath, channel.httpEffect),\n HttpRouter.route('*', '/*', generationStore.httpEffect),\n ]),\n );\n\n return {\n closeDevChannel: channel.close,\n httpEffect,\n watch,\n };\n});\n\ntype DevApplication = Effect.Success<ReturnType<typeof makeDevApplication>>;\n\nexport const launchDevApplication = Effect.fnUntraced(function* (application: DevApplication) {\n return yield* Effect.scoped(\n Effect.gen(function* () {\n const server = yield* Layer.launch(HttpServer.serve(application.httpEffect)).pipe(\n Effect.forkScoped({ startImmediately: true }),\n );\n yield* Effect.addFinalizer(() => application.closeDevChannel);\n const watch = HttpServer.addressFormattedWith((address) =>\n Effect.logInfo(\n `${Terminal.magenta('▌')} effective-rsc ${Terminal.dim(PackageJson.version)} ${address}`,\n ),\n ).pipe(Effect.andThen(application.watch));\n\n return yield* Effect.raceFirst(watch, Fiber.join(server));\n }),\n );\n});\n\nexport const devApplication = Effect.fn('ersc/build/devApplication')(function* (\n options: DevApplicationOptions,\n) {\n const application = yield* makeDevApplication(options).pipe(Effect.provide(Rspack.layer));\n\n return yield* launchDevApplication(application);\n});\n"],"names":["Deferred","Effect","Fiber","FileSystem","Layer","Path","Ref","Schema","ScopedRef","Stream","HttpRouter","HttpServer","PackageJson","DevChannelPath","resolveApplicationBuild","loadServerBundle","makeRunnableHttpLayer","DevOutputDir","EnvironmentConfig","makeDevChannel","Rspack","makeRspackDevConfig","formatDuration","Terminal","DevGenerationError","acquireDevGeneration","compilation","hostname","port","root","path","bundle","HttpLayer","httpEffect","cause","makeDevGenerationStore","options","generation","initialCompilation","update","event","current","compilationCompleted","next","ready","error","TypeError","makeDevApplication","applicationRoot","entries","fileSystem","rspack","channel","generationStore","firstChangedFile","file","changedPath","undefined","subject","duration","compilers","name","details","watch","launchDevApplication","application","server","address","devApplication"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAWgB;AAC8C;AAEK;AACnB;AACE;AAC0B;AACf;AACd;AAC4B;AACrB;AACA;AAI/C,MAAMwB,kBAAkBA,SAASjB,kBAAkB,GACxD,sBACA;IACE,SAASA,aAAa;IACtB,OAAOA,aAAa;AACtB;AACC;AAaI,MAAMkB,oBAAoBA,GAAGxB,iBAAiB,CAAC,UAAW,EAC/DyB,WAAW,EACXC,QAAQ,EACRC,IAAI,EACJC,IAAI,EACwB;IAC5B,MAAMC,OAAO,OAAOzB,SAAS;IAC7B,MAAM0B,SAAS,OAAOhB,gBAAgBA,CACpCe,KAAK,OAAO,CAACJ,YAAY,YAAY,CAAC,UAAU,EAAEA,YAAY,YAAY,CAAC,QAAQ;IAErF,MAAMM,YAAY,OAAOhB,qBAAqBA,CAAC;QAC7Ce;QACA,0BAA0Bb,sDAAsD;QAChF,iBAAiBA,6CAA6C;QAC9DS;QACAC;QACAC;IACF;IACA,MAAMI,aAAa,OAAOvB,uBAAuB,CAACsB,WAAW,IAAI,CAC/D/B,eAAe,CACb,CAACiC,QACC,IAAIV,kBAAkBA,CAAC;YACrB,SAAS,CAAC,uCAAuC,EAAEE,YAAY,IAAI,CAAC,CAAC,CAAC;YACtEQ;QACF;IAIN,OAAO;QACL,MAAMR,YAAY,IAAI;QACtBO;IACF;AACF,GAAG;AASI,MAAME,sBAAsBA,GAAGlC,iBAAiB,CAAC,UAAWmC,OAA6B;IAC9F,MAAMC,aAAa,OAAO7B,cAAc,CAAqB,IAAO;YAAE,MAAM;QAAc;IAC1F,MAAM8B,qBAAqB,OAAOtC,aAAa;IAC/C,MAAM0B,cAAc,OAAOpB,QAAQ,CAACgC;IACpC,MAAMC,SAAStC,iBAAiB,CAAC,UAAWuC,KAAuB;QACjE,MAAMC,UAAU,OAAOnC,OAAO,CAACoB;QAE/B,OAAQc,MAAM,IAAI;YAChB,KAAK;gBAAY;oBACf,MAAME,uBAAuB,OAAO1C,eAAe,CAACyC;oBACpD,IAAIC,sBAAsB;wBACxB,MAAMC,OAAO,OAAO3C,aAAa;wBACjC,OAAOM,OAAO,CAACoB,aAAaiB;oBAC9B;oBACA;gBACF;YACA,KAAK;gBAAU;oBACb,OAAO3C,aAAa,CAACyC,SAASD,MAAM,KAAK;oBACzC;gBACF;YACA,KAAK;gBAAY;oBACf,OAAOhC,aAAa,CAClB6B,YACAZ,oBAAoBA,CAAC;wBAAE,GAAGW,OAAO;wBAAE,aAAaI;oBAAM,GAAG,IAAI,CAC3DvC,UAAU,CAAC,CAAC2C,QAA+B;4BACzC,MAAM;4BACN,YAAYA;wBACd,KACA3C,eAAe,CAAC,CAAC4C,QAAU7C,aAAa,CAACyC,SAASI;oBAGtD,MAAMD,QAAQ,OAAOpC,aAAa,CAAC6B;oBACnC,IAAIO,MAAM,IAAI,KAAK,eAAe;wBAChC,OAAO,OAAO3C,UAAU,CACtB,IAAI6C,UAAU;oBAElB;oBACA,OAAO9C,gBAAgB,CAACyC,SAASG,MAAM,UAAU;gBACnD;QACF;IACF;IACA,MAAMX,aAAa3B,OAAO,CAACoB,aAAa,IAAI,CAC1CzB,cAAc,CAACD,iBAAc,GAC7BC,cAAc,CAAC,CAAC2C,QAAUA,MAAM,UAAU;IAG5C,OAAO;QACLX;QACAM;IACF;AACF,GAAG;AAEI,MAAMQ,kBAAkBA,GAAG9C,iBAAiB,CAAC,UAAW,EAC7D0B,QAAQ,EACRC,IAAI,EACJC,IAAI,EACkB;IACtB,MAAM,EAAEmB,eAAe,EAAEC,OAAO,EAAE,GAAG,OAAOnC,uBAAuBA,CAAC;QAAEe;IAAK;IAC3E,MAAMqB,aAAa,OAAO/C,qBAAqB;IAC/C,MAAM2B,OAAO,OAAOzB,SAAS;IAC7B,MAAM8C,SAAS,OAAO/B,MAAMA;IAC5B,MAAMgC,UAAU,OAAOjC,cAAcA;IAErC,OAAO+B,WAAW,MAAM,CAACpB,KAAK,IAAI,CAACkB,iBAAiB/B,YAAYA,GAAG;QACjE,OAAO;QACP,WAAW;IACb;IAEA,MAAMoC,kBAAkB,OAAOlB,sBAAsBA,CAAC;QACpDR;QACAC;QACA,MAAMoB;IACR;IACA,MAAMT,SAAStC,iBAAiB,CAAC,UAAWuC,KAAuB;QACjE,OAAQA,MAAM,IAAI;YAChB,KAAK;gBAAY;oBACf,OAAOa,gBAAgB,MAAM,CAACb;oBAC9B,MAAMc,mBACJd,MAAM,YAAY,CAAC,IAAI,CAAC,CAACe,OAASzB,KAAK,QAAQ,CAACyB,MAAM,QAAQ,CAAC,SAC/Df,MAAM,YAAY,CAAC,EAAE;oBACvB,MAAMgB,cACJF,qBAAqBG,YACjBA,YACA3B,KAAK,QAAQ,CAACkB,iBAAiBM;oBACrC,MAAMI,UAAUF,eAAe;oBAE/B,OAAOvD,cAAc,CAAC,GAAGsB,aAAa,CAAC,KAAK,WAAW,EAAEmC,QAAQ,GAAG,CAAC;oBACrE;gBACF;YACA,KAAK;gBAAU;oBACb,OAAOL,gBAAgB,MAAM,CAACb;oBAC9B,OAAOY,QAAQ,mBAAmB,CAACZ,MAAM,WAAW;oBACpD,OAAOvC,eAAe,CAACuC,MAAM,KAAK;oBAClC;gBACF;YACA,KAAK;gBAAY;oBACf,IAAIA,MAAM,QAAQ,KAAKiB,WAAW;wBAChC,OAAOxD,iBAAiB,CAACuC,MAAM,QAAQ;oBACzC;oBACA,OAAOa,gBAAgB,MAAM,CAACb,OAAO,IAAI,CACvCvC,cAAc,CAACmD,QAAQ,kBAAkB,CAACZ,MAAM,UAAU,IAC1DvC,UAAU,CAAC;wBACT,MAAM0D,WACJnB,MAAM,QAAQ,KAAKiB,YAAY,KAAK,CAAC,IAAI,EAAEnC,cAAcA,CAACkB,MAAM,QAAQ,GAAG;wBAC7E,MAAMoB,YAAYpB,MAAM,SAAS,CAC9B,GAAG,CAAC,CAAC,EAAEmB,QAAQ,EAAEE,IAAI,EAAE,GACtBF,aAAaF,YAAYI,OAAO,GAAGA,KAAK,CAAC,EAAEvC,cAAcA,CAACqC,WAAW,EAEtE,IAAI,CAAC;wBACR,MAAMG,UAAUF,UAAU,MAAM,KAAK,IAAI,KAAK,CAAC,EAAE,EAAErC,YAAY,CAACqC,YAAY;wBAE5E,OAAO3D,cAAc,CAAC,GAAGsB,cAAc,CAAC,KAAK,MAAM,EAAEoC,WAAWG,SAAS;oBAC3E,IACA7D,eAAY,CAAC,CAAC4C,QAAU5C,eAAe,CAAC4C;gBAE5C;QACF;IACF;IACA,MAAMkB,QAAQZ,OACX,KAAK,CACJ9B,mBAAmBA,CAAC2B,iBAAiBC,SAAS;QAC5C,oBAAoBG,QAAQ,kBAAkB;QAC9C,0BAA0BA,QAAQ,wBAAwB;IAC5D,IAED,IAAI,CAAC3C,iBAAiB,CAAC8B;IAC1B,MAAMN,aAAa,OAAOvB,uBAAuB,CAC/CA,iBAAiB,CAAC;QAChBA,gBAAgB,CAAC,OAAOG,cAAcA,EAAEuC,QAAQ,UAAU;QAC1D1C,gBAAgB,CAAC,KAAK,MAAM2C,gBAAgB,UAAU;KACvD;IAGH,OAAO;QACL,iBAAiBD,QAAQ,KAAK;QAC9BnB;QACA8B;IACF;AACF,GAAG;AAII,MAAMC,oBAAoBA,GAAG/D,iBAAiB,CAAC,UAAWgE,WAA2B;IAC1F,OAAO,OAAOhE,aAAa,CACzBA,UAAU,CAAC;QACT,MAAMiE,SAAS,OAAO9D,YAAY,CAACO,gBAAgB,CAACsD,YAAY,UAAU,GAAG,IAAI,CAC/EhE,iBAAiB,CAAC;YAAE,kBAAkB;QAAK;QAE7C,OAAOA,mBAAmB,CAAC,IAAMgE,YAAY,eAAe;QAC5D,MAAMF,QAAQpD,+BAA+B,CAAC,CAACwD,UAC7ClE,cAAc,CACZ,GAAGsB,gBAAgB,CAAC,KAAK,eAAe,EAAEA,YAAY,CAACX,iBAAmB,EAAE,EAAE,EAAEuD,SAAS,GAE3F,IAAI,CAAClE,cAAc,CAACgE,YAAY,KAAK;QAEvC,OAAO,OAAOhE,gBAAgB,CAAC8D,OAAO7D,UAAU,CAACgE;IACnD;AAEJ,GAAG;AAEI,MAAME,cAAcA,GAAGnE,SAAS,CAAC,6BAA6B,UACnEmC,OAA8B;IAE9B,MAAM6B,cAAc,OAAOlB,kBAAkBA,CAACX,SAAS,IAAI,CAACnC,cAAc,CAACmB,YAAY;IAEvF,OAAO,OAAO4C,oBAAoBA,CAACC;AACrC,GAAG"}
|
|
1
|
+
{"version":3,"file":"build/dev.js","sources":["../../src/build/dev.ts"],"sourcesContent":["import {\n Cause,\n Deferred,\n Effect,\n Fiber,\n FileSystem,\n Layer,\n Path,\n Ref,\n Schema,\n Scope,\n ScopedRef,\n Stream,\n} from 'effect';\nimport { HttpBody, HttpRouter, HttpServer, HttpServerResponse } from 'effect/unstable/http';\n\nimport PackageJson from '../../package.json' with { type: 'json' };\nimport { DevChannelPath } from '../dev/channel';\nimport { resolveApplicationBuild } from './build';\nimport { loadServerBundle, makeRunnableHttpLayer } from './compiled-server';\nimport { DevOutputDir, EnvironmentConfig } from './contract';\nimport { makeDevChannel } from './dev-channel';\nimport { Rspack, type RspackError, type RspackWatchEvent } from './rspack';\nimport { makeRspackDevConfig } from './rspack-config';\nimport { formatDuration, Terminal } from './terminal';\n\ntype RspackCompilation = Extract<RspackWatchEvent, { readonly _tag: 'Compiled' }>;\n\nexport class DevGenerationError extends Schema.TaggedError<DevGenerationError>()(\n 'DevGenerationError',\n {\n message: Schema.String,\n cause: Schema.Defect(),\n },\n) {}\n\ntype AcquireDevGenerationOptions = {\n readonly compilation: RspackCompilation;\n readonly hostname: string;\n readonly port: number;\n readonly root: string;\n};\n\ntype DevGenerationOptions = Omit<AcquireDevGenerationOptions, 'compilation'>;\n\nexport type DevApplicationOptions = DevGenerationOptions;\n\nexport const acquireDevGeneration = Effect.fnUntraced(function* ({\n compilation,\n hostname,\n port,\n root,\n}: AcquireDevGenerationOptions) {\n const path = yield* Path.Path;\n const bundle = yield* loadServerBundle(\n path.resolve(compilation.serverBundle.outputPath, compilation.serverBundle.filename),\n );\n const HttpLayer = yield* makeRunnableHttpLayer({\n bundle,\n clientAssetsCacheControl: EnvironmentConfig.development.clientAssetsCacheControl,\n clientOutputDir: EnvironmentConfig.development.clientOutputDir,\n hostname,\n port,\n root,\n });\n const httpEffect = yield* HttpRouter.toHttpEffect(HttpLayer).pipe(\n Effect.mapError(\n (cause) =>\n new DevGenerationError({\n message: `Failed to start development generation ${compilation.hash}.`,\n cause,\n }),\n ),\n );\n\n // Close request work before the generation's application services.\n const generationScope = yield* Effect.scope;\n const requests = yield* Scope.fork(generationScope, 'parallel');\n const ownRequest = Effect.withFiber((fiber) => {\n Fiber.runIn(fiber, requests);\n return Effect.void;\n });\n\n return {\n hash: compilation.hash,\n httpEffect: Effect.gen(function* () {\n yield* ownRequest;\n const response = yield* httpEffect;\n const body = response.body;\n if (body._tag !== 'Stream') {\n return response;\n }\n\n // Bun consumes the response body on a separate fiber after the handler returns.\n return HttpServerResponse.setBody(\n response,\n HttpBody.stream(\n Stream.onStart(body.stream, ownRequest),\n body.contentType,\n body.contentLength,\n ),\n );\n }),\n };\n});\n\ntype DevGeneration = Effect.Success<ReturnType<typeof acquireDevGeneration>>;\ntype DevGenerationFailure = Effect.Error<ReturnType<typeof acquireDevGeneration>> | RspackError;\n\ntype DevGenerationState =\n | { readonly _tag: 'Unavailable' }\n | { readonly _tag: 'Ready'; readonly generation: DevGeneration };\n\nexport const makeDevGenerationStore = Effect.fnUntraced(function* (options: DevGenerationOptions) {\n const generation = yield* ScopedRef.make<DevGenerationState>(() => ({ _tag: 'Unavailable' }));\n const initialCompilation = yield* Deferred.make<DevGeneration, DevGenerationFailure>();\n const compilation = yield* Ref.make(initialCompilation);\n const update = Effect.fnUntraced(function* (event: RspackWatchEvent) {\n const current = yield* Ref.get(compilation);\n\n switch (event._tag) {\n case 'Building': {\n const compilationCompleted = yield* Deferred.isDone(current);\n if (compilationCompleted) {\n const next = yield* Deferred.make<DevGeneration, DevGenerationFailure>();\n yield* Ref.set(compilation, next);\n }\n return;\n }\n case 'Failed': {\n yield* Deferred.fail(current, event.error);\n return;\n }\n case 'Compiled': {\n yield* ScopedRef.set(\n generation,\n acquireDevGeneration({ ...options, compilation: event }).pipe(\n Effect.interruptible,\n Effect.map((ready): DevGenerationState => ({\n _tag: 'Ready',\n generation: ready,\n })),\n Effect.tapError((error) => Deferred.fail(current, error)),\n ),\n );\n const ready = yield* ScopedRef.get(generation);\n if (ready._tag === 'Unavailable') {\n return yield* Effect.die(\n new TypeError('Expected the completed development generation to be available.'),\n );\n }\n yield* Deferred.succeed(current, ready.generation);\n }\n }\n });\n const httpEffect = Ref.get(compilation).pipe(\n Effect.flatMap(Deferred.await),\n Effect.flatMap((ready) => ready.httpEffect),\n );\n\n return {\n httpEffect,\n update,\n };\n});\n\nexport const makeDevApplication = Effect.fnUntraced(function* ({\n hostname,\n port,\n root,\n}: DevApplicationOptions) {\n const { applicationRoot, entries } = yield* resolveApplicationBuild({ root });\n const fileSystem = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const rspack = yield* Rspack;\n const channel = yield* makeDevChannel;\n\n yield* fileSystem.remove(path.join(applicationRoot, DevOutputDir), {\n force: true,\n recursive: true,\n });\n\n const generationStore = yield* makeDevGenerationStore({\n hostname,\n port,\n root: applicationRoot,\n });\n const update = Effect.fnUntraced(function* (event: RspackWatchEvent) {\n switch (event._tag) {\n case 'Building': {\n yield* generationStore.update(event);\n const firstChangedFile =\n event.changedFiles.find((file) => path.basename(file).includes('.')) ??\n event.changedFiles[0];\n const changedPath =\n firstChangedFile === undefined\n ? undefined\n : path.relative(applicationRoot, firstChangedFile);\n const subject = changedPath ?? 'application';\n\n yield* Effect.logInfo(`${Terminal.cyan('●')} Compiling ${subject}...`);\n return;\n }\n case 'Failed': {\n yield* generationStore.update(event);\n yield* channel.publishBuildFailure(event.diagnostics);\n yield* Effect.logError(event.error);\n return;\n }\n case 'Compiled': {\n if (event.warnings !== undefined) {\n yield* Effect.logWarning(event.warnings);\n }\n yield* generationStore.update(event).pipe(\n Effect.andThen(channel.publishCompilation(event.clientHash)),\n Effect.tap(() => {\n const duration =\n event.duration === undefined ? '' : ` in ${formatDuration(event.duration)}`;\n const compilers = event.compilers\n .map(({ duration, name }) =>\n duration === undefined ? name : `${name} ${formatDuration(duration)}`,\n )\n .join(' · ');\n const details = compilers.length === 0 ? '' : ` ${Terminal.dim(compilers)}`;\n\n return Effect.logInfo(`${Terminal.green('✓')} Ready${duration}${details}`);\n }),\n Effect.catch((error) =>\n channel\n .publishBuildFailure(Cause.pretty(Cause.fail(error)))\n .pipe(Effect.andThen(Effect.logError(error))),\n ),\n );\n }\n }\n });\n const watch = rspack\n .watch(\n makeRspackDevConfig(applicationRoot, entries, {\n onCompilationStart: channel.onCompilationStart,\n onServerComponentChanges: channel.onServerComponentChanges,\n }),\n )\n .pipe(Stream.runForEach(update));\n const httpEffect = yield* HttpRouter.toHttpEffect(\n HttpRouter.addAll([\n HttpRouter.route('GET', DevChannelPath, channel.httpEffect),\n HttpRouter.route('*', '/*', generationStore.httpEffect),\n ]),\n );\n\n return {\n closeDevChannel: channel.close,\n httpEffect,\n watch,\n };\n});\n\ntype DevApplication = Effect.Success<ReturnType<typeof makeDevApplication>>;\n\nexport const launchDevApplication = Effect.fnUntraced(function* (application: DevApplication) {\n return yield* Effect.scoped(\n Effect.gen(function* () {\n const server = yield* Layer.launch(HttpServer.serve(application.httpEffect)).pipe(\n Effect.forkScoped({ startImmediately: true }),\n );\n yield* Effect.addFinalizer(() => application.closeDevChannel);\n const watch = HttpServer.addressFormattedWith((address) =>\n Effect.logInfo(\n `${Terminal.magenta('▌')} effective-rsc ${Terminal.dim(PackageJson.version)} ${address}`,\n ),\n ).pipe(Effect.andThen(application.watch));\n\n return yield* Effect.raceFirst(watch, Fiber.join(server));\n }),\n );\n});\n\nexport const devApplication = Effect.fn('ersc/build/devApplication')(function* (\n options: DevApplicationOptions,\n) {\n const application = yield* makeDevApplication(options).pipe(Effect.provide(Rspack.layer));\n\n return yield* launchDevApplication(application);\n});\n"],"names":["Cause","Deferred","Effect","Fiber","FileSystem","Layer","Path","Ref","Schema","Scope","ScopedRef","Stream","HttpBody","HttpRouter","HttpServer","HttpServerResponse","PackageJson","DevChannelPath","resolveApplicationBuild","loadServerBundle","makeRunnableHttpLayer","DevOutputDir","EnvironmentConfig","makeDevChannel","Rspack","makeRspackDevConfig","formatDuration","Terminal","DevGenerationError","acquireDevGeneration","compilation","hostname","port","root","path","bundle","HttpLayer","httpEffect","cause","generationScope","requests","ownRequest","fiber","response","body","makeDevGenerationStore","options","generation","initialCompilation","update","event","current","compilationCompleted","next","ready","error","TypeError","makeDevApplication","applicationRoot","entries","fileSystem","rspack","channel","generationStore","firstChangedFile","file","changedPath","undefined","subject","duration","compilers","name","details","watch","launchDevApplication","application","server","address","devApplication"],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -83,6 +83,8 @@ const runDev = Effect.fnUntraced(function*({ hostname, port }) {
|
|
|
83
83
|
root: process.cwd()
|
|
84
84
|
}).pipe(Effect.provide(__rspack_external__effect_platform_bun_BunHttpServer_0e4f7bbb.layer({
|
|
85
85
|
development: true,
|
|
86
|
+
// Explicit dev shutdown interrupts request scopes before releasing their generations.
|
|
87
|
+
disablePreemptiveShutdown: true,
|
|
86
88
|
hostname,
|
|
87
89
|
idleTimeout: ApplicationIdleTimeoutSeconds,
|
|
88
90
|
maxRequestBodySize: ApplicationMaxRequestBodySizeBytes,
|