rwsdk 1.0.0-alpha.2 → 1.0.0-alpha.20
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/lib/e2e/browser.d.mts +10 -0
- package/dist/lib/e2e/browser.mjs +124 -0
- package/dist/lib/e2e/dev.d.mts +8 -0
- package/dist/lib/e2e/dev.mjs +242 -0
- package/dist/lib/e2e/environment.d.mts +14 -0
- package/dist/lib/e2e/environment.mjs +266 -0
- package/dist/lib/e2e/index.d.mts +8 -0
- package/dist/lib/e2e/index.mjs +8 -0
- package/dist/lib/e2e/poll.d.mts +8 -0
- package/dist/lib/e2e/poll.mjs +31 -0
- package/dist/lib/e2e/release.d.mts +56 -0
- package/dist/lib/e2e/release.mjs +559 -0
- package/dist/lib/e2e/retry.d.mts +4 -0
- package/dist/lib/e2e/retry.mjs +16 -0
- package/dist/lib/e2e/setup.d.mts +2 -0
- package/dist/lib/e2e/setup.mjs +1 -0
- package/dist/lib/e2e/tarball.d.mts +14 -0
- package/dist/lib/e2e/tarball.mjs +99 -0
- package/dist/lib/e2e/testHarness.d.mts +132 -0
- package/dist/lib/e2e/testHarness.mjs +437 -0
- package/dist/lib/e2e/types.d.mts +32 -0
- package/dist/lib/getShortName.mjs +6 -1
- package/dist/lib/getShortName.test.d.mts +1 -0
- package/dist/lib/getShortName.test.mjs +25 -0
- package/dist/lib/hasPkgScript.d.mts +4 -1
- package/dist/lib/hasPkgScript.mjs +9 -6
- package/dist/lib/hasPkgScript.test.d.mts +1 -0
- package/dist/lib/hasPkgScript.test.mjs +33 -0
- package/dist/lib/jsonUtils.mjs +3 -0
- package/dist/lib/jsonUtils.test.d.mts +1 -0
- package/dist/lib/jsonUtils.test.mjs +90 -0
- package/dist/lib/normalizeModulePath.d.mts +5 -0
- package/dist/lib/normalizeModulePath.mjs +1 -1
- package/dist/lib/normalizeModulePath.test.d.mts +1 -0
- package/dist/lib/{normalizeModulePath.test.js → normalizeModulePath.test.mjs} +20 -1
- package/dist/lib/smokeTests/browser.mjs +3 -94
- package/dist/lib/smokeTests/development.mjs +2 -223
- package/dist/lib/smokeTests/environment.d.mts +4 -11
- package/dist/lib/smokeTests/environment.mjs +10 -158
- package/dist/lib/smokeTests/release.d.mts +2 -49
- package/dist/lib/smokeTests/release.mjs +3 -503
- package/dist/llms/rules/middleware.d.ts +1 -1
- package/dist/llms/rules/middleware.js +4 -4
- package/dist/runtime/entries/worker.d.ts +0 -1
- package/dist/runtime/entries/worker.js +0 -1
- package/dist/runtime/lib/auth/session.d.ts +2 -2
- package/dist/runtime/lib/auth/session.js +4 -4
- package/dist/runtime/lib/memoizeOnId.test.d.ts +1 -0
- package/dist/runtime/lib/memoizeOnId.test.js +49 -0
- package/dist/runtime/lib/realtime/protocol.test.d.ts +1 -0
- package/dist/runtime/lib/realtime/protocol.test.js +107 -0
- package/dist/runtime/lib/realtime/shared.test.d.ts +1 -0
- package/dist/runtime/lib/realtime/shared.test.js +18 -0
- package/dist/runtime/lib/realtime/validateUpgradeRequest.test.d.ts +1 -0
- package/dist/runtime/lib/realtime/validateUpgradeRequest.test.js +66 -0
- package/dist/runtime/lib/realtime/worker.d.ts +1 -1
- package/dist/runtime/lib/router.js +40 -22
- package/dist/runtime/lib/router.test.js +590 -2
- package/dist/runtime/lib/rwContext.d.ts +22 -0
- package/dist/runtime/lib/rwContext.js +1 -0
- package/dist/runtime/lib/stitchDocumentAndAppStreams.d.ts +18 -0
- package/dist/runtime/lib/stitchDocumentAndAppStreams.js +143 -0
- package/dist/runtime/lib/turnstile/verifyTurnstileToken.d.ts +2 -1
- package/dist/runtime/lib/turnstile/verifyTurnstileToken.js +6 -6
- package/dist/runtime/lib/turnstile/verifyTurnstileToken.test.d.ts +1 -0
- package/dist/runtime/lib/turnstile/verifyTurnstileToken.test.js +49 -0
- package/dist/runtime/register/worker.d.ts +1 -1
- package/dist/runtime/register/worker.js +33 -21
- package/dist/runtime/render/assembleDocument.d.ts +6 -0
- package/dist/runtime/render/assembleDocument.js +22 -0
- package/dist/runtime/render/createThenableFromReadableStream.d.ts +1 -0
- package/dist/runtime/render/createThenableFromReadableStream.js +9 -0
- package/dist/runtime/render/normalizeActionResult.d.ts +1 -0
- package/dist/runtime/render/normalizeActionResult.js +43 -0
- package/dist/runtime/render/preloads.d.ts +2 -2
- package/dist/runtime/render/preloads.js +2 -3
- package/dist/runtime/render/{renderRscThenableToHtmlStream.d.ts → renderDocumentHtmlStream.d.ts} +3 -3
- package/dist/runtime/render/renderDocumentHtmlStream.js +39 -0
- package/dist/runtime/render/renderHtmlStream.d.ts +7 -0
- package/dist/runtime/render/renderHtmlStream.js +31 -0
- package/dist/runtime/render/renderToRscStream.d.ts +5 -3
- package/dist/runtime/render/renderToRscStream.js +12 -41
- package/dist/runtime/render/renderToStream.d.ts +2 -1
- package/dist/runtime/render/renderToStream.js +15 -8
- package/dist/runtime/render/stylesheets.d.ts +2 -2
- package/dist/runtime/render/stylesheets.js +2 -3
- package/dist/runtime/requestInfo/types.d.ts +0 -2
- package/dist/runtime/requestInfo/worker.js +1 -9
- package/dist/runtime/ssrBridge.d.ts +2 -1
- package/dist/runtime/ssrBridge.js +2 -1
- package/dist/runtime/worker.d.ts +1 -0
- package/dist/runtime/worker.js +11 -14
- package/dist/scripts/debug-sync.mjs +102 -133
- package/dist/vite/buildApp.d.mts +2 -1
- package/dist/vite/buildApp.mjs +9 -5
- package/dist/vite/checkIsUsingPrisma.d.mts +4 -0
- package/dist/vite/checkIsUsingPrisma.mjs +2 -2
- package/dist/vite/checkIsUsingPrisma.test.d.mts +1 -0
- package/dist/vite/checkIsUsingPrisma.test.mjs +30 -0
- package/dist/vite/configPlugin.mjs +54 -14
- package/dist/vite/createDirectiveLookupPlugin.d.mts +9 -0
- package/dist/vite/createDirectiveLookupPlugin.mjs +33 -29
- package/dist/vite/createDirectiveLookupPlugin.test.d.mts +1 -0
- package/dist/vite/createDirectiveLookupPlugin.test.mjs +40 -0
- package/dist/vite/directiveModulesDevPlugin.d.mts +4 -1
- package/dist/vite/directiveModulesDevPlugin.mjs +6 -5
- package/dist/vite/directiveModulesDevPlugin.test.d.mts +1 -0
- package/dist/vite/directiveModulesDevPlugin.test.mjs +59 -0
- package/dist/vite/directivesPlugin.d.mts +1 -0
- package/dist/vite/directivesPlugin.mjs +1 -1
- package/dist/vite/directivesPlugin.test.d.mts +1 -0
- package/dist/vite/directivesPlugin.test.mjs +24 -0
- package/dist/vite/ensureAliasArray.test.d.mts +1 -0
- package/dist/vite/ensureAliasArray.test.mjs +71 -0
- package/dist/vite/findSpecifiers.mjs +2 -1
- package/dist/vite/findSpecifiers.test.d.mts +1 -0
- package/dist/vite/findSpecifiers.test.mjs +202 -0
- package/dist/vite/findSsrSpecifiers.test.d.mts +1 -0
- package/dist/vite/findSsrSpecifiers.test.mjs +99 -0
- package/dist/vite/hasDirective.d.mts +6 -3
- package/dist/vite/hasDirective.mjs +43 -27
- package/dist/vite/hasDirective.test.d.mts +1 -0
- package/dist/vite/hasDirective.test.mjs +107 -0
- package/dist/vite/isJsFile.test.d.mts +1 -0
- package/dist/vite/isJsFile.test.mjs +38 -0
- package/dist/vite/{reactConditionsResolverPlugin.d.mts → knownDepsResolverPlugin.d.mts} +2 -2
- package/dist/vite/{reactConditionsResolverPlugin.mjs → knownDepsResolverPlugin.mjs} +28 -23
- package/dist/vite/linkerPlugin.d.mts +8 -0
- package/dist/vite/linkerPlugin.mjs +30 -22
- package/dist/vite/linkerPlugin.test.d.mts +1 -0
- package/dist/vite/linkerPlugin.test.mjs +41 -0
- package/dist/vite/miniflareHMRPlugin.d.mts +5 -0
- package/dist/vite/miniflareHMRPlugin.mjs +2 -2
- package/dist/vite/miniflareHMRPlugin.test.d.mts +1 -0
- package/dist/vite/miniflareHMRPlugin.test.mjs +42 -0
- package/dist/vite/redwoodPlugin.d.mts +9 -0
- package/dist/vite/redwoodPlugin.mjs +29 -5
- package/dist/vite/redwoodPlugin.test.d.mts +1 -0
- package/dist/vite/redwoodPlugin.test.mjs +34 -0
- package/dist/vite/resolveForcedPaths.d.mts +4 -0
- package/dist/vite/resolveForcedPaths.mjs +9 -0
- package/dist/vite/runDirectivesScan.d.mts +22 -1
- package/dist/vite/runDirectivesScan.mjs +105 -58
- package/dist/vite/runDirectivesScan.test.d.mts +1 -0
- package/dist/vite/runDirectivesScan.test.mjs +73 -0
- package/dist/vite/ssrBridgePlugin.mjs +8 -1
- package/dist/vite/transformClientComponents.mjs +6 -4
- package/dist/vite/transformClientComponents.test.mjs +116 -58
- package/dist/vite/transformServerFunctions.d.mts +1 -1
- package/dist/vite/transformServerFunctions.mjs +1 -1
- package/dist/vite/transformServerFunctions.test.mjs +3 -3
- package/package.json +56 -47
- package/dist/runtime/imports/resolveSSRValue.d.ts +0 -1
- package/dist/runtime/imports/resolveSSRValue.js +0 -8
- package/dist/runtime/render/renderRscThenableToHtmlStream.js +0 -54
- package/dist/runtime/render/transformRscToHtmlStream.d.ts +0 -8
- package/dist/runtime/render/transformRscToHtmlStream.js +0 -19
- /package/dist/lib/{normalizeModulePath.test.d.ts → e2e/types.mjs} +0 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { packMessage, unpackMessage } from "./protocol";
|
|
3
|
+
import { MESSAGE_TYPE } from "./shared";
|
|
4
|
+
describe("Realtime Protocol pack/unpack", () => {
|
|
5
|
+
const textEncoder = new TextEncoder();
|
|
6
|
+
// Helper to generate a UUID string of the correct length
|
|
7
|
+
const generateId = () => "a".repeat(36);
|
|
8
|
+
const testMessages = [
|
|
9
|
+
{
|
|
10
|
+
type: MESSAGE_TYPE.ACTION_REQUEST,
|
|
11
|
+
id: "my-action",
|
|
12
|
+
args: { foo: "bar" },
|
|
13
|
+
requestId: generateId(),
|
|
14
|
+
clientUrl: "http://localhost:3000/",
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
type: MESSAGE_TYPE.ACTION_START,
|
|
18
|
+
id: generateId(),
|
|
19
|
+
status: 200,
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
type: MESSAGE_TYPE.ACTION_CHUNK,
|
|
23
|
+
id: generateId(),
|
|
24
|
+
payload: textEncoder.encode("chunk data"),
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
type: MESSAGE_TYPE.ACTION_END,
|
|
28
|
+
id: generateId(),
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
type: MESSAGE_TYPE.ACTION_ERROR,
|
|
32
|
+
id: generateId(),
|
|
33
|
+
error: "Something went wrong",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
type: MESSAGE_TYPE.RSC_START,
|
|
37
|
+
id: generateId(),
|
|
38
|
+
status: 200,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
type: MESSAGE_TYPE.RSC_CHUNK,
|
|
42
|
+
id: generateId(),
|
|
43
|
+
payload: textEncoder.encode("rsc chunk"),
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
type: MESSAGE_TYPE.RSC_END,
|
|
47
|
+
id: generateId(),
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
testMessages.forEach((message) => {
|
|
51
|
+
it(`should correctly pack and unpack a ${Object.keys(MESSAGE_TYPE).find((key) => MESSAGE_TYPE[key] === message.type) || "UNKNOWN"} message`, () => {
|
|
52
|
+
const packed = packMessage(message);
|
|
53
|
+
const unpacked = unpackMessage(packed);
|
|
54
|
+
expect(unpacked).toEqual(message);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
describe("Error Handling", () => {
|
|
58
|
+
it("should throw an error for an unknown message type on pack", () => {
|
|
59
|
+
const invalidMessage = { type: 999 };
|
|
60
|
+
expect(() => packMessage(invalidMessage)).toThrow("Unknown message type for packing");
|
|
61
|
+
});
|
|
62
|
+
it("should throw an error for an unknown message type on unpack", () => {
|
|
63
|
+
const invalidData = new Uint8Array([99, 1, 2, 3]);
|
|
64
|
+
expect(() => unpackMessage(invalidData)).toThrow("Unknown message type for unpacking: 99");
|
|
65
|
+
});
|
|
66
|
+
it("should throw an error for an empty message on unpack", () => {
|
|
67
|
+
const emptyData = new Uint8Array([]);
|
|
68
|
+
expect(() => unpackMessage(emptyData)).toThrow("Cannot unpack empty message");
|
|
69
|
+
});
|
|
70
|
+
const invalidLengthTests = [
|
|
71
|
+
{ type: MESSAGE_TYPE.ACTION_START, name: "START" },
|
|
72
|
+
{ type: MESSAGE_TYPE.RSC_START, name: "START" },
|
|
73
|
+
{ type: MESSAGE_TYPE.ACTION_CHUNK, name: "CHUNK" },
|
|
74
|
+
{ type: MESSAGE_TYPE.RSC_CHUNK, name: "CHUNK" },
|
|
75
|
+
{ type: MESSAGE_TYPE.ACTION_END, name: "END" },
|
|
76
|
+
{ type: MESSAGE_TYPE.RSC_END, name: "END" },
|
|
77
|
+
{ type: MESSAGE_TYPE.ACTION_ERROR, name: "ERROR" },
|
|
78
|
+
];
|
|
79
|
+
invalidLengthTests.forEach(({ type, name }) => {
|
|
80
|
+
it(`should throw for invalid ${name} message length on unpack`, () => {
|
|
81
|
+
const invalidData = new Uint8Array([type, 1, 2, 3]); // Too short
|
|
82
|
+
expect(() => unpackMessage(invalidData)).toThrow(`Invalid ${name} message length`);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
const invalidIdTests = [
|
|
86
|
+
{ type: MESSAGE_TYPE.ACTION_START, name: "START" },
|
|
87
|
+
{ type: MESSAGE_TYPE.RSC_START, name: "START" },
|
|
88
|
+
{ type: MESSAGE_TYPE.ACTION_CHUNK, name: "CHUNK" },
|
|
89
|
+
{ type: MESSAGE_TYPE.RSC_CHUNK, name: "CHUNK" },
|
|
90
|
+
{ type: MESSAGE_TYPE.ACTION_END, name: "END" },
|
|
91
|
+
{ type: MESSAGE_TYPE.RSC_END, name: "END" },
|
|
92
|
+
{ type: MESSAGE_TYPE.ACTION_ERROR, name: "ERROR" },
|
|
93
|
+
];
|
|
94
|
+
invalidIdTests.forEach(({ type, name }) => {
|
|
95
|
+
it(`should throw for invalid ID length on ${name} message pack`, () => {
|
|
96
|
+
const message = {
|
|
97
|
+
type,
|
|
98
|
+
id: "short-id",
|
|
99
|
+
status: 200, // For START types
|
|
100
|
+
payload: new Uint8Array(), // For CHUNK types
|
|
101
|
+
error: "", // For ERROR type
|
|
102
|
+
};
|
|
103
|
+
expect(() => packMessage(message)).toThrow(`Invalid message ID length for ${name} message`);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { MESSAGE_TYPE } from "./shared";
|
|
3
|
+
describe("Realtime Shared Constants", () => {
|
|
4
|
+
it("MESSAGE_TYPE should match snapshot", () => {
|
|
5
|
+
expect(MESSAGE_TYPE).toMatchInlineSnapshot(`
|
|
6
|
+
{
|
|
7
|
+
"ACTION_CHUNK": 5,
|
|
8
|
+
"ACTION_END": 6,
|
|
9
|
+
"ACTION_ERROR": 7,
|
|
10
|
+
"ACTION_REQUEST": 3,
|
|
11
|
+
"ACTION_START": 4,
|
|
12
|
+
"RSC_CHUNK": 1,
|
|
13
|
+
"RSC_END": 2,
|
|
14
|
+
"RSC_START": 0,
|
|
15
|
+
}
|
|
16
|
+
`);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { validateUpgradeRequest } from "./validateUpgradeRequest";
|
|
3
|
+
describe("validateUpgradeRequest", () => {
|
|
4
|
+
it("should return valid for a correct WebSocket upgrade request", () => {
|
|
5
|
+
const request = new Request("http://localhost:8787/ws", {
|
|
6
|
+
headers: {
|
|
7
|
+
Upgrade: "websocket",
|
|
8
|
+
Origin: "http://localhost:8787",
|
|
9
|
+
},
|
|
10
|
+
});
|
|
11
|
+
const result = validateUpgradeRequest(request);
|
|
12
|
+
expect(result.valid).toBe(true);
|
|
13
|
+
});
|
|
14
|
+
it("should return invalid if Upgrade header is not 'websocket'", async () => {
|
|
15
|
+
const request = new Request("http://localhost:8787/ws", {
|
|
16
|
+
headers: {
|
|
17
|
+
Upgrade: "not-websocket",
|
|
18
|
+
Origin: "http://localhost:8787",
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
const result = validateUpgradeRequest(request);
|
|
22
|
+
expect(result.valid).toBe(false);
|
|
23
|
+
if (!result.valid) {
|
|
24
|
+
expect(result.response?.status).toBe(400);
|
|
25
|
+
await expect(result.response?.text()).resolves.toBe("Expected WebSocket");
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
it("should return invalid if Upgrade header is missing", () => {
|
|
29
|
+
const request = new Request("http://localhost:8787/ws", {
|
|
30
|
+
headers: {
|
|
31
|
+
Origin: "http://localhost:8787",
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
const result = validateUpgradeRequest(request);
|
|
35
|
+
expect(result.valid).toBe(false);
|
|
36
|
+
if (!result.valid) {
|
|
37
|
+
expect(result.response?.status).toBe(400);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
it("should return invalid if Origin header is missing", async () => {
|
|
41
|
+
const request = new Request("http://localhost:8787/ws", {
|
|
42
|
+
headers: {
|
|
43
|
+
Upgrade: "websocket",
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
const result = validateUpgradeRequest(request);
|
|
47
|
+
expect(result.valid).toBe(false);
|
|
48
|
+
if (!result.valid) {
|
|
49
|
+
expect(result.response?.status).toBe(403);
|
|
50
|
+
await expect(result.response?.text()).resolves.toBe("Invalid origin");
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
it("should return invalid if Origin does not match request URL", () => {
|
|
54
|
+
const request = new Request("http://localhost:8787/ws", {
|
|
55
|
+
headers: {
|
|
56
|
+
Upgrade: "websocket",
|
|
57
|
+
Origin: "http://another-domain.com",
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
const result = validateUpgradeRequest(request);
|
|
61
|
+
expect(result.valid).toBe(false);
|
|
62
|
+
if (!result.valid) {
|
|
63
|
+
expect(result.response?.status).toBe(403);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
});
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { RealtimeDurableObject } from "./durableObject";
|
|
2
2
|
export { renderRealtimeClients } from "./renderRealtimeClients";
|
|
3
|
-
export declare const realtimeRoute: (getDurableObjectNamespace: (env: Cloudflare.Env) => DurableObjectNamespace<RealtimeDurableObject>) => import("../router").RouteDefinition<import("../../
|
|
3
|
+
export declare const realtimeRoute: (getDurableObjectNamespace: (env: Cloudflare.Env) => DurableObjectNamespace<RealtimeDurableObject>) => import("../router").RouteDefinition<import("../../worker").RequestInfo<any, import("../../worker").DefaultAppContext>>;
|
|
@@ -97,30 +97,38 @@ export function defineRoutes(routes) {
|
|
|
97
97
|
return undefined;
|
|
98
98
|
}
|
|
99
99
|
// --- Main flow ---
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
100
|
+
let firstRouteDefinitionEncountered = false;
|
|
101
|
+
let actionHandled = false;
|
|
102
|
+
const handleAction = async () => {
|
|
103
|
+
if (!actionHandled && url.searchParams.has("__rsc_action_id")) {
|
|
104
|
+
getRequestInfo().rw.actionResult = await rscActionHandler(request);
|
|
105
|
+
actionHandled = true;
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
for (const route of flattenedRoutes) {
|
|
109
|
+
if (typeof route === "function") {
|
|
110
|
+
// This is a global middleware.
|
|
111
|
+
const result = await route(getRequestInfo());
|
|
112
|
+
const handled = await handleMiddlewareResult(result);
|
|
113
|
+
if (handled) {
|
|
114
|
+
return handled; // Short-circuit
|
|
115
|
+
}
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
// This is a RouteDefinition.
|
|
119
|
+
// The first time we see one, we handle any RSC actions.
|
|
120
|
+
if (!firstRouteDefinitionEncountered) {
|
|
121
|
+
firstRouteDefinitionEncountered = true;
|
|
122
|
+
await handleAction();
|
|
108
123
|
}
|
|
109
|
-
}
|
|
110
|
-
// 2. Handle RSC actions
|
|
111
|
-
if (url.searchParams.has("__rsc_action_id")) {
|
|
112
|
-
getRequestInfo().rw.actionResult = await rscActionHandler(request);
|
|
113
|
-
}
|
|
114
|
-
// 3. Match and handle routes
|
|
115
|
-
for (const route of routeDefinitions) {
|
|
116
124
|
const params = matchPath(route.path, path);
|
|
117
125
|
if (!params) {
|
|
118
|
-
continue;
|
|
126
|
+
continue; // Not a match, keep going.
|
|
119
127
|
}
|
|
120
|
-
// Found a match: run route-specific middlewares, then the final component
|
|
128
|
+
// Found a match: run route-specific middlewares, then the final component, then stop.
|
|
121
129
|
return await runWithRequestInfoOverrides({ params }, async () => {
|
|
122
130
|
const { routeMiddlewares, componentHandler } = parseHandlers(route.handler);
|
|
123
|
-
//
|
|
131
|
+
// Route-specific middlewares
|
|
124
132
|
for (const mw of routeMiddlewares) {
|
|
125
133
|
const result = await mw(getRequestInfo());
|
|
126
134
|
const handled = await handleMiddlewareResult(result);
|
|
@@ -128,7 +136,7 @@ export function defineRoutes(routes) {
|
|
|
128
136
|
return handled;
|
|
129
137
|
}
|
|
130
138
|
}
|
|
131
|
-
//
|
|
139
|
+
// Final component/handler
|
|
132
140
|
if (isRouteComponent(componentHandler)) {
|
|
133
141
|
const requestInfo = getRequestInfo();
|
|
134
142
|
const WrappedComponent = wrapWithLayouts(wrapHandlerToThrowResponses(componentHandler), route.layouts || [], requestInfo);
|
|
@@ -148,7 +156,11 @@ export function defineRoutes(routes) {
|
|
|
148
156
|
});
|
|
149
157
|
});
|
|
150
158
|
}
|
|
151
|
-
//
|
|
159
|
+
// If we've gotten this far, no route was matched.
|
|
160
|
+
// We still need to handle a possible action if the app has no route definitions at all.
|
|
161
|
+
if (!firstRouteDefinitionEncountered) {
|
|
162
|
+
await handleAction();
|
|
163
|
+
}
|
|
152
164
|
return new Response("Not Found", { status: 404 });
|
|
153
165
|
},
|
|
154
166
|
};
|
|
@@ -168,8 +180,14 @@ export function index(handler) {
|
|
|
168
180
|
export function prefix(prefixPath, routes) {
|
|
169
181
|
return routes.map((r) => {
|
|
170
182
|
if (typeof r === "function") {
|
|
171
|
-
|
|
172
|
-
|
|
183
|
+
const middleware = (requestInfo) => {
|
|
184
|
+
const url = new URL(requestInfo.request.url);
|
|
185
|
+
if (url.pathname.startsWith(prefixPath)) {
|
|
186
|
+
return r(requestInfo);
|
|
187
|
+
}
|
|
188
|
+
return;
|
|
189
|
+
};
|
|
190
|
+
return middleware;
|
|
173
191
|
}
|
|
174
192
|
if (Array.isArray(r)) {
|
|
175
193
|
// Recursively process nested route arrays
|