@rsc-kit/core 0.30.48 → 0.30.50

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/dist/vite.js CHANGED
@@ -3465,11 +3465,16 @@ import { depthOf, fileWins, folderOf, nearestShareImage } from ${JSON.stringify(
3465
3465
  import { SlotBoundary } from ${JSON.stringify(join(packageDir, "js/SlotBoundary"))}
3466
3466
  import { RouteErrorBoundary } from ${JSON.stringify(join(packageDir, "js/RouteErrorBoundary"))}
3467
3467
  import __rsc_assets from 'virtual:vite-rsc/assets-manifest'
3468
- import { isSharedSection, sectionComponent } from ${JSON.stringify(join(packageDir, "js/section"))}
3468
+ ${
3469
+ // The backend's actions, so defineForm({ action: contactSend }) can tell
3470
+ // which backend function a stub calls: the stub is the key, by identity.
3471
+ Object.keys(hostActions).length > 0
3472
+ ? `import * as __rsc_host_actions from ${JSON.stringify(join(sourceDir, HOST_ACTIONS_MODULE))}\n`
3473
+ : ""}import { isSharedSection, sectionComponent } from ${JSON.stringify(join(packageDir, "js/section"))}
3469
3474
  import { shareRender } from ${JSON.stringify(join(packageDir, "sharedRenders"))}
3470
3475
  import { PathnameProvider } from ${JSON.stringify(join(packageDir, "js/PathnameProvider"))}
3471
3476
  import { DefaultRouteError } from ${JSON.stringify(join(packageDir, "js/DefaultRouteError"))}
3472
- import { noteNotFoundRow, noteRenderFailure, renderAsNobody, requestFromCrawler, requestSearch, searchParams as requestSearchParams, withRequest, withUrl } from ${JSON.stringify(join(packageDir, "request"))}
3477
+ import { guardsPassed, noteNotFoundRow, noteRenderFailure, renderAsNobody, requestFromCrawler, requestPageUrl, requestSearch, searchParams as requestSearchParams, withRequest, withUrl } from ${JSON.stringify(join(packageDir, "request"))}
3473
3478
  import { parseParams, parseSearchParams, parseBody, isSearchParamsError, isBodyError } from ${JSON.stringify(join(packageDir, "routeSchema"))}
3474
3479
  import { notFoundDigest, isNotFoundSignal } from ${JSON.stringify(join(packageDir, "notFound"))}
3475
3480
  import { noteRequestRead, notePageProps, urlOf } from ${JSON.stringify(join(packageDir, "request"))}
@@ -3860,11 +3865,14 @@ export async function getStaticParams(component: string): Promise<Record<string,
3860
3865
  // not reach the Flight render.
3861
3866
  const HOST_GLOBAL = ${JSON.stringify(hostGlobal)}
3862
3867
 
3863
- // For defineForm({ action }): which global calls the backend, and what each
3864
- // function takes. On the global because a form is defined as its module loads,
3865
- // and read when it first renders, by which time this entry has run.
3868
+ // For defineForm({ action: contactSend }): which backend function each
3869
+ // generated action calls, and what each function takes. On the global because
3870
+ // a form is defined as its module loads, and read when it first renders, by
3871
+ // which time this entry has run.
3866
3872
  ;(globalThis as Record<symbol, unknown>)[Symbol.for('rsc-kit.host-forms')] = {
3867
- global: HOST_GLOBAL,
3873
+ actions: new Map<unknown, string>(${Object.keys(hostActions).length > 0
3874
+ ? `Object.entries(${JSON.stringify(hostActions)}).map(([name, target]) => [(__rsc_host_actions as Record<string, unknown>)[name], target])`
3875
+ : ""}),
3868
3876
  inputs: ${JSON.stringify(formInputs(hostTypes, hostDefs))},
3869
3877
  }
3870
3878
 
@@ -4847,6 +4855,13 @@ let middlewareChains: Record<string, string[]> | null = null
4847
4855
 
4848
4856
  let hostChains: Record<string, string[]> | null = null
4849
4857
 
4858
+ /** The params each guarded route's url binds, by the name runHostMiddleware is asked with. */
4859
+ let hostParamNames: Record<string, string[]> = {}
4860
+
4861
+ function boundNames(segments: { type: string; value: string }[] | undefined): string[] {
4862
+ return (segments ?? []).filter((segment) => segment.type !== 'static').map((segment) => segment.value)
4863
+ }
4864
+
4850
4865
  /**
4851
4866
  * Guards the host runs, named by a route.ts and meaningless here.
4852
4867
  *
@@ -4860,17 +4875,23 @@ let hostChains: Record<string, string[]> | null = null
4860
4875
  * whoever asked, if the absence of a refusal is read as permission. Only a
4861
4876
  * literal true allows.
4862
4877
  */
4863
- async function runHostMiddleware(component) {
4878
+ async function runHostMiddleware(component, props: Record<string, unknown> = {}) {
4864
4879
  if (!hostChains) {
4865
4880
  hostChains = {}
4866
4881
 
4867
4882
  for (const route of manifest().routes) {
4868
- if (route.hostMiddleware?.length) hostChains[route.component] = route.hostMiddleware
4883
+ if (route.hostMiddleware?.length) {
4884
+ hostChains[route.component] = route.hostMiddleware
4885
+ hostParamNames[route.component] = boundNames(route.segments)
4886
+ }
4869
4887
  }
4870
4888
 
4871
4889
  // Api routes, keyed by module name - the key runRouteMiddleware is asked with.
4872
4890
  for (const api of manifest().apis ?? []) {
4873
- if (api.hostMiddleware?.length) hostChains[api.name] = api.hostMiddleware
4891
+ if (api.hostMiddleware?.length) {
4892
+ hostChains[api.name] = api.hostMiddleware
4893
+ hostParamNames[api.name] = boundNames(api.segments)
4894
+ }
4874
4895
  }
4875
4896
  }
4876
4897
 
@@ -4885,7 +4906,21 @@ async function runHostMiddleware(component) {
4885
4906
  )
4886
4907
  }
4887
4908
 
4888
- const answer = await currentHost(HOST_MIDDLEWARE_FN, names)
4909
+ // The page the names are about, as a second argument a host may ignore. The
4910
+ // call itself is a POST from this renderer to an endpoint of the backend's,
4911
+ // so a middleware reading the request it runs under saw that: a signed-url
4912
+ // check verified the endpoint's url and refused every link, and a policy
4913
+ // on a route param had no param to bind. The url is the visitor's,
4914
+ // the params the route matched - strings only, a catch-all's list joined
4915
+ // the way its url spells it. Only the names the route binds: a page's props
4916
+ // carry its query beside them, and ?order=8 must not stand in for {order}.
4917
+ const page = { url: requestPageUrl(), params: routeParams(props, hostParamNames[component] ?? []) }
4918
+ const passed = guardsPassed()
4919
+ const asked = JSON.stringify([names, page])
4920
+
4921
+ if (passed?.has(asked)) return
4922
+
4923
+ const answer = await currentHost(HOST_MIDDLEWARE_FN, names, page)
4889
4924
 
4890
4925
  // Anything other than a literal true. A host answering null, undefined, a
4891
4926
  // string, or an object it happened to build on the way to an error is not
@@ -4893,11 +4928,27 @@ async function runHostMiddleware(component) {
4893
4928
  if (answer !== true) {
4894
4929
  throw new Error('Host middleware refused ' + component + ' (' + names.join(', ') + ').')
4895
4930
  }
4931
+
4932
+ passed?.add(asked)
4896
4933
  }
4897
4934
 
4898
4935
 
4936
+ /** A route's params as a backend can bind them: every value a string. */
4937
+ function routeParams(props: Record<string, unknown>, bound: string[]): Record<string, string> {
4938
+ const params: Record<string, string> = {}
4939
+
4940
+ for (const name of bound) {
4941
+ const value = props[name]
4942
+
4943
+ if (typeof value === 'string') params[name] = value
4944
+ else if (Array.isArray(value) && value.every((part) => typeof part === 'string')) params[name] = value.join('/')
4945
+ }
4946
+
4947
+ return params
4948
+ }
4949
+
4899
4950
  async function runMiddleware(component: string, props: Record<string, unknown> = {}): Promise<void> {
4900
- await runHostMiddleware(component)
4951
+ await runHostMiddleware(component, props)
4901
4952
 
4902
4953
  // Read from the route table rather than passed in, so every render path is
4903
4954
  // covered by construction and no host has to remember to forward them.