From 61116845eccbb0d049b5b262e7520ce0f1cac795 Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Tue, 26 Mar 2024 12:40:15 -0400 Subject: [PATCH 1/5] Temp --- packages/router/router.ts | 70 ++++++++++++++++++++++++++++++++++----- 1 file changed, 61 insertions(+), 9 deletions(-) diff --git a/packages/router/router.ts b/packages/router/router.ts index cf693cc3b9..b9f0684e51 100644 --- a/packages/router/router.ts +++ b/packages/router/router.ts @@ -407,6 +407,7 @@ export interface StaticHandler { opts?: { loadRouteIds?: string[]; requestContext?: unknown; + skipLoaders?: boolean; skipLoaderErrorBubbling?: boolean; } ): Promise; @@ -2988,14 +2989,16 @@ export function createStaticHandler( * propagate that out and return the raw Response so the HTTP server can * return it directly. * - * - `opts.loadRouteIds` is an optional array of routeIds if you wish to only - * run a subset of route loaders on a GET request + * - `opts.loadRouteIds` is an optional array of routeIds to run only a subset of + * loaders during a query() call * - `opts.requestContext` is an optional server context that will be passed * to actions/loaders in the `context` parameter * - `opts.skipLoaderErrorBubbling` is an optional parameter that will prevent - * the bubbling of loader errors which allows single-fetch-type implementations + * the bubbling of errors which allows single-fetch-type implementations * where the client will handle the bubbling and we may need to return data * for the handling route + * - `opts.skipLoaders` is an optional parameter that will prevent loaders + * from running after an action */ async function query( request: Request, @@ -3003,10 +3006,12 @@ export function createStaticHandler( loadRouteIds, requestContext, skipLoaderErrorBubbling, + skipLoaders, }: { loadRouteIds?: string[]; requestContext?: unknown; skipLoaderErrorBubbling?: boolean; + skipLoaders?: boolean; } = {} ): Promise { let url = new URL(request.url); @@ -3060,6 +3065,7 @@ export function createStaticHandler( requestContext, loadRouteIds || null, skipLoaderErrorBubbling === true, + skipLoaders === true, null ); if (isResponse(result)) { @@ -3138,6 +3144,7 @@ export function createStaticHandler( requestContext, null, false, + false, match ); if (isResponse(result)) { @@ -3176,6 +3183,7 @@ export function createStaticHandler( requestContext: unknown, loadRouteIds: string[] | null, skipLoaderErrorBubbling: boolean, + skipLoaders: boolean, routeMatch: AgnosticDataRouteMatch | null ): Promise | Response> { invariant( @@ -3192,6 +3200,7 @@ export function createStaticHandler( requestContext, loadRouteIds, skipLoaderErrorBubbling, + skipLoaders, routeMatch != null ); return result; @@ -3238,6 +3247,7 @@ export function createStaticHandler( requestContext: unknown, loadRouteIds: string[] | null, skipLoaderErrorBubbling: boolean, + skipLoaders: boolean, isRouteRequest: boolean ): Promise | Response> { let result: DataResult; @@ -3326,7 +3336,33 @@ export function createStaticHandler( if (isErrorResult(result)) { // Store off the pending error - we use it to determine which loaders // to call and will commit it when we complete the navigation - let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id); + let boundaryMatch = skipLoaderErrorBubbling + ? actionMatch + : findNearestBoundary(matches, actionMatch.route.id); + let statusCode = isRouteErrorResponse(result.error) + ? result.error.status + : result.statusCode != null + ? result.statusCode + : 500; + let actionHeaders = { + ...(result.headers ? { [actionMatch.route.id]: result.headers } : {}), + }; + + if (skipLoaders) { + return { + matches, + loaderData: {}, + actionData: {}, + errors: { + [boundaryMatch.route.id]: result.error, + }, + statusCode, + loaderHeaders: {}, + actionHeaders, + activeDeferreds: null, + }; + } + let context = await loadRouteData( loaderRequest, matches, @@ -3340,13 +3376,28 @@ export function createStaticHandler( // action status codes take precedence over loader status codes return { ...context, - statusCode: isRouteErrorResponse(result.error) - ? result.error.status - : 500, + statusCode, actionData: null, - actionHeaders: { - ...(result.headers ? { [actionMatch.route.id]: result.headers } : {}), + actionHeaders, + }; + } + + let actionHeaders = result.headers + ? { [actionMatch.route.id]: result.headers } + : {}; + + if (skipLoaders) { + return { + matches, + loaderData: {}, + actionData: { + [actionMatch.route.id]: result.data, }, + errors: null, + statusCode: result.statusCode || 200, + loaderHeaders: {}, + actionHeaders, + activeDeferreds: null, }; } @@ -4188,6 +4239,7 @@ async function callDataStrategyImpl( }), request, params: matches[0].params, + context: requestContext, }); // Throw if any loadRoute implementations not called since they are what From 0f6db9c93a80d28da2f85eeac9b40f7b4128b3f3 Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Tue, 26 Mar 2024 15:38:39 -0400 Subject: [PATCH 2/5] Move datastrategy to a call-site param for staticHandler.query --- packages/router/router.ts | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/packages/router/router.ts b/packages/router/router.ts index b9f0684e51..e99b844e66 100644 --- a/packages/router/router.ts +++ b/packages/router/router.ts @@ -409,6 +409,7 @@ export interface StaticHandler { requestContext?: unknown; skipLoaders?: boolean; skipLoaderErrorBubbling?: boolean; + unstable_dataStrategy?: DataStrategyFunction; } ): Promise; queryRoute( @@ -2927,7 +2928,6 @@ export interface CreateStaticHandlerOptions { * @deprecated Use `mapRouteProperties` instead */ detectErrorBoundary?: DetectErrorBoundaryFunction; - unstable_dataStrategy?: DataStrategyFunction; mapRouteProperties?: MapRoutePropertiesFunction; future?: Partial; } @@ -2943,7 +2943,6 @@ export function createStaticHandler( let manifest: RouteManifest = {}; let basename = (opts ? opts.basename : null) || "/"; - let dataStrategyImpl = opts?.unstable_dataStrategy || defaultDataStrategy; let mapRouteProperties: MapRoutePropertiesFunction; if (opts?.mapRouteProperties) { mapRouteProperties = opts.mapRouteProperties; @@ -3007,11 +3006,13 @@ export function createStaticHandler( requestContext, skipLoaderErrorBubbling, skipLoaders, + unstable_dataStrategy, }: { loadRouteIds?: string[]; requestContext?: unknown; skipLoaderErrorBubbling?: boolean; skipLoaders?: boolean; + unstable_dataStrategy?: DataStrategyFunction; } = {} ): Promise { let url = new URL(request.url); @@ -3063,6 +3064,7 @@ export function createStaticHandler( location, matches, requestContext, + unstable_dataStrategy || null, loadRouteIds || null, skipLoaderErrorBubbling === true, skipLoaders === true, @@ -3143,6 +3145,7 @@ export function createStaticHandler( matches, requestContext, null, + null, false, false, match @@ -3181,6 +3184,7 @@ export function createStaticHandler( location: Location, matches: AgnosticDataRouteMatch[], requestContext: unknown, + unstable_dataStrategy: DataStrategyFunction | null, loadRouteIds: string[] | null, skipLoaderErrorBubbling: boolean, skipLoaders: boolean, @@ -3198,6 +3202,7 @@ export function createStaticHandler( matches, routeMatch || getTargetMatch(matches, location), requestContext, + unstable_dataStrategy, loadRouteIds, skipLoaderErrorBubbling, skipLoaders, @@ -3210,6 +3215,7 @@ export function createStaticHandler( request, matches, requestContext, + unstable_dataStrategy, loadRouteIds, skipLoaderErrorBubbling, routeMatch @@ -3245,6 +3251,7 @@ export function createStaticHandler( matches: AgnosticDataRouteMatch[], actionMatch: AgnosticDataRouteMatch, requestContext: unknown, + unstable_dataStrategy: DataStrategyFunction | null, loadRouteIds: string[] | null, skipLoaderErrorBubbling: boolean, skipLoaders: boolean, @@ -3272,7 +3279,8 @@ export function createStaticHandler( [actionMatch], matches, isRouteRequest, - requestContext + requestContext, + unstable_dataStrategy ); result = results[0]; @@ -3367,6 +3375,7 @@ export function createStaticHandler( loaderRequest, matches, requestContext, + unstable_dataStrategy, loadRouteIds, skipLoaderErrorBubbling, null, @@ -3405,6 +3414,7 @@ export function createStaticHandler( loaderRequest, matches, requestContext, + unstable_dataStrategy, loadRouteIds, skipLoaderErrorBubbling, null @@ -3427,6 +3437,7 @@ export function createStaticHandler( request: Request, matches: AgnosticDataRouteMatch[], requestContext: unknown, + unstable_dataStrategy: DataStrategyFunction | null, loadRouteIds: string[] | null, skipLoaderErrorBubbling: boolean, routeMatch: AgnosticDataRouteMatch | null, @@ -3495,7 +3506,8 @@ export function createStaticHandler( matchesToLoad, matches, isRouteRequest, - requestContext + requestContext, + unstable_dataStrategy ); if (request.signal.aborted) { @@ -3541,10 +3553,11 @@ export function createStaticHandler( matchesToLoad: AgnosticDataRouteMatch[], matches: AgnosticDataRouteMatch[], isRouteRequest: boolean, - requestContext: unknown + requestContext: unknown, + unstable_dataStrategy: DataStrategyFunction | null ): Promise { let results = await callDataStrategyImpl( - dataStrategyImpl, + unstable_dataStrategy || defaultDataStrategy, type, request, matchesToLoad, From 2fd30b6aa72a66006696958dcba68dae3a352fe5 Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Tue, 26 Mar 2024 17:20:37 -0400 Subject: [PATCH 3/5] Fix tests --- packages/router/__tests__/ssr-test.ts | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/packages/router/__tests__/ssr-test.ts b/packages/router/__tests__/ssr-test.ts index bf0d54c6b6..19061e15e9 100644 --- a/packages/router/__tests__/ssr-test.ts +++ b/packages/router/__tests__/ssr-test.ts @@ -1649,11 +1649,11 @@ describe("ssr", () => { describe("router dataStrategy", () => { it("should support document load navigations with custom dataStrategy", async () => { - let { query } = createStaticHandler(SSR_ROUTES, { + let { query } = createStaticHandler(SSR_ROUTES); + + let context = await query(createRequest("/custom"), { unstable_dataStrategy: urlDataStrategy, }); - - let context = await query(createRequest("/custom")); expect(context).toMatchObject({ actionData: null, loaderData: { @@ -2678,18 +2678,5 @@ describe("ssr", () => { /* eslint-enable jest/no-conditional-expect */ }); - - describe("router dataStrategy", () => { - it("should match routes automatically if no routeId is provided", async () => { - let { queryRoute } = createStaticHandler(SSR_ROUTES, { - unstable_dataStrategy: urlDataStrategy, - }); - let data; - - data = await queryRoute(createRequest("/custom")); - expect(data).toBeInstanceOf(URLSearchParams); - expect((data as URLSearchParams).get("foo")).toBe("bar"); - }); - }); }); }); From 54da459221c2bc6249f4c625e2e05606bf4faa49 Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Tue, 26 Mar 2024 17:24:33 -0400 Subject: [PATCH 4/5] Add changeset --- .changeset/slow-flies-help.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/slow-flies-help.md diff --git a/.changeset/slow-flies-help.md b/.changeset/slow-flies-help.md new file mode 100644 index 0000000000..94d7064ecb --- /dev/null +++ b/.changeset/slow-flies-help.md @@ -0,0 +1,6 @@ +--- +"@remix-run/router": minor +--- + +- Move `unstable_dataStrategy` from `createStaticHandler` to `staticHandler.query` so it can be request-specific for use with the `ResponseStub` approach in Remix. It's not really applicable to `queryRoute` for now since that's a singular handler call anyway so any pre-processing/post/processing could be done there manually. +- Added a new `skipLoaders` flag to `staticHandler.query` for calling only the action in Remix Single Fetch From c5ff2394a8b603d38cdfa40f339d2b11a44c2362 Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Tue, 26 Mar 2024 17:25:12 -0400 Subject: [PATCH 5/5] Bump bundle --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 242ee7956a..605d1b9aca 100644 --- a/package.json +++ b/package.json @@ -105,7 +105,7 @@ }, "filesize": { "packages/router/dist/router.umd.min.js": { - "none": "52.4 kB" + "none": "52.8 kB" }, "packages/react-router/dist/react-router.production.min.js": { "none": "14.8 kB"