@rsc-kit/core 0.30.1 → 0.30.3
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/action.js +32 -7
- package/dist/action.js.map +1 -1
- package/dist/conformance.js +3 -0
- package/dist/conformance.js.map +1 -1
- package/dist/host.d.ts +1 -0
- package/dist/host.js +1 -1
- package/dist/host.js.map +1 -1
- package/dist/hostCalls.js +11 -14
- package/dist/hostCalls.js.map +1 -1
- package/dist/js/errors.d.ts +25 -0
- package/dist/js/errors.js +14 -0
- package/dist/js/errors.js.map +1 -1
- package/dist/js/queryClient.js +4 -0
- package/dist/js/queryClient.js.map +1 -1
- package/dist/query.d.ts +15 -0
- package/dist/query.js +25 -0
- package/dist/query.js.map +1 -1
- package/dist/vite.js +18 -3
- package/dist/vite.js.map +1 -1
- package/package.json +1 -1
package/dist/action.js
CHANGED
|
@@ -23,6 +23,8 @@ import { validateWith } from './js/standardSchema.js';
|
|
|
23
23
|
import { decodeFormData } from './js/formEncoding.js';
|
|
24
24
|
import { markQuery, QueryValidationError } from './query.js';
|
|
25
25
|
import { isRedirectSignal } from './redirectDigest.js';
|
|
26
|
+
import { isNotFoundSignal } from './notFound.js';
|
|
27
|
+
import { ServerAuthenticationError, ServerAuthorizationError } from './js/errors.js';
|
|
26
28
|
/**
|
|
27
29
|
* A middleware that neither continued nor refused.
|
|
28
30
|
*
|
|
@@ -141,6 +143,13 @@ export function fieldErrors(errors) {
|
|
|
141
143
|
throw new ActionValidationError(normalised);
|
|
142
144
|
}
|
|
143
145
|
const GENERIC = 'Something went wrong.';
|
|
146
|
+
/**
|
|
147
|
+
* Whether the backend turned this caller away: not signed in, not allowed, or
|
|
148
|
+
* nothing there for them. Each carries a message written for the person.
|
|
149
|
+
*/
|
|
150
|
+
function turnedAway(error) {
|
|
151
|
+
return (error instanceof ServerAuthenticationError || error instanceof ServerAuthorizationError || isNotFoundSignal(error));
|
|
152
|
+
}
|
|
144
153
|
/**
|
|
145
154
|
* FormData in, a plain object out — what a schema expects to be handed.
|
|
146
155
|
*
|
|
@@ -213,7 +222,7 @@ export function createActionClient(options = {}) {
|
|
|
213
222
|
* be seen - and its data only once the declared schema has checked it.
|
|
214
223
|
* Data with no schema to check it, or that fails the schema, never
|
|
215
224
|
* reaches the browser: the first is said in the server's log, the second
|
|
216
|
-
* is a bug in the server
|
|
225
|
+
* is a bug in the server, returned as the error each terminal reports.
|
|
217
226
|
*/
|
|
218
227
|
const refusalResult = async (error) => {
|
|
219
228
|
if (error.data === undefined)
|
|
@@ -224,9 +233,7 @@ export function createActionClient(options = {}) {
|
|
|
224
233
|
}
|
|
225
234
|
const checked = await refusalSchema['~standard'].validate(error.data);
|
|
226
235
|
if (checked.issues) {
|
|
227
|
-
return {
|
|
228
|
-
serverError: report(new Error(`An action refused with data its .refusal(schema) does not accept: ${checked.issues.map((issue) => issue.message).join('; ')}`)),
|
|
229
|
-
};
|
|
236
|
+
return new Error(`An action refused with data its .refusal(schema) does not accept: ${checked.issues.map((issue) => issue.message).join('; ')}`);
|
|
230
237
|
}
|
|
231
238
|
return { serverError: error.message, refusal: checked.value };
|
|
232
239
|
};
|
|
@@ -258,8 +265,16 @@ export function createActionClient(options = {}) {
|
|
|
258
265
|
if (isActionValidationError(error)) {
|
|
259
266
|
return { validationErrors: error.errors };
|
|
260
267
|
}
|
|
261
|
-
if (isActionRefusal(error))
|
|
262
|
-
|
|
268
|
+
if (isActionRefusal(error)) {
|
|
269
|
+
const refused = await refusalResult(error);
|
|
270
|
+
return (refused instanceof Error ? { serverError: report(refused) } : refused);
|
|
271
|
+
}
|
|
272
|
+
// Turned away by the backend - not signed in, not allowed, no such
|
|
273
|
+
// record - is an answer too, and its message is meant to be seen.
|
|
274
|
+
// Not rethrown as a redirect is: the action endpoint answers a
|
|
275
|
+
// throw with a 500, and the form would show nothing at all.
|
|
276
|
+
if (turnedAway(error))
|
|
277
|
+
return { serverError: error.message };
|
|
263
278
|
return { serverError: report(error) };
|
|
264
279
|
}
|
|
265
280
|
});
|
|
@@ -274,6 +289,11 @@ export function createActionClient(options = {}) {
|
|
|
274
289
|
throw error;
|
|
275
290
|
if (isRedirectSignal(error))
|
|
276
291
|
throw error;
|
|
292
|
+
// Left as they are, as a redirect is. A page that reads through a
|
|
293
|
+
// query answers 401, 403 or its not-found page, as it does calling
|
|
294
|
+
// the backend directly; the read endpoint answers the same statuses.
|
|
295
|
+
if (turnedAway(error))
|
|
296
|
+
throw error;
|
|
277
297
|
// Thrown, not returned. A cache library reports failure by
|
|
278
298
|
// rejection, so a query that answered with an error-shaped object
|
|
279
299
|
// would look like a successful read of something odd.
|
|
@@ -284,7 +304,12 @@ export function createActionClient(options = {}) {
|
|
|
284
304
|
// the error for a fetcher that wants it.
|
|
285
305
|
if (isActionRefusal(error)) {
|
|
286
306
|
const refused = await refusalResult(error);
|
|
287
|
-
|
|
307
|
+
if (refused instanceof Error)
|
|
308
|
+
throw new Error(report(refused));
|
|
309
|
+
throw Object.assign(new Error(refused.serverError), {
|
|
310
|
+
refusal: refused.refusal,
|
|
311
|
+
refusalStatus: error.refusalStatus,
|
|
312
|
+
});
|
|
288
313
|
}
|
|
289
314
|
throw new Error(report(error));
|
|
290
315
|
}
|
package/dist/action.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action.js","sourceRoot":"","sources":["../src/action.ts"],"names":[],"mappings":"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","sourcesContent":["// Server actions with a schema, middleware, and types that follow from both.\n//\n// export const action = createActionClient({ onError: report })\n//\n// export const createPost = action\n// .use(async ({ next }) => next({ ctx: { user: await currentUser() } }))\n// .input(z.object({ title: z.string().min(3) }))\n// .handler(async ({ input, ctx }) => savePost(ctx.user.id, input.title))\n//\n// `input` is typed from the schema and `ctx` from every middleware that ran, so\n// the handler is checked against both without either being written down twice.\n//\n// The built action RETURNS its failures rather than throwing them, and that is\n// not a style choice. React serialises a rejected server action opaquely —\n// production strips the message and leaves a digest — so a thrown validation\n// error reaches the browser as \"an error occurred\" and the fields it named are\n// gone. A returned object crosses the boundary intact.\n//\n// Distinct from `middleware.ts` in a route directory, which decides whether a\n// page may render. This wraps one action. They are different questions: an\n// action is reachable without any page, which is why it defends itself.\n\nimport { validateWith, type StandardSchemaV1 } from './js/standardSchema.js'\nimport { decodeFormData } from './js/formEncoding.js'\nimport { markQuery, QueryValidationError, type QueryOptions } from './query.js'\nimport { isRedirectSignal } from './redirectDigest.js'\n\n/**\n * What an action answers with. One of `data`, `validationErrors`,\n * `serverError` and `redirected` is set; `refusal` only ever beside\n * `serverError`.\n */\nexport interface ActionResult<Data, Refusal = never> {\n /** What the handler returned. */\n data?: Data\n /** Field name to messages, in the shape a form already renders. */\n validationErrors?: Record<string, string[]>\n /**\n * The action did not happen, as a message the browser may see: a refusal's\n * own message - see `refuse()` - or something unexpected, reduced by\n * `onError` to one that says nothing a stranger should not see.\n */\n serverError?: string\n /**\n * What a refusal said beside its message - the things blocking a delete,\n * say - checked against the schema the action declared with `.refusal()`\n * and typed from it. Set only by `refuse()`, here or on the backend.\n */\n refusal?: Refusal\n /**\n * Where the action sent the visitor. Set by the client, which has already\n * started the navigation: the page is on its way there, and there is\n * nothing for the caller to do. Never set on the server side of the call.\n */\n redirected?: string\n}\n\n/**\n * A middleware that neither continued nor refused.\n *\n * Never reported through `onError`: that reduces an error to a message for the\n * browser, and this one is for whoever wrote the middleware. A check that\n * forgot to call `next()` would otherwise look exactly like a check that\n * passed.\n */\nexport class ActionMisuse extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'ActionMisuse'\n }\n}\n\n/** Refuse from inside a handler, naming the fields. */\n/**\n * Marks a refusal so it survives a bundle seam.\n *\n * A property rather than `instanceof`, for the reason this project keeps\n * running into: an app's actions are bundled separately from the engine, so\n * each gets its own copy of this module and its own copy of the class.\n * `instanceof` compares identity across that seam and is simply false — and\n * the refusal is then reported as a server error, so the form shows \"Something\n * went wrong\" instead of naming the fields. Everything works; nothing logs.\n *\n * Symbol.for, so the two copies agree on the key as well as the value.\n */\nconst VALIDATION_MARK = Symbol.for('@rsc-kit/core.action-validation')\n\n/**\n * Set on every function a client builds, so the build can tell them from a\n * bare \"use server\" export. The difference is the middleware: a bare export\n * runs with nothing checking who called it, and nothing else in the app\n * would ever say so. Symbol.for, because the build reads the mark from the\n * bundled copy of this module and the app's actions were built by another.\n */\nconst CLIENT_MARK = Symbol.for('@rsc-kit/core.action-client')\n\n/** Whether a server action was built by createActionClient, and so ran its chain. */\nexport function isClientBuilt(fn: unknown): boolean {\n return typeof fn === 'function' && (fn as unknown as Record<symbol, unknown>)[CLIENT_MARK] === true\n}\n\nfunction markClientBuilt<F extends Function>(fn: F): F {\n Object.defineProperty(fn, CLIENT_MARK, { value: true })\n\n return fn\n}\n\nexport class ActionValidationError extends Error {\n public readonly errors: Record<string, string[]>\n\n constructor(errors: Record<string, string[]>) {\n super('Validation failed')\n this.name = 'ActionValidationError'\n this.errors = errors\n ;(this as unknown as Record<symbol, boolean>)[VALIDATION_MARK] = true\n }\n}\n\n/** Whether this is a refusal, whichever copy of the class built it. */\nexport function isActionValidationError(error: unknown): error is ActionValidationError {\n return (\n typeof error === 'object' &&\n error !== null &&\n (error as Record<symbol, unknown>)[VALIDATION_MARK] === true\n )\n}\n\n/**\n * The field errors a handler may report, keyed by its own input's fields.\n *\n * `''` is the whole submission — for a refusal that is about no field in\n * particular, which is where the form already looks for one.\n */\nexport type FieldErrorsFor<Input> = Partial<\n Record<(Input extends object ? keyof Input & string : string) | '', string | string[]>\n>\n\nconst REFUSAL_MARK = Symbol.for('@rsc-kit/core.action-refusal')\n\n/**\n * An action declining to do what it was asked, on purpose, with a message for\n * the person who asked and - optionally - data the page can act on: the\n * records blocking a delete, the plan a quota belongs to.\n *\n * Not a validation error: the input was fine, the state of things says no.\n * And not a failure: its message is meant to be seen, so it is never\n * replaced by `onError`'s \"Something went wrong.\". It arrives as the result's\n * `serverError`, which is where a form's `formError` already reads, and its\n * data as `refusal`.\n */\nexport class ActionRefusal extends Error {\n public readonly data: unknown\n /** The status a request that is not an action - a page, a form posted without javascript - answers with. */\n public readonly refusalStatus: number\n\n constructor(message: string, data?: unknown, status = 409) {\n super(message)\n this.name = 'ActionRefusal'\n this.data = data\n this.refusalStatus = status\n ;(this as unknown as Record<symbol, boolean>)[REFUSAL_MARK] = true\n }\n}\n\n/** Whether this is a refusal, whichever copy of the class built it. */\nexport function isActionRefusal(error: unknown): error is ActionRefusal {\n return typeof error === 'object' && error !== null && (error as Record<symbol, unknown>)[REFUSAL_MARK] === true\n}\n\n/**\n * Decline, with a message to show and optional data to act on. Throws.\n *\n * if (attached.length) refuse('Still in use', { blockers: attached })\n *\n * From a handler, a middleware or anything they call. The data reaches the\n * page only when the action declares its shape with `.refusal(schema)`, and\n * only once it matches - see ActionResult.refusal. Inside a handler, the\n * `refuse` it is given is typed to that schema; this one takes anything.\n */\nexport function refuse(message: string, data?: unknown, options: { status?: number } = {}): never {\n throw new ActionRefusal(message, data, options.status)\n}\n\n/**\n * What a handler is given.\n *\n * `fieldErrors` is here as well as exported on its own, and the one here is\n * the one to use: it is typed to this handler's input, so a field the schema\n * does not have is a type error rather than an error the form never shows.\n * The bare export takes any string, for the rare check that runs outside a\n * handler.\n */\nexport interface HandlerArgs<Input, Ctx, Refusal = never> {\n input: Input\n ctx: Ctx\n /**\n * Decline, with a message and the data the action declared with\n * `.refusal(schema)`. Throws; write `return refuse(...)`, as with\n * fieldErrors.\n */\n refuse: [Refusal] extends [never]\n ? (message: string) => never\n : (message: string, data: Refusal, options?: { status?: number }) => never\n /**\n * Fail with errors on this input's fields. Throws; nothing after it runs.\n *\n * Write `return fieldErrors(...)`. It throws either way, but TypeScript does\n * not treat a never-return as terminating when the callee is a destructured\n * binding — only a declaration or an explicitly annotated variable — so\n * without the return, a value checked on the line above is still possibly\n * undefined on the line below. The return is what lets the type narrow.\n */\n fieldErrors: (errors: FieldErrorsFor<Input>) => never\n}\n\n/**\n * Fail with field errors the form can show.\n *\n * For what a schema cannot know — a name already taken, a balance too low.\n * Throws, so the handler stops where it is; the action turns it into a\n * returned result on the way out.\n *\n * Untyped by field, because it has no handler to take the input from. Inside\n * one, use the `fieldErrors` the handler is given instead.\n */\nexport function fieldErrors(errors: Record<string, string[] | string>): never {\n const normalised: Record<string, string[]> = {}\n\n for (const [field, message] of Object.entries(errors)) {\n normalised[field] = Array.isArray(message) ? message : [message]\n }\n\n throw new ActionValidationError(normalised)\n}\n\n/**\n * What `next()` hands back, carrying what the step added.\n *\n * The context a middleware contributes cannot be inferred from the arguments\n * it passes to `next` — TypeScript infers from a function's return, not from a\n * call inside it. So `next` returns this, the middleware returns it, and the\n * addition is read off the middleware's own return type.\n */\nexport interface MiddlewareResult<Extra> {\n readonly ctx: Extra\n readonly value: unknown\n}\n\n/**\n * A step that runs before the handler.\n *\n * It calls `next` to continue, optionally adding to the context, and what it\n * adds shows up in the handler's types. Returning without calling `next` — or\n * throwing — stops the action, which is how a check refuses.\n */\nexport type ActionMiddleware<Ctx, Extra extends Record<string, unknown>> = (args: {\n ctx: Ctx\n next: <E extends Record<string, unknown> = Record<string, never>>(\n opts?: { ctx?: E },\n ) => Promise<MiddlewareResult<E>>\n}) => Promise<MiddlewareResult<Extra>>\n\ntype Output<S> = S extends StandardSchemaV1<unknown, infer O> ? O : never\n\n/** What a caller may pass, before the schema parses it. */\ntype InputOf<S> = S extends StandardSchemaV1<infer I, unknown> ? I : unknown\n\n/**\n * A built action, as its callers see it.\n *\n * Typed from the schema's input when there is one, so a call with the wrong\n * shape fails the typecheck rather than the validation - and FormData beside\n * it, which is how a form calls the same action. Without a schema, anything.\n */\nexport type Action<Raw, Data, Refusal = never> = unknown extends Raw\n ? (input?: unknown) => Promise<ActionResult<Data, Refusal>>\n : undefined extends Raw\n ? (input?: Raw | FormData) => Promise<ActionResult<Data, Refusal>>\n : (input: Raw | FormData) => Promise<ActionResult<Data, Refusal>>\n\nexport interface ActionBuilder<Ctx extends Record<string, unknown>, Input, Raw = unknown, Refusal = never> {\n /** Add a step, and whatever context it contributes. */\n use<Extra extends Record<string, unknown> = Record<string, never>>(\n middleware: (args: {\n ctx: Ctx\n next: <E extends Record<string, unknown> = Record<string, never>>(\n opts?: { ctx?: E },\n ) => Promise<MiddlewareResult<E>>\n }) => Promise<MiddlewareResult<Extra>>,\n ): ActionBuilder<Ctx & Extra, Input, Raw, Refusal>\n /** Parse and check what the caller sent. The handler's `input` follows. */\n input<S extends StandardSchemaV1>(schema: S): ActionBuilder<Ctx, Output<S>, InputOf<S>, Refusal>\n /**\n * The shape of what a refusal may carry - see `refuse()`. The page gets\n * `result.refusal` typed from it, and only data that matches it: data that\n * does not is a bug in the server, answered as one.\n */\n refusal<S extends StandardSchemaV1>(schema: S): ActionBuilder<Ctx, Input, Raw, Output<S>>\n /**\n * The body.\n *\n * What the caller gets is always the result object: `data`, or a\n * refusal, or - when the action redirected - `redirected`, set by the\n * client once the navigation is under way. Always an object, so a caller\n * reading `result.validationErrors` after a redirect reads undefined and\n * not a TypeError inside a transition, which unmounts the root.\n */\n handler<Data>(\n fn: (args: HandlerArgs<Input, Ctx, Refusal>) => Promise<Data> | Data,\n ): Action<Raw, Data, Refusal>\n /**\n * The body of a READ, sharing this client's middleware and schema.\n *\n * export const getPosts = client.input(filter).query(async ({ input, ctx }) =>\n * db.posts(ctx.user.id, input))\n *\n * The same builder as `handler`, and deliberately so: an app configures its\n * auth check and its error reporting once, and both a mutation and a read go\n * through them.\n *\n * It fails differently, though, and that is not an oversight. An action\n * RETURNS its failures because React serialises a rejection opaquely. A query\n * is handed to a cache library as a fetcher, and every one of them reports\n * failure by rejection — so this returns the data directly and throws, and\n * the endpoint carries the message across for it.\n */\n query<Data>(\n fn: (args: { input: Input; ctx: Ctx }) => Promise<Data> | Data,\n options?: QueryOptions,\n ): (input?: unknown) => Promise<Data>\n}\n\nexport interface ActionClientOptions {\n /**\n * What the browser is told when something unexpected throws.\n *\n * Everything reaching here is a bug or an outage, and its message may say\n * more than a stranger should see — a query, a path, a host. Returning a\n * fixed string is the safe default; return the message only for errors you\n * raised deliberately.\n */\n onError?: (error: unknown) => string\n}\n\nconst GENERIC = 'Something went wrong.'\n\n/**\n * FormData in, a plain object out — what a schema expects to be handed.\n *\n * The form's own decoder, so the object validated here is the object the\n * browser validated. This had a flat decoder of its own: `items[0].name`\n * stayed a key spelled exactly that, `<Form>` had already parsed it into an\n * array, and a nested form passed in the browser and failed on the server\n * with the fields it named gone.\n */\nconst fromFormData = (body: FormData, schema: unknown): Record<string, unknown> => decodeFormData(body, schema)\n\nexport function createActionClient(\n options: ActionClientOptions = {},\n): ActionBuilder<Record<never, never>, undefined> {\n const report = options.onError ?? (() => GENERIC)\n\n function build<Ctx extends Record<string, unknown>, Input>(\n middlewares: ActionMiddleware<never, never>[],\n schema: StandardSchemaV1 | null,\n refusalSchema: StandardSchemaV1 | null = null,\n ): ActionBuilder<Ctx, Input> {\n /**\n * Validate, run the chain, call the body.\n *\n * Shared by both terminals, which is the point of putting a read on this\n * builder at all: one set of middleware, one schema, one place the auth\n * check lives. Refusals leave by throwing, and each terminal decides what\n * that should look like from the outside.\n */\n const pipeline = async (\n raw: unknown,\n fn: (args: HandlerArgs<never, never>) => unknown,\n ): Promise<unknown> => {\n const value = raw instanceof FormData ? fromFormData(raw, schema) : raw\n\n if (schema) {\n const invalid = await validateWith(schema, value)\n\n if (invalid) throw new ActionValidationError(invalid)\n }\n\n const parsed = schema\n ? ((await schema['~standard'].validate(value)).value as Input)\n : (value as Input)\n\n // Composed inside-out so the first `use` is the outermost — it sees the\n // others run, which is what makes timing and cleanup possible rather\n // than only checks.\n let ctx = {} as Ctx\n let index = 0\n\n const run = async (): Promise<unknown> => {\n const middleware = middlewares[index++]\n\n if (!middleware) {\n return await fn({\n input: parsed as never,\n ctx: ctx as never,\n // The same function as the export; the type on the way in is what\n // is different, and the type is the handler's input.\n fieldErrors: fieldErrors as never,\n refuse: refuse as never,\n })\n }\n\n let continued = false\n\n const result = await (middleware as unknown as ActionMiddleware<Ctx, Record<string, unknown>>)({\n ctx,\n next: (async (opts?: { ctx?: Record<string, unknown> }) => {\n continued = true\n ctx = { ...ctx, ...(opts?.ctx ?? {}) } as Ctx\n\n return { ctx, value: await run() }\n }) as never,\n })\n\n // Silence is not refusal. A middleware that neither called next() nor\n // threw has done nothing, and guessing which it meant turns a\n // forgotten `return` into a check that quietly passes.\n if (!continued) {\n throw new ActionMisuse(\n 'A middleware returned without calling next(). Call it to continue, or throw to refuse.',\n )\n }\n\n return (result as { value?: unknown })?.value\n }\n\n return await run()\n }\n\n /**\n * A refusal as the page gets it: its message, always - it was written to\n * be seen - and its data only once the declared schema has checked it.\n * Data with no schema to check it, or that fails the schema, never\n * reaches the browser: the first is said in the server's log, the second\n * is a bug in the server and answered as one.\n */\n const refusalResult = async (error: ActionRefusal): Promise<ActionResult<never, unknown>> => {\n if (error.data === undefined) return { serverError: error.message }\n\n if (!refusalSchema) {\n console.error(\n `[rsc-kit] An action refused with data, and declares no .refusal(schema) for it - the message was sent, the data was not: ${error.message}`,\n )\n\n return { serverError: error.message }\n }\n\n const checked = await refusalSchema['~standard'].validate(error.data)\n\n if (checked.issues) {\n return {\n serverError: report(\n new Error(\n `An action refused with data its .refusal(schema) does not accept: ${checked.issues.map((issue) => issue.message).join('; ')}`,\n ),\n ),\n }\n }\n\n return { serverError: error.message, refusal: checked.value }\n }\n\n return {\n use(middleware) {\n return build([...middlewares, middleware as never], schema, refusalSchema) as never\n },\n input(next) {\n return build(middlewares, next, refusalSchema) as never\n },\n refusal(next) {\n return build(middlewares, schema, next) as never\n },\n handler(fn) {\n return markClientBuilt(async (raw?: unknown) => {\n try {\n return { data: (await pipeline(raw, fn)) as Awaited<ReturnType<typeof fn>> }\n } catch (error) {\n // Past onError deliberately — see ActionMisuse.\n if (error instanceof ActionMisuse) throw error\n\n // A redirect is an instruction, not a failure: it has to reach\n // the host, which answers the action with the destination. Caught\n // here it became { serverError: 'Something went wrong.' } - a\n // login that succeeded and then showed an error.\n if (isRedirectSignal(error)) throw error\n\n if (isActionValidationError(error)) {\n return { validationErrors: error.errors }\n }\n\n if (isActionRefusal(error)) return (await refusalResult(error)) as ActionResult<never>\n\n return { serverError: report(error) }\n }\n })\n },\n query(fn, options) {\n const read = async (raw?: unknown) => {\n try {\n return await pipeline(raw, fn)\n } catch (error) {\n if (error instanceof ActionMisuse) throw error\n if (isRedirectSignal(error)) throw error\n\n // Thrown, not returned. A cache library reports failure by\n // rejection, so a query that answered with an error-shaped object\n // would look like a successful read of something odd.\n if (isActionValidationError(error)) {\n throw new QueryValidationError(error.errors)\n }\n\n // Its own message, as an action's is, and its checked data on\n // the error for a fetcher that wants it.\n if (isActionRefusal(error)) {\n const refused = await refusalResult(error)\n\n throw Object.assign(new Error(refused.serverError), { refusal: refused.refusal })\n }\n\n throw new Error(report(error))\n }\n }\n\n return markClientBuilt(markQuery(read, options)) as (input?: unknown) => Promise<never>\n },\n }\n }\n\n return build([], null)\n}\n"]}
|
|
1
|
+
{"version":3,"file":"action.js","sourceRoot":"","sources":["../src/action.ts"],"names":[],"mappings":"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","sourcesContent":["// Server actions with a schema, middleware, and types that follow from both.\n//\n// export const action = createActionClient({ onError: report })\n//\n// export const createPost = action\n// .use(async ({ next }) => next({ ctx: { user: await currentUser() } }))\n// .input(z.object({ title: z.string().min(3) }))\n// .handler(async ({ input, ctx }) => savePost(ctx.user.id, input.title))\n//\n// `input` is typed from the schema and `ctx` from every middleware that ran, so\n// the handler is checked against both without either being written down twice.\n//\n// The built action RETURNS its failures rather than throwing them, and that is\n// not a style choice. React serialises a rejected server action opaquely —\n// production strips the message and leaves a digest — so a thrown validation\n// error reaches the browser as \"an error occurred\" and the fields it named are\n// gone. A returned object crosses the boundary intact.\n//\n// Distinct from `middleware.ts` in a route directory, which decides whether a\n// page may render. This wraps one action. They are different questions: an\n// action is reachable without any page, which is why it defends itself.\n\nimport { validateWith, type StandardSchemaV1 } from './js/standardSchema.js'\nimport { decodeFormData } from './js/formEncoding.js'\nimport { markQuery, QueryValidationError, type QueryOptions } from './query.js'\nimport { isRedirectSignal } from './redirectDigest.js'\nimport { isNotFoundSignal } from './notFound.js'\nimport { ServerAuthenticationError, ServerAuthorizationError } from './js/errors.js'\n\n/**\n * What an action answers with. One of `data`, `validationErrors`,\n * `serverError` and `redirected` is set; `refusal` only ever beside\n * `serverError`.\n */\nexport interface ActionResult<Data, Refusal = never> {\n /** What the handler returned. */\n data?: Data\n /** Field name to messages, in the shape a form already renders. */\n validationErrors?: Record<string, string[]>\n /**\n * The action did not happen, as a message the browser may see: a refusal's\n * own message - see `refuse()` - or something unexpected, reduced by\n * `onError` to one that says nothing a stranger should not see.\n */\n serverError?: string\n /**\n * What a refusal said beside its message - the things blocking a delete,\n * say - checked against the schema the action declared with `.refusal()`\n * and typed from it. Set only by `refuse()`, here or on the backend.\n */\n refusal?: Refusal\n /**\n * Where the action sent the visitor. Set by the client, which has already\n * started the navigation: the page is on its way there, and there is\n * nothing for the caller to do. Never set on the server side of the call.\n */\n redirected?: string\n}\n\n/**\n * A middleware that neither continued nor refused.\n *\n * Never reported through `onError`: that reduces an error to a message for the\n * browser, and this one is for whoever wrote the middleware. A check that\n * forgot to call `next()` would otherwise look exactly like a check that\n * passed.\n */\nexport class ActionMisuse extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'ActionMisuse'\n }\n}\n\n/** Refuse from inside a handler, naming the fields. */\n/**\n * Marks a refusal so it survives a bundle seam.\n *\n * A property rather than `instanceof`, for the reason this project keeps\n * running into: an app's actions are bundled separately from the engine, so\n * each gets its own copy of this module and its own copy of the class.\n * `instanceof` compares identity across that seam and is simply false — and\n * the refusal is then reported as a server error, so the form shows \"Something\n * went wrong\" instead of naming the fields. Everything works; nothing logs.\n *\n * Symbol.for, so the two copies agree on the key as well as the value.\n */\nconst VALIDATION_MARK = Symbol.for('@rsc-kit/core.action-validation')\n\n/**\n * Set on every function a client builds, so the build can tell them from a\n * bare \"use server\" export. The difference is the middleware: a bare export\n * runs with nothing checking who called it, and nothing else in the app\n * would ever say so. Symbol.for, because the build reads the mark from the\n * bundled copy of this module and the app's actions were built by another.\n */\nconst CLIENT_MARK = Symbol.for('@rsc-kit/core.action-client')\n\n/** Whether a server action was built by createActionClient, and so ran its chain. */\nexport function isClientBuilt(fn: unknown): boolean {\n return typeof fn === 'function' && (fn as unknown as Record<symbol, unknown>)[CLIENT_MARK] === true\n}\n\nfunction markClientBuilt<F extends Function>(fn: F): F {\n Object.defineProperty(fn, CLIENT_MARK, { value: true })\n\n return fn\n}\n\nexport class ActionValidationError extends Error {\n public readonly errors: Record<string, string[]>\n\n constructor(errors: Record<string, string[]>) {\n super('Validation failed')\n this.name = 'ActionValidationError'\n this.errors = errors\n ;(this as unknown as Record<symbol, boolean>)[VALIDATION_MARK] = true\n }\n}\n\n/** Whether this is a refusal, whichever copy of the class built it. */\nexport function isActionValidationError(error: unknown): error is ActionValidationError {\n return (\n typeof error === 'object' &&\n error !== null &&\n (error as Record<symbol, unknown>)[VALIDATION_MARK] === true\n )\n}\n\n/**\n * The field errors a handler may report, keyed by its own input's fields.\n *\n * `''` is the whole submission — for a refusal that is about no field in\n * particular, which is where the form already looks for one.\n */\nexport type FieldErrorsFor<Input> = Partial<\n Record<(Input extends object ? keyof Input & string : string) | '', string | string[]>\n>\n\nconst REFUSAL_MARK = Symbol.for('@rsc-kit/core.action-refusal')\n\n/**\n * An action declining to do what it was asked, on purpose, with a message for\n * the person who asked and - optionally - data the page can act on: the\n * records blocking a delete, the plan a quota belongs to.\n *\n * Not a validation error: the input was fine, the state of things says no.\n * And not a failure: its message is meant to be seen, so it is never\n * replaced by `onError`'s \"Something went wrong.\". It arrives as the result's\n * `serverError`, which is where a form's `formError` already reads, and its\n * data as `refusal`.\n */\nexport class ActionRefusal extends Error {\n public readonly data: unknown\n /** The status a request that is not an action - a page, a form posted without javascript - answers with. */\n public readonly refusalStatus: number\n\n constructor(message: string, data?: unknown, status = 409) {\n super(message)\n this.name = 'ActionRefusal'\n this.data = data\n this.refusalStatus = status\n ;(this as unknown as Record<symbol, boolean>)[REFUSAL_MARK] = true\n }\n}\n\n/** Whether this is a refusal, whichever copy of the class built it. */\nexport function isActionRefusal(error: unknown): error is ActionRefusal {\n return typeof error === 'object' && error !== null && (error as Record<symbol, unknown>)[REFUSAL_MARK] === true\n}\n\n/**\n * Decline, with a message to show and optional data to act on. Throws.\n *\n * if (attached.length) refuse('Still in use', { blockers: attached })\n *\n * From a handler, a middleware or anything they call. The data reaches the\n * page only when the action declares its shape with `.refusal(schema)`, and\n * only once it matches - see ActionResult.refusal. Inside a handler, the\n * `refuse` it is given is typed to that schema; this one takes anything.\n */\nexport function refuse(message: string, data?: unknown, options: { status?: number } = {}): never {\n throw new ActionRefusal(message, data, options.status)\n}\n\n/**\n * What a handler is given.\n *\n * `fieldErrors` is here as well as exported on its own, and the one here is\n * the one to use: it is typed to this handler's input, so a field the schema\n * does not have is a type error rather than an error the form never shows.\n * The bare export takes any string, for the rare check that runs outside a\n * handler.\n */\nexport interface HandlerArgs<Input, Ctx, Refusal = never> {\n input: Input\n ctx: Ctx\n /**\n * Decline, with a message and the data the action declared with\n * `.refusal(schema)`. Throws; write `return refuse(...)`, as with\n * fieldErrors.\n */\n refuse: [Refusal] extends [never]\n ? (message: string) => never\n : (message: string, data: Refusal, options?: { status?: number }) => never\n /**\n * Fail with errors on this input's fields. Throws; nothing after it runs.\n *\n * Write `return fieldErrors(...)`. It throws either way, but TypeScript does\n * not treat a never-return as terminating when the callee is a destructured\n * binding — only a declaration or an explicitly annotated variable — so\n * without the return, a value checked on the line above is still possibly\n * undefined on the line below. The return is what lets the type narrow.\n */\n fieldErrors: (errors: FieldErrorsFor<Input>) => never\n}\n\n/**\n * Fail with field errors the form can show.\n *\n * For what a schema cannot know — a name already taken, a balance too low.\n * Throws, so the handler stops where it is; the action turns it into a\n * returned result on the way out.\n *\n * Untyped by field, because it has no handler to take the input from. Inside\n * one, use the `fieldErrors` the handler is given instead.\n */\nexport function fieldErrors(errors: Record<string, string[] | string>): never {\n const normalised: Record<string, string[]> = {}\n\n for (const [field, message] of Object.entries(errors)) {\n normalised[field] = Array.isArray(message) ? message : [message]\n }\n\n throw new ActionValidationError(normalised)\n}\n\n/**\n * What `next()` hands back, carrying what the step added.\n *\n * The context a middleware contributes cannot be inferred from the arguments\n * it passes to `next` — TypeScript infers from a function's return, not from a\n * call inside it. So `next` returns this, the middleware returns it, and the\n * addition is read off the middleware's own return type.\n */\nexport interface MiddlewareResult<Extra> {\n readonly ctx: Extra\n readonly value: unknown\n}\n\n/**\n * A step that runs before the handler.\n *\n * It calls `next` to continue, optionally adding to the context, and what it\n * adds shows up in the handler's types. Returning without calling `next` — or\n * throwing — stops the action, which is how a check refuses.\n */\nexport type ActionMiddleware<Ctx, Extra extends Record<string, unknown>> = (args: {\n ctx: Ctx\n next: <E extends Record<string, unknown> = Record<string, never>>(\n opts?: { ctx?: E },\n ) => Promise<MiddlewareResult<E>>\n}) => Promise<MiddlewareResult<Extra>>\n\ntype Output<S> = S extends StandardSchemaV1<unknown, infer O> ? O : never\n\n/** What a caller may pass, before the schema parses it. */\ntype InputOf<S> = S extends StandardSchemaV1<infer I, unknown> ? I : unknown\n\n/**\n * A built action, as its callers see it.\n *\n * Typed from the schema's input when there is one, so a call with the wrong\n * shape fails the typecheck rather than the validation - and FormData beside\n * it, which is how a form calls the same action. Without a schema, anything.\n */\nexport type Action<Raw, Data, Refusal = never> = unknown extends Raw\n ? (input?: unknown) => Promise<ActionResult<Data, Refusal>>\n : undefined extends Raw\n ? (input?: Raw | FormData) => Promise<ActionResult<Data, Refusal>>\n : (input: Raw | FormData) => Promise<ActionResult<Data, Refusal>>\n\nexport interface ActionBuilder<Ctx extends Record<string, unknown>, Input, Raw = unknown, Refusal = never> {\n /** Add a step, and whatever context it contributes. */\n use<Extra extends Record<string, unknown> = Record<string, never>>(\n middleware: (args: {\n ctx: Ctx\n next: <E extends Record<string, unknown> = Record<string, never>>(\n opts?: { ctx?: E },\n ) => Promise<MiddlewareResult<E>>\n }) => Promise<MiddlewareResult<Extra>>,\n ): ActionBuilder<Ctx & Extra, Input, Raw, Refusal>\n /** Parse and check what the caller sent. The handler's `input` follows. */\n input<S extends StandardSchemaV1>(schema: S): ActionBuilder<Ctx, Output<S>, InputOf<S>, Refusal>\n /**\n * The shape of what a refusal may carry - see `refuse()`. The page gets\n * `result.refusal` typed from it, and only data that matches it: data that\n * does not is a bug in the server, answered as one.\n */\n refusal<S extends StandardSchemaV1>(schema: S): ActionBuilder<Ctx, Input, Raw, Output<S>>\n /**\n * The body.\n *\n * What the caller gets is always the result object: `data`, or a\n * refusal, or - when the action redirected - `redirected`, set by the\n * client once the navigation is under way. Always an object, so a caller\n * reading `result.validationErrors` after a redirect reads undefined and\n * not a TypeError inside a transition, which unmounts the root.\n */\n handler<Data>(\n fn: (args: HandlerArgs<Input, Ctx, Refusal>) => Promise<Data> | Data,\n ): Action<Raw, Data, Refusal>\n /**\n * The body of a READ, sharing this client's middleware and schema.\n *\n * export const getPosts = client.input(filter).query(async ({ input, ctx }) =>\n * db.posts(ctx.user.id, input))\n *\n * The same builder as `handler`, and deliberately so: an app configures its\n * auth check and its error reporting once, and both a mutation and a read go\n * through them.\n *\n * It fails differently, though, and that is not an oversight. An action\n * RETURNS its failures because React serialises a rejection opaquely. A query\n * is handed to a cache library as a fetcher, and every one of them reports\n * failure by rejection — so this returns the data directly and throws, and\n * the endpoint carries the message across for it.\n */\n query<Data>(\n fn: (args: { input: Input; ctx: Ctx }) => Promise<Data> | Data,\n options?: QueryOptions,\n ): (input?: unknown) => Promise<Data>\n}\n\nexport interface ActionClientOptions {\n /**\n * What the browser is told when something unexpected throws.\n *\n * Everything reaching here is a bug or an outage, and its message may say\n * more than a stranger should see — a query, a path, a host. Returning a\n * fixed string is the safe default; return the message only for errors you\n * raised deliberately.\n */\n onError?: (error: unknown) => string\n}\n\nconst GENERIC = 'Something went wrong.'\n\n/**\n * Whether the backend turned this caller away: not signed in, not allowed, or\n * nothing there for them. Each carries a message written for the person.\n */\nfunction turnedAway(error: unknown): error is Error {\n return (\n error instanceof ServerAuthenticationError || error instanceof ServerAuthorizationError || isNotFoundSignal(error)\n )\n}\n\n/**\n * FormData in, a plain object out — what a schema expects to be handed.\n *\n * The form's own decoder, so the object validated here is the object the\n * browser validated. This had a flat decoder of its own: `items[0].name`\n * stayed a key spelled exactly that, `<Form>` had already parsed it into an\n * array, and a nested form passed in the browser and failed on the server\n * with the fields it named gone.\n */\nconst fromFormData = (body: FormData, schema: unknown): Record<string, unknown> => decodeFormData(body, schema)\n\nexport function createActionClient(\n options: ActionClientOptions = {},\n): ActionBuilder<Record<never, never>, undefined> {\n const report = options.onError ?? (() => GENERIC)\n\n function build<Ctx extends Record<string, unknown>, Input>(\n middlewares: ActionMiddleware<never, never>[],\n schema: StandardSchemaV1 | null,\n refusalSchema: StandardSchemaV1 | null = null,\n ): ActionBuilder<Ctx, Input> {\n /**\n * Validate, run the chain, call the body.\n *\n * Shared by both terminals, which is the point of putting a read on this\n * builder at all: one set of middleware, one schema, one place the auth\n * check lives. Refusals leave by throwing, and each terminal decides what\n * that should look like from the outside.\n */\n const pipeline = async (\n raw: unknown,\n fn: (args: HandlerArgs<never, never>) => unknown,\n ): Promise<unknown> => {\n const value = raw instanceof FormData ? fromFormData(raw, schema) : raw\n\n if (schema) {\n const invalid = await validateWith(schema, value)\n\n if (invalid) throw new ActionValidationError(invalid)\n }\n\n const parsed = schema\n ? ((await schema['~standard'].validate(value)).value as Input)\n : (value as Input)\n\n // Composed inside-out so the first `use` is the outermost — it sees the\n // others run, which is what makes timing and cleanup possible rather\n // than only checks.\n let ctx = {} as Ctx\n let index = 0\n\n const run = async (): Promise<unknown> => {\n const middleware = middlewares[index++]\n\n if (!middleware) {\n return await fn({\n input: parsed as never,\n ctx: ctx as never,\n // The same function as the export; the type on the way in is what\n // is different, and the type is the handler's input.\n fieldErrors: fieldErrors as never,\n refuse: refuse as never,\n })\n }\n\n let continued = false\n\n const result = await (middleware as unknown as ActionMiddleware<Ctx, Record<string, unknown>>)({\n ctx,\n next: (async (opts?: { ctx?: Record<string, unknown> }) => {\n continued = true\n ctx = { ...ctx, ...(opts?.ctx ?? {}) } as Ctx\n\n return { ctx, value: await run() }\n }) as never,\n })\n\n // Silence is not refusal. A middleware that neither called next() nor\n // threw has done nothing, and guessing which it meant turns a\n // forgotten `return` into a check that quietly passes.\n if (!continued) {\n throw new ActionMisuse(\n 'A middleware returned without calling next(). Call it to continue, or throw to refuse.',\n )\n }\n\n return (result as { value?: unknown })?.value\n }\n\n return await run()\n }\n\n /**\n * A refusal as the page gets it: its message, always - it was written to\n * be seen - and its data only once the declared schema has checked it.\n * Data with no schema to check it, or that fails the schema, never\n * reaches the browser: the first is said in the server's log, the second\n * is a bug in the server, returned as the error each terminal reports.\n */\n const refusalResult = async (error: ActionRefusal): Promise<ActionResult<never, unknown> | Error> => {\n if (error.data === undefined) return { serverError: error.message }\n\n if (!refusalSchema) {\n console.error(\n `[rsc-kit] An action refused with data, and declares no .refusal(schema) for it - the message was sent, the data was not: ${error.message}`,\n )\n\n return { serverError: error.message }\n }\n\n const checked = await refusalSchema['~standard'].validate(error.data)\n\n if (checked.issues) {\n return new Error(\n `An action refused with data its .refusal(schema) does not accept: ${checked.issues.map((issue) => issue.message).join('; ')}`,\n )\n }\n\n return { serverError: error.message, refusal: checked.value }\n }\n\n return {\n use(middleware) {\n return build([...middlewares, middleware as never], schema, refusalSchema) as never\n },\n input(next) {\n return build(middlewares, next, refusalSchema) as never\n },\n refusal(next) {\n return build(middlewares, schema, next) as never\n },\n handler(fn) {\n return markClientBuilt(async (raw?: unknown) => {\n try {\n return { data: (await pipeline(raw, fn)) as Awaited<ReturnType<typeof fn>> }\n } catch (error) {\n // Past onError deliberately — see ActionMisuse.\n if (error instanceof ActionMisuse) throw error\n\n // A redirect is an instruction, not a failure: it has to reach\n // the host, which answers the action with the destination. Caught\n // here it became { serverError: 'Something went wrong.' } - a\n // login that succeeded and then showed an error.\n if (isRedirectSignal(error)) throw error\n\n if (isActionValidationError(error)) {\n return { validationErrors: error.errors }\n }\n\n if (isActionRefusal(error)) {\n const refused = await refusalResult(error)\n\n return (refused instanceof Error ? { serverError: report(refused) } : refused) as ActionResult<never>\n }\n\n // Turned away by the backend - not signed in, not allowed, no such\n // record - is an answer too, and its message is meant to be seen.\n // Not rethrown as a redirect is: the action endpoint answers a\n // throw with a 500, and the form would show nothing at all.\n if (turnedAway(error)) return { serverError: error.message }\n\n return { serverError: report(error) }\n }\n })\n },\n query(fn, options) {\n const read = async (raw?: unknown) => {\n try {\n return await pipeline(raw, fn)\n } catch (error) {\n if (error instanceof ActionMisuse) throw error\n if (isRedirectSignal(error)) throw error\n\n // Left as they are, as a redirect is. A page that reads through a\n // query answers 401, 403 or its not-found page, as it does calling\n // the backend directly; the read endpoint answers the same statuses.\n if (turnedAway(error)) throw error\n\n // Thrown, not returned. A cache library reports failure by\n // rejection, so a query that answered with an error-shaped object\n // would look like a successful read of something odd.\n if (isActionValidationError(error)) {\n throw new QueryValidationError(error.errors)\n }\n\n // Its own message, as an action's is, and its checked data on\n // the error for a fetcher that wants it.\n if (isActionRefusal(error)) {\n const refused = await refusalResult(error)\n\n if (refused instanceof Error) throw new Error(report(refused))\n\n throw Object.assign(new Error(refused.serverError), {\n refusal: refused.refusal,\n refusalStatus: error.refusalStatus,\n })\n }\n\n throw new Error(report(error))\n }\n }\n\n return markClientBuilt(markQuery(read, options)) as (input?: unknown) => Promise<never>\n },\n }\n }\n\n return build([], null)\n}\n"]}
|
package/dist/conformance.js
CHANGED
|
@@ -159,6 +159,9 @@ export async function conformance(call, options) {
|
|
|
159
159
|
});
|
|
160
160
|
await check('a refusal keeps its status and its message', async () => {
|
|
161
161
|
const error = (await rejection(() => call('Conformance.refuse')));
|
|
162
|
+
// A refusal, not a failure: an action shows its message rather than
|
|
163
|
+
// onError's, data or no data.
|
|
164
|
+
expect(isActionRefusal(error), 'raised as ' + String(error) + ', not as a refusal - is refusalStatus in the reply?');
|
|
162
165
|
expect(error.refusalStatus === 429, 'status ' + String(error.refusalStatus));
|
|
163
166
|
expect(String(error.message).includes('Slow down.'), 'message ' + JSON.stringify(error.message));
|
|
164
167
|
});
|
package/dist/conformance.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conformance.js","sourceRoot":"","sources":["../src/conformance.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n// The contract every backend adapter keeps, as a suite it runs against itself.\n//\n// A backend answers rpc(), actions and guards over one endpoint, and every\n// difference between how it and the engine read that wire is a bug in an\n// app that nobody wrote: a nil slice arriving as null where the type said a\n// list, a timestamp the type called unknown, a refusal that did not come out\n// as the error a page checks for. Each was found by an app, one at a time.\n// This finds them before an adapter ships.\n//\n// The adapter registers the Conformance.* functions described in CASES, in\n// its own language, the way an app would write them; this calls them through\n// the real client and checks what arrives. Where the adapter's manifest types\n// a function, every value it sends is checked against that type too.\n//\n// rsc-kit-conformance --endpoint http://127.0.0.1:8080/__rsc/host-call \\\n// --secret test-secret --manifest rsc-host.json\n//\n// The test host's hostReply passes the same suite (conformance.test.ts), so\n// a page test faking the backend fakes what a real adapter does.\n\nimport { readFileSync } from 'node:fs'\nimport { argv, exit, stderr, stdout } from 'node:process'\nimport { pathToFileURL } from 'node:url'\nimport { httpHostCalls } from './hostCalls.js'\nimport { isNotFoundSignal } from './notFound.js'\nimport { isActionRefusal } from './action.js'\nimport { withRedirect } from './redirect.js'\nimport { withRequest, withResponseDraft } from './request.js'\nimport { ServerAuthenticationError, ServerAuthorizationError } from './js/errors.js'\n\ntype Schema = Record<string, unknown>\n\n/** A host-call client: the real one in a run, the test host's in core's own test. */\nexport type ConformanceCall = (name: string, ...args: unknown[]) => Promise<unknown>\n\nexport interface ConformanceOptions {\n /** The adapter's host-call endpoint, e.g. http://127.0.0.1:8080/__rsc/host-call. */\n endpoint: string\n /** The secret the adapter checks. */\n secret: string\n /** The adapter's rsc-host.json, parsed or as a path: its types are checked against what arrives. */\n manifest?:\n | string\n | { actions?: unknown; functions?: string[]; types?: Record<string, { result?: Schema }>; defs?: Record<string, Schema> }\n /** For a test: the fetch the client uses. */\n fetch?: typeof fetch\n}\n\nexport interface ConformanceResult {\n case: string\n ok: boolean\n /** What went wrong, when it did. */\n detail?: string\n}\n\n/**\n * What the adapter registers, and what each must do. Names are fixed; how\n * they are written is the adapter's - the point is that they are written the\n * way an app's would be, with the adapter's ordinary API.\n */\nexport const CASES = {\n 'Conformance.echo': 'Return its one argument unchanged: any JSON value, nested.',\n 'Conformance.emptyList': 'Return an empty list of objects, the way the language makes \"no rows\" (Go: a nil slice).',\n 'Conformance.time': \"Return the instant 2026-01-02T03:04:05Z as the language's own time value.\",\n 'Conformance.noTime': \"Return an absent time: a nil pointer, a null Carbon, typed as a time or nothing.\",\n 'Conformance.unauthenticated': 'Refuse as not signed in, the way the framework does.',\n 'Conformance.unauthorized': 'Refuse as signed in but not allowed.',\n 'Conformance.notFound': \"Refuse as not found (404), the way the framework does: Go's Refuse(404), Laravel's abort(404).\",\n 'Conformance.refuse': 'Refuse with status 429 and the message \"Slow down.\"',\n 'Conformance.refuseWithData':\n 'Refuse with status 409, the message \"Still in use\", and the data { blockers: [{ id: 7, href: \"/orders/7\" }] } - ' +\n \"the adapter's own refuse, carrying data for the page to act on.\",\n 'Conformance.invalid': 'Refuse the input: a validation error on the field \"name\".',\n 'Conformance.redirect': 'Send the visitor to /login.',\n 'Conformance.revalidate': 'Mark the region \"orders\" stale, and return \"ok\".',\n 'Conformance.fail': 'Fail unexpectedly: an ordinary error, not a refusal.',\n 'Conformance.authorization': \"Return the request's Authorization header, as the renderer forwarded it.\",\n 'Conformance.cookie': \"Return the request's Cookie header, as the renderer forwarded it.\",\n 'Conformance.login': 'Set a cookie named \"conformance_login\" on the response, the way a login sets its session cookie, and return \"ok\".',\n 'Conformance.double': 'Take one integer and return it doubled. Arguments that do not fit - a string, none - fail it: a 500, not a refusal.',\n 'Conformance.invalidNested': 'Refuse the input with errors on the nested field \"address.city\" and on the form itself, under \"\".',\n '__rsc.middleware':\n 'Guards, run in the order named, stopping at the first that does not pass - none at all passes: \"conformance-allow\" passes; ' +\n '\"conformance-deny\" refuses; \"conformance-redirect\" sends the visitor to /conformance-login; a name with no guard refuses.',\n 'Conformance.change': 'Say the name \"conformance:changed\" changed, the way the adapter does from a webhook, and return \"ok\".',\n '__rsc.changed':\n 'Given { since: { name: version }, wait }: answer { versions } with every name whose version differs from since now, ' +\n 'and no other. A name never changed is at 0. A change moves a version to the larger of one past it and the time in ' +\n 'ms - never + 1 alone. May hold the call up to wait ms for one to differ; may answer at once.',\n} as const\n\nconst INSTANT = Date.parse('2026-01-02T03:04:05Z')\n\n/** Two JSON values alike, whatever order an object's keys were written in. */\nfunction sameValue(a: unknown, b: unknown): boolean {\n if (Array.isArray(a) || Array.isArray(b)) {\n return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((item, i) => sameValue(item, b[i]))\n }\n\n if (typeof a === 'object' && a !== null && typeof b === 'object' && b !== null) {\n const keys = Object.keys(a)\n\n return (\n keys.length === Object.keys(b).length &&\n keys.every((key) => sameValue((a as Record<string, unknown>)[key], (b as Record<string, unknown>)[key]))\n )\n }\n\n return a === b\n}\n\nconst ECHOES: unknown[] = [null, 0, -1.5, 'héllo ✓ \"quoted\"', [1, 'a', null], { a: { b: [true, false] }, c: '' }]\n\n/**\n * Run the suite against a client. Every case runs; none stops another.\n *\n * `revalidated` is where the client records what each call marked stale -\n * its onRevalidate - so the revalidation case can read it.\n */\nexport async function conformance(\n call: ConformanceCall,\n options: {\n revalidated: string[][]\n manifest?: ConformanceOptions['manifest']\n wrongSecret?: ConformanceCall\n /**\n * A POST straight to the endpoint, for what the client never sends:\n * malformed bodies, an oversized batch, no secret at all. `secret: false`\n * leaves the header off.\n */\n raw?: (body: string, options?: { secret?: boolean }) => Promise<Response>\n },\n): Promise<ConformanceResult[]> {\n const { revalidated, manifest, wrongSecret, raw } = options\n const results: ConformanceResult[] = []\n const types = typeof manifest === 'string' ? JSON.parse(readFileSync(manifest, 'utf-8')) : manifest\n\n const check = async (name: string, run: () => Promise<void>) => {\n try {\n await run()\n results.push({ case: name, ok: true })\n } catch (error) {\n results.push({ case: name, ok: false, detail: error instanceof Error ? error.message : String(error) })\n }\n }\n\n const expect = (ok: boolean, detail: string) => {\n if (!ok) throw new Error(detail)\n }\n\n const rejection = async (run: () => Promise<unknown>): Promise<unknown> => {\n try {\n const value = await run()\n\n throw new Error('answered ' + JSON.stringify(value) + ' instead of refusing')\n } catch (error) {\n return error\n }\n }\n\n /** The value against the type the adapter's manifest declares, when it declares one. */\n const typed = (name: string, value: unknown) => {\n const schema = types?.types?.[name]?.result\n\n if (!schema) return\n\n const problem = conformsTo(value, schema, types?.defs ?? {}, 'result')\n\n expect(problem === null, `the manifest types ${name}'s result, and what arrived does not fit it: ${problem}`)\n }\n\n await check('the manifest lists every Conformance function', async () => {\n if (!types) return\n\n const missing = Object.keys(CASES).filter((n) => !n.startsWith('__') && !types.functions?.includes(n))\n\n expect(missing.length === 0, 'not in functions: ' + missing.join(', '))\n })\n\n await check('the manifest\\'s actions is an object, even with none', async () => {\n if (!types) return\n\n expect(\n typeof types.actions === 'object' && types.actions !== null && !Array.isArray(types.actions),\n 'actions is ' + JSON.stringify(types.actions),\n )\n })\n\n await check('a value of any JSON shape comes back unchanged', async () => {\n for (const value of ECHOES) {\n const back = await call('Conformance.echo', value)\n\n expect(JSON.stringify(back) === JSON.stringify(value), `sent ${JSON.stringify(value)}, got ${JSON.stringify(back)}`)\n }\n })\n\n await check('\"no rows\" is an empty list, never null', async () => {\n const value = await call('Conformance.emptyList')\n\n expect(Array.isArray(value) && value.length === 0, 'got ' + JSON.stringify(value))\n typed('Conformance.emptyList', value)\n })\n\n await check('a time is an ISO 8601 string of the same instant', async () => {\n const value = await call('Conformance.time')\n\n expect(typeof value === 'string' && Date.parse(value) === INSTANT, 'got ' + JSON.stringify(value))\n typed('Conformance.time', value)\n })\n\n await check('an absent time is null', async () => {\n const value = await call('Conformance.noTime')\n\n expect(value === null, 'got ' + JSON.stringify(value))\n typed('Conformance.noTime', value)\n })\n\n await check('not signed in is the engine\\'s ServerAuthenticationError', async () => {\n const error = await rejection(() => call('Conformance.unauthenticated'))\n\n expect(error instanceof ServerAuthenticationError, 'got ' + String(error))\n })\n\n await check('not allowed is the engine\\'s ServerAuthorizationError', async () => {\n const error = await rejection(() => call('Conformance.unauthorized'))\n\n expect(error instanceof ServerAuthorizationError, 'got ' + String(error))\n })\n\n await check('not found is the engine\\'s notFound()', async () => {\n const error = await rejection(() => call('Conformance.notFound'))\n\n expect(isNotFoundSignal(error), 'got ' + String(error))\n })\n\n await check('a refusal keeps its status and its message', async () => {\n const error = (await rejection(() => call('Conformance.refuse'))) as Error & { refusalStatus?: number }\n\n expect(error.refusalStatus === 429, 'status ' + String(error.refusalStatus))\n expect(String(error.message).includes('Slow down.'), 'message ' + JSON.stringify(error.message))\n })\n\n await check('a refusal carries its data, its message and its status', async () => {\n const error = (await rejection(() => call('Conformance.refuseWithData'))) as Error & {\n refusalStatus?: number\n data?: unknown\n }\n\n expect(isActionRefusal(error), 'raised as ' + String(error) + ', not as a refusal - is refusalData in the reply?')\n expect(error.message === 'Still in use', 'message ' + JSON.stringify(error.message))\n expect(error.refusalStatus === 409, 'status ' + String(error.refusalStatus))\n // Compared as values, not as text: an object's keys have no order, and\n // Go writes a map's sorted.\n expect(\n sameValue(error.data, { blockers: [{ id: 7, href: '/orders/7' }] }),\n 'data ' + JSON.stringify(error.data),\n )\n })\n\n await check('refused input names its field', async () => {\n const error = (await rejection(() => call('Conformance.invalid'))) as { errors?: Record<string, string[]> }\n\n expect(Array.isArray(error.errors?.name) && error.errors.name.length > 0, 'errors ' + JSON.stringify(error.errors))\n })\n\n await check('a redirect is the engine\\'s redirect, to where it said', async () => {\n const taken = await withRedirect(async (seen) => {\n await rejection(() => call('Conformance.redirect'))\n\n return seen()\n })\n\n expect(taken?.location === '/login', 'redirect ' + JSON.stringify(taken))\n expect(taken!.status >= 300 && taken!.status < 400, 'status ' + taken?.status)\n })\n\n await check('in a batch, a revalidation stays with its own call', async () => {\n const before = revalidated.length\n\n await Promise.all([call('Conformance.revalidate'), call('Conformance.echo', 1), call('Conformance.echo', 2)])\n\n expect(revalidated.length - before === 1, 'revalidated ' + JSON.stringify(revalidated.slice(before)))\n })\n\n await check('a revalidation rides with the result', async () => {\n const value = await call('Conformance.revalidate')\n\n expect(value === 'ok', 'got ' + JSON.stringify(value))\n expect(revalidated.some((r) => r.includes('orders')), 'revalidated ' + JSON.stringify(revalidated))\n })\n\n await check('an unexpected failure is an error, not a refusal', async () => {\n const error = (await rejection(() => call('Conformance.fail'))) as Error & { refusalStatus?: number }\n\n expect(\n error instanceof Error && !(error instanceof ServerAuthenticationError) && !(error instanceof ServerAuthorizationError) && !error.refusalStatus && !isNotFoundSignal(error),\n 'got ' + String(error),\n )\n })\n\n await check('the visitor\\'s Authorization header is forwarded', async () => {\n const value = await withRequest(new Request('https://app.test/', { headers: { authorization: 'Bearer conformance' } }), () =>\n call('Conformance.authorization'),\n )\n\n expect(value === 'Bearer conformance', 'got ' + JSON.stringify(value))\n })\n\n await check('the visitor\\'s Cookie header is forwarded', async () => {\n const value = await withRequest(new Request('https://app.test/', { headers: { cookie: 'conformance=1; other=2' } }), () =>\n call('Conformance.cookie'),\n )\n\n expect(typeof value === 'string' && value.includes('conformance=1') && value.includes('other=2'), 'got ' + JSON.stringify(value))\n })\n\n await check('a cookie set during a call - a login - reaches the page\\'s response', async () => {\n const cookies = await withRequest(new Request('https://app.test/'), () =>\n withResponseDraft(async ({ taken }) => {\n const value = await call('Conformance.login')\n\n expect(value === 'ok', 'got ' + JSON.stringify(value))\n\n return taken().getSetCookie()\n }),\n )\n\n expect(cookies.some((c) => c.startsWith('conformance_login=')), 'Set-Cookie ' + JSON.stringify(cookies))\n })\n\n await check('arguments are decoded to their types', async () => {\n const value = await call('Conformance.double', 21)\n\n expect(value === 42, 'got ' + JSON.stringify(value))\n })\n\n await check('arguments that do not fit fail the call, not refuse it', async () => {\n for (const args of [['twenty-one'], []]) {\n const error: unknown = await rejection(() => call('Conformance.double', ...args))\n const fields = error as { refusalStatus?: number; errors?: unknown }\n\n expect(\n error instanceof Error && !(error instanceof ServerAuthenticationError) && !(error instanceof ServerAuthorizationError) &&\n !fields.refusalStatus && fields.errors === undefined && !isNotFoundSignal(error),\n `with ${JSON.stringify(args)}: got ` + String(error),\n )\n }\n })\n\n await check('refused input names nested fields with dots, and the form under \"\"', async () => {\n const error = (await rejection(() => call('Conformance.invalidNested'))) as { errors?: Record<string, string[]> }\n\n expect(Array.isArray(error.errors?.['address.city']) && error.errors['address.city'].length > 0, 'errors ' + JSON.stringify(error.errors))\n expect(Array.isArray(error.errors?.['']) && error.errors[''].length > 0, 'errors ' + JSON.stringify(error.errors))\n })\n\n await check('calls in one batch are each answered, a refusal only its own', async () => {\n const [a, b, c] = await Promise.allSettled([\n call('Conformance.echo', 1),\n call('Conformance.unauthenticated'),\n call('Conformance.echo', 2),\n ])\n\n expect(a.status === 'fulfilled' && a.value === 1, 'first ' + JSON.stringify(a))\n expect(b.status === 'rejected' && b.reason instanceof ServerAuthenticationError, 'second ' + String((b as PromiseRejectedResult).reason))\n expect(c.status === 'fulfilled' && c.value === 2, 'third ' + JSON.stringify(c))\n })\n\n await check('no guards at all passes: what a health check asks', async () => {\n // The renderer's /_rsc/health asks with an empty list: it runs no app\n // code, and still proves the address, the secret and the adapter.\n const value = await call('__rsc.middleware', [])\n\n expect(value === true, 'got ' + JSON.stringify(value))\n })\n\n await check('a guard that passes answers true', async () => {\n const value = await call('__rsc.middleware', ['conformance-allow'])\n\n expect(value === true, 'got ' + JSON.stringify(value))\n })\n\n await check('a guard that refuses refuses', async () => {\n const value = await call('__rsc.middleware', ['conformance-deny']).catch((e: unknown) => e)\n\n expect(value !== true, 'it answered true')\n })\n\n await check('a guard can send the visitor somewhere else', async () => {\n const taken = await withRedirect(async (seen) => {\n await call('__rsc.middleware', ['conformance-redirect']).catch(() => {})\n\n return seen()\n })\n\n expect(taken?.location === '/conformance-login', 'redirect ' + JSON.stringify(taken))\n })\n\n await check('guards run in order and stop at the first that does not pass', async () => {\n const after = await call('__rsc.middleware', ['conformance-allow', 'conformance-deny']).catch((e: unknown) => e)\n\n expect(after !== true, 'allow then deny answered true')\n\n // Deny first: the redirect after it must never be asked.\n const taken = await withRedirect(async (seen) => {\n const value = await call('__rsc.middleware', ['conformance-deny', 'conformance-redirect']).catch((e: unknown) => e)\n\n expect(value !== true, 'deny then redirect answered true')\n\n return seen()\n })\n\n expect(taken === null, 'the guard after a refusal ran: redirected to ' + JSON.stringify(taken))\n })\n\n await check('a guard nobody registered refuses: fail closed', async () => {\n const value = await call('__rsc.middleware', ['conformance-nobody-registered-this']).catch((e: unknown) => e)\n\n expect(value !== true, 'it answered true')\n })\n\n const versionsOf = async (query: { since: Record<string, number>; wait?: number }) => {\n const answer = (await call('__rsc.changed', query)) as { versions?: Record<string, number> } | null\n\n expect(typeof answer?.versions === 'object' && answer.versions !== null, 'got ' + JSON.stringify(answer))\n\n return answer!.versions!\n }\n\n await check('a name nobody changed is at version 0, and unchanged from 0', async () => {\n const all = await versionsOf({ since: { 'conformance:never': -1 } })\n\n expect(all['conformance:never'] === 0, 'from -1: ' + JSON.stringify(all))\n\n const none = await versionsOf({ since: { 'conformance:never': 0 } })\n\n expect(Object.keys(none).length === 0, 'from 0: ' + JSON.stringify(none))\n })\n\n await check('saying a name changed moves its version', async () => {\n const before = (await versionsOf({ since: { 'conformance:changed': -1 } }))['conformance:changed'] ?? 0\n const value = await call('Conformance.change')\n\n expect(value === 'ok', 'got ' + JSON.stringify(value))\n\n const moved = await versionsOf({ since: { 'conformance:changed': before } })\n\n expect(typeof moved['conformance:changed'] === 'number' && moved['conformance:changed'] !== before, 'from ' + before + ': ' + JSON.stringify(moved))\n })\n\n await check('a version is the time of the change, and never comes round again', async () => {\n // The larger of one past the old version and the time in ms: a counter\n // repeats once a pruned name starts again from 0, and a tab holding the\n // old value misses the next change. A minute's leeway for clock skew.\n const started = Date.now()\n\n await call('Conformance.change')\n\n const first = (await versionsOf({ since: { 'conformance:changed': -1 } }))['conformance:changed'] ?? 0\n\n expect(first >= started - 60_000, `a change at ${started} moved the version to ${first}: not a time in ms`)\n\n await call('Conformance.change')\n\n const second = (await versionsOf({ since: { 'conformance:changed': -1 } }))['conformance:changed'] ?? 0\n\n expect(second > first, `a second change moved ${first} to ${second}`)\n })\n\n await check('only the names that differ are answered', async () => {\n const current = (await versionsOf({ since: { 'conformance:changed': -1 } }))['conformance:changed'] ?? 0\n const answer = await versionsOf({ since: { 'conformance:changed': current, 'conformance:never': 5 } })\n\n expect(JSON.stringify(answer) === JSON.stringify({ 'conformance:never': 0 }), 'got ' + JSON.stringify(answer))\n })\n\n await check('waiting for a name to change is bounded by wait', async () => {\n const started = Date.now()\n const none = await versionsOf({ since: { 'conformance:never': 0 }, wait: 300 })\n const took = Date.now() - started\n\n expect(Object.keys(none).length === 0, 'got ' + JSON.stringify(none))\n expect(took < 3_000, 'took ' + took + 'ms')\n })\n\n if (raw) {\n const statusOf = async (body: string, secret = true) => (await raw(body, { secret })).status\n\n await check('a call with no secret at all is refused, 403', async () => {\n const status = await statusOf(JSON.stringify({ function: 'Conformance.echo', args: [1] }), false)\n\n expect(status === 403, 'answered ' + status)\n })\n\n await check('a function nobody registered is a 404', async () => {\n const status = await statusOf(JSON.stringify({ function: 'Conformance.nobodyRegisteredThis', args: [] }))\n\n expect(status === 404, 'answered ' + status)\n })\n\n await check('a malformed call is a 400: not JSON, no function, args not a list', async () => {\n for (const body of ['not json', JSON.stringify({ args: [] }), JSON.stringify({ function: 'Conformance.echo', args: 'x' })]) {\n const status = await statusOf(body)\n\n expect(status === 400, `${body} answered ${status}`)\n }\n })\n\n await check('a batch of more than 50 is refused, 413, before any call runs', async () => {\n const before = (await versionsOf({ since: { 'conformance:changed': -1 } }))['conformance:changed'] ?? 0\n const calls = Array.from({ length: 51 }, () => ({ function: 'Conformance.change', args: [] }))\n const status = await statusOf(JSON.stringify({ calls }))\n const after = (await versionsOf({ since: { 'conformance:changed': -1 } }))['conformance:changed'] ?? 0\n\n expect(status === 413, 'answered ' + status)\n expect(after === before, 'calls ran: conformance:changed moved from ' + before + ' to ' + after)\n })\n }\n\n if (wrongSecret) {\n await check('a call with the wrong secret is refused', async () => {\n const value = await wrongSecret('Conformance.echo', 'should not run').catch((e: unknown) => e)\n\n expect(value !== 'should not run', 'it ran')\n })\n }\n\n return results\n}\n\n/** Run the suite against an adapter's endpoint. */\nexport async function runConformance(options: ConformanceOptions): Promise<ConformanceResult[]> {\n const revalidated: string[][] = []\n const client = (secret: string) =>\n httpHostCalls({\n endpoint: options.endpoint,\n secret,\n fetch: options.fetch,\n onRevalidate: (targets) => revalidated.push(targets),\n })\n\n const doFetch = options.fetch ?? globalThis.fetch\n\n return await conformance(client(options.secret), {\n revalidated,\n manifest: options.manifest,\n wrongSecret: client(options.secret + '-wrong'),\n raw: (body, { secret = true } = {}) =>\n doFetch(options.endpoint, {\n method: 'POST',\n headers: { 'content-type': 'application/json', ...(secret ? { 'x-rsc-host-secret': options.secret } : {}) },\n body,\n }),\n })\n}\n\n/**\n * Whether a value fits the JSON Schema subset the manifest uses. Null when it\n * does; otherwise where and why it does not.\n */\nexport function conformsTo(value: unknown, schema: Schema, defs: Record<string, Schema>, at: string): string | null {\n if (!schema || Object.keys(schema).length === 0) return null\n\n const ref = schema.$ref\n\n if (typeof ref === 'string' && ref.startsWith('#/defs/')) {\n const target = defs[ref.slice(7)]\n\n return target ? conformsTo(value, target, defs, at) : `${at}: ${ref} is not in defs`\n }\n\n if (Array.isArray(schema.anyOf)) {\n const fits = (schema.anyOf as Schema[]).some((s) => conformsTo(value, s, defs, at) === null)\n\n return fits ? null : `${at}: ${JSON.stringify(value)} is none of ${JSON.stringify(schema.anyOf)}`\n }\n\n if (Array.isArray(schema.enum)) {\n return (schema.enum as unknown[]).includes(value) ? null : `${at}: ${JSON.stringify(value)} is not one of ${JSON.stringify(schema.enum)}`\n }\n\n const kind = Array.isArray(value) ? 'array' : value === null ? 'null' : typeof value\n\n switch (schema.type) {\n case 'string':\n if (kind !== 'string') return `${at}: expected a string, got ${JSON.stringify(value)}`\n if (schema.format === 'date-time' && Number.isNaN(Date.parse(value as string))) return `${at}: ${JSON.stringify(value)} is not a date-time`\n return null\n case 'integer':\n return Number.isInteger(value) ? null : `${at}: expected an integer, got ${JSON.stringify(value)}`\n case 'number':\n return kind === 'number' ? null : `${at}: expected a number, got ${JSON.stringify(value)}`\n case 'boolean':\n return kind === 'boolean' ? null : `${at}: expected a boolean, got ${JSON.stringify(value)}`\n case 'null':\n return value === null ? null : `${at}: expected null, got ${JSON.stringify(value)}`\n case 'array': {\n if (kind !== 'array') return `${at}: expected an array, got ${JSON.stringify(value)}`\n for (const [i, item] of (value as unknown[]).entries()) {\n const problem = conformsTo(item, schema.items as Schema, defs, `${at}[${i}]`)\n if (problem) return problem\n }\n return null\n }\n case 'object': {\n if (kind !== 'object') return `${at}: expected an object, got ${JSON.stringify(value)}`\n const object = value as Record<string, unknown>\n const properties = (schema.properties ?? {}) as Record<string, Schema>\n for (const name of (schema.required as string[] | undefined) ?? []) {\n if (!(name in object)) return `${at}.${name}: required, and missing`\n }\n for (const [name, s] of Object.entries(properties)) {\n if (name in object) {\n const problem = conformsTo(object[name], s, defs, `${at}.${name}`)\n if (problem) return problem\n }\n }\n const extra = schema.additionalProperties as Schema | undefined\n if (extra && !schema.properties) {\n for (const [name, item] of Object.entries(object)) {\n const problem = conformsTo(item, extra, defs, `${at}.${name}`)\n if (problem) return problem\n }\n }\n return null\n }\n default:\n return null\n }\n}\n\n/** Print a result table, and say whether the adapter conforms. */\nexport function report(results: ConformanceResult[]): boolean {\n for (const r of results) {\n stdout.write(` ${r.ok ? '✓' : '✗'} ${r.case}${r.ok ? '' : '\\n ' + r.detail}\\n`)\n }\n\n const failed = results.filter((r) => !r.ok).length\n\n stdout.write(failed === 0 ? `\\n conforms: ${results.length} cases\\n` : `\\n ${failed} of ${results.length} cases failed\\n`)\n\n return failed === 0\n}\n\n// Run as a command, not when imported.\nif (import.meta.url === pathToFileURL(argv[1] ?? '').href || argv[1]?.endsWith('rsc-kit-conformance')) {\n const flag = (name: string) => {\n const at = argv.indexOf('--' + name)\n\n return at === -1 ? undefined : argv[at + 1]\n }\n\n const endpoint = flag('endpoint')\n const secret = flag('secret')\n\n if (!endpoint || !secret) {\n stderr.write('usage: rsc-kit-conformance --endpoint <url> --secret <secret> [--manifest rsc-host.json]\\n')\n exit(2)\n }\n\n runConformance({ endpoint, secret, manifest: flag('manifest') })\n .then((results) => exit(report(results) ? 0 : 1))\n .catch((error: unknown) => {\n stderr.write('rsc-kit-conformance: ' + (error instanceof Error ? error.message : String(error)) + '\\n')\n exit(1)\n })\n}\n"]}
|
|
1
|
+
{"version":3,"file":"conformance.js","sourceRoot":"","sources":["../src/conformance.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n// The contract every backend adapter keeps, as a suite it runs against itself.\n//\n// A backend answers rpc(), actions and guards over one endpoint, and every\n// difference between how it and the engine read that wire is a bug in an\n// app that nobody wrote: a nil slice arriving as null where the type said a\n// list, a timestamp the type called unknown, a refusal that did not come out\n// as the error a page checks for. Each was found by an app, one at a time.\n// This finds them before an adapter ships.\n//\n// The adapter registers the Conformance.* functions described in CASES, in\n// its own language, the way an app would write them; this calls them through\n// the real client and checks what arrives. Where the adapter's manifest types\n// a function, every value it sends is checked against that type too.\n//\n// rsc-kit-conformance --endpoint http://127.0.0.1:8080/__rsc/host-call \\\n// --secret test-secret --manifest rsc-host.json\n//\n// The test host's hostReply passes the same suite (conformance.test.ts), so\n// a page test faking the backend fakes what a real adapter does.\n\nimport { readFileSync } from 'node:fs'\nimport { argv, exit, stderr, stdout } from 'node:process'\nimport { pathToFileURL } from 'node:url'\nimport { httpHostCalls } from './hostCalls.js'\nimport { isNotFoundSignal } from './notFound.js'\nimport { isActionRefusal } from './action.js'\nimport { withRedirect } from './redirect.js'\nimport { withRequest, withResponseDraft } from './request.js'\nimport { ServerAuthenticationError, ServerAuthorizationError } from './js/errors.js'\n\ntype Schema = Record<string, unknown>\n\n/** A host-call client: the real one in a run, the test host's in core's own test. */\nexport type ConformanceCall = (name: string, ...args: unknown[]) => Promise<unknown>\n\nexport interface ConformanceOptions {\n /** The adapter's host-call endpoint, e.g. http://127.0.0.1:8080/__rsc/host-call. */\n endpoint: string\n /** The secret the adapter checks. */\n secret: string\n /** The adapter's rsc-host.json, parsed or as a path: its types are checked against what arrives. */\n manifest?:\n | string\n | { actions?: unknown; functions?: string[]; types?: Record<string, { result?: Schema }>; defs?: Record<string, Schema> }\n /** For a test: the fetch the client uses. */\n fetch?: typeof fetch\n}\n\nexport interface ConformanceResult {\n case: string\n ok: boolean\n /** What went wrong, when it did. */\n detail?: string\n}\n\n/**\n * What the adapter registers, and what each must do. Names are fixed; how\n * they are written is the adapter's - the point is that they are written the\n * way an app's would be, with the adapter's ordinary API.\n */\nexport const CASES = {\n 'Conformance.echo': 'Return its one argument unchanged: any JSON value, nested.',\n 'Conformance.emptyList': 'Return an empty list of objects, the way the language makes \"no rows\" (Go: a nil slice).',\n 'Conformance.time': \"Return the instant 2026-01-02T03:04:05Z as the language's own time value.\",\n 'Conformance.noTime': \"Return an absent time: a nil pointer, a null Carbon, typed as a time or nothing.\",\n 'Conformance.unauthenticated': 'Refuse as not signed in, the way the framework does.',\n 'Conformance.unauthorized': 'Refuse as signed in but not allowed.',\n 'Conformance.notFound': \"Refuse as not found (404), the way the framework does: Go's Refuse(404), Laravel's abort(404).\",\n 'Conformance.refuse': 'Refuse with status 429 and the message \"Slow down.\"',\n 'Conformance.refuseWithData':\n 'Refuse with status 409, the message \"Still in use\", and the data { blockers: [{ id: 7, href: \"/orders/7\" }] } - ' +\n \"the adapter's own refuse, carrying data for the page to act on.\",\n 'Conformance.invalid': 'Refuse the input: a validation error on the field \"name\".',\n 'Conformance.redirect': 'Send the visitor to /login.',\n 'Conformance.revalidate': 'Mark the region \"orders\" stale, and return \"ok\".',\n 'Conformance.fail': 'Fail unexpectedly: an ordinary error, not a refusal.',\n 'Conformance.authorization': \"Return the request's Authorization header, as the renderer forwarded it.\",\n 'Conformance.cookie': \"Return the request's Cookie header, as the renderer forwarded it.\",\n 'Conformance.login': 'Set a cookie named \"conformance_login\" on the response, the way a login sets its session cookie, and return \"ok\".',\n 'Conformance.double': 'Take one integer and return it doubled. Arguments that do not fit - a string, none - fail it: a 500, not a refusal.',\n 'Conformance.invalidNested': 'Refuse the input with errors on the nested field \"address.city\" and on the form itself, under \"\".',\n '__rsc.middleware':\n 'Guards, run in the order named, stopping at the first that does not pass - none at all passes: \"conformance-allow\" passes; ' +\n '\"conformance-deny\" refuses; \"conformance-redirect\" sends the visitor to /conformance-login; a name with no guard refuses.',\n 'Conformance.change': 'Say the name \"conformance:changed\" changed, the way the adapter does from a webhook, and return \"ok\".',\n '__rsc.changed':\n 'Given { since: { name: version }, wait }: answer { versions } with every name whose version differs from since now, ' +\n 'and no other. A name never changed is at 0. A change moves a version to the larger of one past it and the time in ' +\n 'ms - never + 1 alone. May hold the call up to wait ms for one to differ; may answer at once.',\n} as const\n\nconst INSTANT = Date.parse('2026-01-02T03:04:05Z')\n\n/** Two JSON values alike, whatever order an object's keys were written in. */\nfunction sameValue(a: unknown, b: unknown): boolean {\n if (Array.isArray(a) || Array.isArray(b)) {\n return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((item, i) => sameValue(item, b[i]))\n }\n\n if (typeof a === 'object' && a !== null && typeof b === 'object' && b !== null) {\n const keys = Object.keys(a)\n\n return (\n keys.length === Object.keys(b).length &&\n keys.every((key) => sameValue((a as Record<string, unknown>)[key], (b as Record<string, unknown>)[key]))\n )\n }\n\n return a === b\n}\n\nconst ECHOES: unknown[] = [null, 0, -1.5, 'héllo ✓ \"quoted\"', [1, 'a', null], { a: { b: [true, false] }, c: '' }]\n\n/**\n * Run the suite against a client. Every case runs; none stops another.\n *\n * `revalidated` is where the client records what each call marked stale -\n * its onRevalidate - so the revalidation case can read it.\n */\nexport async function conformance(\n call: ConformanceCall,\n options: {\n revalidated: string[][]\n manifest?: ConformanceOptions['manifest']\n wrongSecret?: ConformanceCall\n /**\n * A POST straight to the endpoint, for what the client never sends:\n * malformed bodies, an oversized batch, no secret at all. `secret: false`\n * leaves the header off.\n */\n raw?: (body: string, options?: { secret?: boolean }) => Promise<Response>\n },\n): Promise<ConformanceResult[]> {\n const { revalidated, manifest, wrongSecret, raw } = options\n const results: ConformanceResult[] = []\n const types = typeof manifest === 'string' ? JSON.parse(readFileSync(manifest, 'utf-8')) : manifest\n\n const check = async (name: string, run: () => Promise<void>) => {\n try {\n await run()\n results.push({ case: name, ok: true })\n } catch (error) {\n results.push({ case: name, ok: false, detail: error instanceof Error ? error.message : String(error) })\n }\n }\n\n const expect = (ok: boolean, detail: string) => {\n if (!ok) throw new Error(detail)\n }\n\n const rejection = async (run: () => Promise<unknown>): Promise<unknown> => {\n try {\n const value = await run()\n\n throw new Error('answered ' + JSON.stringify(value) + ' instead of refusing')\n } catch (error) {\n return error\n }\n }\n\n /** The value against the type the adapter's manifest declares, when it declares one. */\n const typed = (name: string, value: unknown) => {\n const schema = types?.types?.[name]?.result\n\n if (!schema) return\n\n const problem = conformsTo(value, schema, types?.defs ?? {}, 'result')\n\n expect(problem === null, `the manifest types ${name}'s result, and what arrived does not fit it: ${problem}`)\n }\n\n await check('the manifest lists every Conformance function', async () => {\n if (!types) return\n\n const missing = Object.keys(CASES).filter((n) => !n.startsWith('__') && !types.functions?.includes(n))\n\n expect(missing.length === 0, 'not in functions: ' + missing.join(', '))\n })\n\n await check('the manifest\\'s actions is an object, even with none', async () => {\n if (!types) return\n\n expect(\n typeof types.actions === 'object' && types.actions !== null && !Array.isArray(types.actions),\n 'actions is ' + JSON.stringify(types.actions),\n )\n })\n\n await check('a value of any JSON shape comes back unchanged', async () => {\n for (const value of ECHOES) {\n const back = await call('Conformance.echo', value)\n\n expect(JSON.stringify(back) === JSON.stringify(value), `sent ${JSON.stringify(value)}, got ${JSON.stringify(back)}`)\n }\n })\n\n await check('\"no rows\" is an empty list, never null', async () => {\n const value = await call('Conformance.emptyList')\n\n expect(Array.isArray(value) && value.length === 0, 'got ' + JSON.stringify(value))\n typed('Conformance.emptyList', value)\n })\n\n await check('a time is an ISO 8601 string of the same instant', async () => {\n const value = await call('Conformance.time')\n\n expect(typeof value === 'string' && Date.parse(value) === INSTANT, 'got ' + JSON.stringify(value))\n typed('Conformance.time', value)\n })\n\n await check('an absent time is null', async () => {\n const value = await call('Conformance.noTime')\n\n expect(value === null, 'got ' + JSON.stringify(value))\n typed('Conformance.noTime', value)\n })\n\n await check('not signed in is the engine\\'s ServerAuthenticationError', async () => {\n const error = await rejection(() => call('Conformance.unauthenticated'))\n\n expect(error instanceof ServerAuthenticationError, 'got ' + String(error))\n })\n\n await check('not allowed is the engine\\'s ServerAuthorizationError', async () => {\n const error = await rejection(() => call('Conformance.unauthorized'))\n\n expect(error instanceof ServerAuthorizationError, 'got ' + String(error))\n })\n\n await check('not found is the engine\\'s notFound()', async () => {\n const error = await rejection(() => call('Conformance.notFound'))\n\n expect(isNotFoundSignal(error), 'got ' + String(error))\n })\n\n await check('a refusal keeps its status and its message', async () => {\n const error = (await rejection(() => call('Conformance.refuse'))) as Error & { refusalStatus?: number }\n\n // A refusal, not a failure: an action shows its message rather than\n // onError's, data or no data.\n expect(isActionRefusal(error), 'raised as ' + String(error) + ', not as a refusal - is refusalStatus in the reply?')\n expect(error.refusalStatus === 429, 'status ' + String(error.refusalStatus))\n expect(String(error.message).includes('Slow down.'), 'message ' + JSON.stringify(error.message))\n })\n\n await check('a refusal carries its data, its message and its status', async () => {\n const error = (await rejection(() => call('Conformance.refuseWithData'))) as Error & {\n refusalStatus?: number\n data?: unknown\n }\n\n expect(isActionRefusal(error), 'raised as ' + String(error) + ', not as a refusal - is refusalData in the reply?')\n expect(error.message === 'Still in use', 'message ' + JSON.stringify(error.message))\n expect(error.refusalStatus === 409, 'status ' + String(error.refusalStatus))\n // Compared as values, not as text: an object's keys have no order, and\n // Go writes a map's sorted.\n expect(\n sameValue(error.data, { blockers: [{ id: 7, href: '/orders/7' }] }),\n 'data ' + JSON.stringify(error.data),\n )\n })\n\n await check('refused input names its field', async () => {\n const error = (await rejection(() => call('Conformance.invalid'))) as { errors?: Record<string, string[]> }\n\n expect(Array.isArray(error.errors?.name) && error.errors.name.length > 0, 'errors ' + JSON.stringify(error.errors))\n })\n\n await check('a redirect is the engine\\'s redirect, to where it said', async () => {\n const taken = await withRedirect(async (seen) => {\n await rejection(() => call('Conformance.redirect'))\n\n return seen()\n })\n\n expect(taken?.location === '/login', 'redirect ' + JSON.stringify(taken))\n expect(taken!.status >= 300 && taken!.status < 400, 'status ' + taken?.status)\n })\n\n await check('in a batch, a revalidation stays with its own call', async () => {\n const before = revalidated.length\n\n await Promise.all([call('Conformance.revalidate'), call('Conformance.echo', 1), call('Conformance.echo', 2)])\n\n expect(revalidated.length - before === 1, 'revalidated ' + JSON.stringify(revalidated.slice(before)))\n })\n\n await check('a revalidation rides with the result', async () => {\n const value = await call('Conformance.revalidate')\n\n expect(value === 'ok', 'got ' + JSON.stringify(value))\n expect(revalidated.some((r) => r.includes('orders')), 'revalidated ' + JSON.stringify(revalidated))\n })\n\n await check('an unexpected failure is an error, not a refusal', async () => {\n const error = (await rejection(() => call('Conformance.fail'))) as Error & { refusalStatus?: number }\n\n expect(\n error instanceof Error && !(error instanceof ServerAuthenticationError) && !(error instanceof ServerAuthorizationError) && !error.refusalStatus && !isNotFoundSignal(error),\n 'got ' + String(error),\n )\n })\n\n await check('the visitor\\'s Authorization header is forwarded', async () => {\n const value = await withRequest(new Request('https://app.test/', { headers: { authorization: 'Bearer conformance' } }), () =>\n call('Conformance.authorization'),\n )\n\n expect(value === 'Bearer conformance', 'got ' + JSON.stringify(value))\n })\n\n await check('the visitor\\'s Cookie header is forwarded', async () => {\n const value = await withRequest(new Request('https://app.test/', { headers: { cookie: 'conformance=1; other=2' } }), () =>\n call('Conformance.cookie'),\n )\n\n expect(typeof value === 'string' && value.includes('conformance=1') && value.includes('other=2'), 'got ' + JSON.stringify(value))\n })\n\n await check('a cookie set during a call - a login - reaches the page\\'s response', async () => {\n const cookies = await withRequest(new Request('https://app.test/'), () =>\n withResponseDraft(async ({ taken }) => {\n const value = await call('Conformance.login')\n\n expect(value === 'ok', 'got ' + JSON.stringify(value))\n\n return taken().getSetCookie()\n }),\n )\n\n expect(cookies.some((c) => c.startsWith('conformance_login=')), 'Set-Cookie ' + JSON.stringify(cookies))\n })\n\n await check('arguments are decoded to their types', async () => {\n const value = await call('Conformance.double', 21)\n\n expect(value === 42, 'got ' + JSON.stringify(value))\n })\n\n await check('arguments that do not fit fail the call, not refuse it', async () => {\n for (const args of [['twenty-one'], []]) {\n const error: unknown = await rejection(() => call('Conformance.double', ...args))\n const fields = error as { refusalStatus?: number; errors?: unknown }\n\n expect(\n error instanceof Error && !(error instanceof ServerAuthenticationError) && !(error instanceof ServerAuthorizationError) &&\n !fields.refusalStatus && fields.errors === undefined && !isNotFoundSignal(error),\n `with ${JSON.stringify(args)}: got ` + String(error),\n )\n }\n })\n\n await check('refused input names nested fields with dots, and the form under \"\"', async () => {\n const error = (await rejection(() => call('Conformance.invalidNested'))) as { errors?: Record<string, string[]> }\n\n expect(Array.isArray(error.errors?.['address.city']) && error.errors['address.city'].length > 0, 'errors ' + JSON.stringify(error.errors))\n expect(Array.isArray(error.errors?.['']) && error.errors[''].length > 0, 'errors ' + JSON.stringify(error.errors))\n })\n\n await check('calls in one batch are each answered, a refusal only its own', async () => {\n const [a, b, c] = await Promise.allSettled([\n call('Conformance.echo', 1),\n call('Conformance.unauthenticated'),\n call('Conformance.echo', 2),\n ])\n\n expect(a.status === 'fulfilled' && a.value === 1, 'first ' + JSON.stringify(a))\n expect(b.status === 'rejected' && b.reason instanceof ServerAuthenticationError, 'second ' + String((b as PromiseRejectedResult).reason))\n expect(c.status === 'fulfilled' && c.value === 2, 'third ' + JSON.stringify(c))\n })\n\n await check('no guards at all passes: what a health check asks', async () => {\n // The renderer's /_rsc/health asks with an empty list: it runs no app\n // code, and still proves the address, the secret and the adapter.\n const value = await call('__rsc.middleware', [])\n\n expect(value === true, 'got ' + JSON.stringify(value))\n })\n\n await check('a guard that passes answers true', async () => {\n const value = await call('__rsc.middleware', ['conformance-allow'])\n\n expect(value === true, 'got ' + JSON.stringify(value))\n })\n\n await check('a guard that refuses refuses', async () => {\n const value = await call('__rsc.middleware', ['conformance-deny']).catch((e: unknown) => e)\n\n expect(value !== true, 'it answered true')\n })\n\n await check('a guard can send the visitor somewhere else', async () => {\n const taken = await withRedirect(async (seen) => {\n await call('__rsc.middleware', ['conformance-redirect']).catch(() => {})\n\n return seen()\n })\n\n expect(taken?.location === '/conformance-login', 'redirect ' + JSON.stringify(taken))\n })\n\n await check('guards run in order and stop at the first that does not pass', async () => {\n const after = await call('__rsc.middleware', ['conformance-allow', 'conformance-deny']).catch((e: unknown) => e)\n\n expect(after !== true, 'allow then deny answered true')\n\n // Deny first: the redirect after it must never be asked.\n const taken = await withRedirect(async (seen) => {\n const value = await call('__rsc.middleware', ['conformance-deny', 'conformance-redirect']).catch((e: unknown) => e)\n\n expect(value !== true, 'deny then redirect answered true')\n\n return seen()\n })\n\n expect(taken === null, 'the guard after a refusal ran: redirected to ' + JSON.stringify(taken))\n })\n\n await check('a guard nobody registered refuses: fail closed', async () => {\n const value = await call('__rsc.middleware', ['conformance-nobody-registered-this']).catch((e: unknown) => e)\n\n expect(value !== true, 'it answered true')\n })\n\n const versionsOf = async (query: { since: Record<string, number>; wait?: number }) => {\n const answer = (await call('__rsc.changed', query)) as { versions?: Record<string, number> } | null\n\n expect(typeof answer?.versions === 'object' && answer.versions !== null, 'got ' + JSON.stringify(answer))\n\n return answer!.versions!\n }\n\n await check('a name nobody changed is at version 0, and unchanged from 0', async () => {\n const all = await versionsOf({ since: { 'conformance:never': -1 } })\n\n expect(all['conformance:never'] === 0, 'from -1: ' + JSON.stringify(all))\n\n const none = await versionsOf({ since: { 'conformance:never': 0 } })\n\n expect(Object.keys(none).length === 0, 'from 0: ' + JSON.stringify(none))\n })\n\n await check('saying a name changed moves its version', async () => {\n const before = (await versionsOf({ since: { 'conformance:changed': -1 } }))['conformance:changed'] ?? 0\n const value = await call('Conformance.change')\n\n expect(value === 'ok', 'got ' + JSON.stringify(value))\n\n const moved = await versionsOf({ since: { 'conformance:changed': before } })\n\n expect(typeof moved['conformance:changed'] === 'number' && moved['conformance:changed'] !== before, 'from ' + before + ': ' + JSON.stringify(moved))\n })\n\n await check('a version is the time of the change, and never comes round again', async () => {\n // The larger of one past the old version and the time in ms: a counter\n // repeats once a pruned name starts again from 0, and a tab holding the\n // old value misses the next change. A minute's leeway for clock skew.\n const started = Date.now()\n\n await call('Conformance.change')\n\n const first = (await versionsOf({ since: { 'conformance:changed': -1 } }))['conformance:changed'] ?? 0\n\n expect(first >= started - 60_000, `a change at ${started} moved the version to ${first}: not a time in ms`)\n\n await call('Conformance.change')\n\n const second = (await versionsOf({ since: { 'conformance:changed': -1 } }))['conformance:changed'] ?? 0\n\n expect(second > first, `a second change moved ${first} to ${second}`)\n })\n\n await check('only the names that differ are answered', async () => {\n const current = (await versionsOf({ since: { 'conformance:changed': -1 } }))['conformance:changed'] ?? 0\n const answer = await versionsOf({ since: { 'conformance:changed': current, 'conformance:never': 5 } })\n\n expect(JSON.stringify(answer) === JSON.stringify({ 'conformance:never': 0 }), 'got ' + JSON.stringify(answer))\n })\n\n await check('waiting for a name to change is bounded by wait', async () => {\n const started = Date.now()\n const none = await versionsOf({ since: { 'conformance:never': 0 }, wait: 300 })\n const took = Date.now() - started\n\n expect(Object.keys(none).length === 0, 'got ' + JSON.stringify(none))\n expect(took < 3_000, 'took ' + took + 'ms')\n })\n\n if (raw) {\n const statusOf = async (body: string, secret = true) => (await raw(body, { secret })).status\n\n await check('a call with no secret at all is refused, 403', async () => {\n const status = await statusOf(JSON.stringify({ function: 'Conformance.echo', args: [1] }), false)\n\n expect(status === 403, 'answered ' + status)\n })\n\n await check('a function nobody registered is a 404', async () => {\n const status = await statusOf(JSON.stringify({ function: 'Conformance.nobodyRegisteredThis', args: [] }))\n\n expect(status === 404, 'answered ' + status)\n })\n\n await check('a malformed call is a 400: not JSON, no function, args not a list', async () => {\n for (const body of ['not json', JSON.stringify({ args: [] }), JSON.stringify({ function: 'Conformance.echo', args: 'x' })]) {\n const status = await statusOf(body)\n\n expect(status === 400, `${body} answered ${status}`)\n }\n })\n\n await check('a batch of more than 50 is refused, 413, before any call runs', async () => {\n const before = (await versionsOf({ since: { 'conformance:changed': -1 } }))['conformance:changed'] ?? 0\n const calls = Array.from({ length: 51 }, () => ({ function: 'Conformance.change', args: [] }))\n const status = await statusOf(JSON.stringify({ calls }))\n const after = (await versionsOf({ since: { 'conformance:changed': -1 } }))['conformance:changed'] ?? 0\n\n expect(status === 413, 'answered ' + status)\n expect(after === before, 'calls ran: conformance:changed moved from ' + before + ' to ' + after)\n })\n }\n\n if (wrongSecret) {\n await check('a call with the wrong secret is refused', async () => {\n const value = await wrongSecret('Conformance.echo', 'should not run').catch((e: unknown) => e)\n\n expect(value !== 'should not run', 'it ran')\n })\n }\n\n return results\n}\n\n/** Run the suite against an adapter's endpoint. */\nexport async function runConformance(options: ConformanceOptions): Promise<ConformanceResult[]> {\n const revalidated: string[][] = []\n const client = (secret: string) =>\n httpHostCalls({\n endpoint: options.endpoint,\n secret,\n fetch: options.fetch,\n onRevalidate: (targets) => revalidated.push(targets),\n })\n\n const doFetch = options.fetch ?? globalThis.fetch\n\n return await conformance(client(options.secret), {\n revalidated,\n manifest: options.manifest,\n wrongSecret: client(options.secret + '-wrong'),\n raw: (body, { secret = true } = {}) =>\n doFetch(options.endpoint, {\n method: 'POST',\n headers: { 'content-type': 'application/json', ...(secret ? { 'x-rsc-host-secret': options.secret } : {}) },\n body,\n }),\n })\n}\n\n/**\n * Whether a value fits the JSON Schema subset the manifest uses. Null when it\n * does; otherwise where and why it does not.\n */\nexport function conformsTo(value: unknown, schema: Schema, defs: Record<string, Schema>, at: string): string | null {\n if (!schema || Object.keys(schema).length === 0) return null\n\n const ref = schema.$ref\n\n if (typeof ref === 'string' && ref.startsWith('#/defs/')) {\n const target = defs[ref.slice(7)]\n\n return target ? conformsTo(value, target, defs, at) : `${at}: ${ref} is not in defs`\n }\n\n if (Array.isArray(schema.anyOf)) {\n const fits = (schema.anyOf as Schema[]).some((s) => conformsTo(value, s, defs, at) === null)\n\n return fits ? null : `${at}: ${JSON.stringify(value)} is none of ${JSON.stringify(schema.anyOf)}`\n }\n\n if (Array.isArray(schema.enum)) {\n return (schema.enum as unknown[]).includes(value) ? null : `${at}: ${JSON.stringify(value)} is not one of ${JSON.stringify(schema.enum)}`\n }\n\n const kind = Array.isArray(value) ? 'array' : value === null ? 'null' : typeof value\n\n switch (schema.type) {\n case 'string':\n if (kind !== 'string') return `${at}: expected a string, got ${JSON.stringify(value)}`\n if (schema.format === 'date-time' && Number.isNaN(Date.parse(value as string))) return `${at}: ${JSON.stringify(value)} is not a date-time`\n return null\n case 'integer':\n return Number.isInteger(value) ? null : `${at}: expected an integer, got ${JSON.stringify(value)}`\n case 'number':\n return kind === 'number' ? null : `${at}: expected a number, got ${JSON.stringify(value)}`\n case 'boolean':\n return kind === 'boolean' ? null : `${at}: expected a boolean, got ${JSON.stringify(value)}`\n case 'null':\n return value === null ? null : `${at}: expected null, got ${JSON.stringify(value)}`\n case 'array': {\n if (kind !== 'array') return `${at}: expected an array, got ${JSON.stringify(value)}`\n for (const [i, item] of (value as unknown[]).entries()) {\n const problem = conformsTo(item, schema.items as Schema, defs, `${at}[${i}]`)\n if (problem) return problem\n }\n return null\n }\n case 'object': {\n if (kind !== 'object') return `${at}: expected an object, got ${JSON.stringify(value)}`\n const object = value as Record<string, unknown>\n const properties = (schema.properties ?? {}) as Record<string, Schema>\n for (const name of (schema.required as string[] | undefined) ?? []) {\n if (!(name in object)) return `${at}.${name}: required, and missing`\n }\n for (const [name, s] of Object.entries(properties)) {\n if (name in object) {\n const problem = conformsTo(object[name], s, defs, `${at}.${name}`)\n if (problem) return problem\n }\n }\n const extra = schema.additionalProperties as Schema | undefined\n if (extra && !schema.properties) {\n for (const [name, item] of Object.entries(object)) {\n const problem = conformsTo(item, extra, defs, `${at}.${name}`)\n if (problem) return problem\n }\n }\n return null\n }\n default:\n return null\n }\n}\n\n/** Print a result table, and say whether the adapter conforms. */\nexport function report(results: ConformanceResult[]): boolean {\n for (const r of results) {\n stdout.write(` ${r.ok ? '✓' : '✗'} ${r.case}${r.ok ? '' : '\\n ' + r.detail}\\n`)\n }\n\n const failed = results.filter((r) => !r.ok).length\n\n stdout.write(failed === 0 ? `\\n conforms: ${results.length} cases\\n` : `\\n ${failed} of ${results.length} cases failed\\n`)\n\n return failed === 0\n}\n\n// Run as a command, not when imported.\nif (import.meta.url === pathToFileURL(argv[1] ?? '').href || argv[1]?.endsWith('rsc-kit-conformance')) {\n const flag = (name: string) => {\n const at = argv.indexOf('--' + name)\n\n return at === -1 ? undefined : argv[at + 1]\n }\n\n const endpoint = flag('endpoint')\n const secret = flag('secret')\n\n if (!endpoint || !secret) {\n stderr.write('usage: rsc-kit-conformance --endpoint <url> --secret <secret> [--manifest rsc-host.json]\\n')\n exit(2)\n }\n\n runConformance({ endpoint, secret, manifest: flag('manifest') })\n .then((results) => exit(report(results) ? 0 : 1))\n .catch((error: unknown) => {\n stderr.write('rsc-kit-conformance: ' + (error instanceof Error ? error.message : String(error)) + '\\n')\n exit(1)\n })\n}\n"]}
|
package/dist/host.d.ts
CHANGED
package/dist/host.js
CHANGED
|
@@ -1751,7 +1751,7 @@ export function createRscHandler(options) {
|
|
|
1751
1751
|
// the fetcher rejects with something a person can read — a failure rendered
|
|
1752
1752
|
// into a 200 would reach the browser as React's opaque error instead.
|
|
1753
1753
|
if (!("stream" in answered)) {
|
|
1754
|
-
return new Response(JSON.stringify({ message: answered.message, errors: answered.errors }), {
|
|
1754
|
+
return new Response(JSON.stringify({ message: answered.message, errors: answered.errors, refusal: answered.refusal }), {
|
|
1755
1755
|
status: answered.status,
|
|
1756
1756
|
headers: withVersion({
|
|
1757
1757
|
"Content-Type": "application/json",
|