rwsdk 0.1.23 → 0.1.25
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/normalizeModulePath.d.mts +26 -0
- package/dist/lib/normalizeModulePath.mjs +101 -0
- package/dist/lib/normalizeModulePath.test.d.ts +1 -0
- package/dist/lib/normalizeModulePath.test.js +203 -0
- package/dist/runtime/client.d.ts +3 -1
- package/dist/runtime/client.js +23 -3
- package/dist/runtime/clientNavigation.d.ts +3 -1
- package/dist/runtime/clientNavigation.js +11 -0
- package/dist/runtime/lib/realtime/client.d.ts +4 -2
- package/dist/runtime/lib/realtime/client.js +133 -100
- package/dist/runtime/lib/realtime/durableObject.d.ts +1 -0
- package/dist/runtime/lib/realtime/durableObject.js +42 -34
- package/dist/runtime/lib/realtime/protocol.d.ts +50 -0
- package/dist/runtime/lib/realtime/protocol.js +141 -0
- package/dist/runtime/lib/realtime/shared.d.ts +8 -8
- package/dist/runtime/lib/realtime/shared.js +4 -4
- package/dist/scripts/debug-sync.mjs +90 -40
- package/dist/vite/createDirectiveLookupPlugin.mjs +2 -2
- package/dist/vite/directivesPlugin.mjs +7 -6
- package/dist/vite/miniflareHMRPlugin.mjs +4 -4
- package/package.json +1 -1
- package/dist/vite/normalizeModulePath.d.mts +0 -1
- package/dist/vite/normalizeModulePath.mjs +0 -13
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize a module path to a consistent form.
|
|
3
|
+
* Returns slash-prefixed paths for files within project root,
|
|
4
|
+
* or absolute paths for external files.
|
|
5
|
+
*
|
|
6
|
+
* Examples:
|
|
7
|
+
* /Users/justin/my-app/src/page.ts → /src/page.ts
|
|
8
|
+
* ../shared/utils.ts → /Users/justin/shared/utils.ts
|
|
9
|
+
* /src/page.ts (Vite-style) → /src/page.ts
|
|
10
|
+
* node_modules/foo/index.js → /node_modules/foo/index.js
|
|
11
|
+
*
|
|
12
|
+
* With { absolute: true }:
|
|
13
|
+
* /Users/justin/my-app/src/page.ts → /Users/justin/my-app/src/page.ts
|
|
14
|
+
*
|
|
15
|
+
* With { isViteStyle: false }:
|
|
16
|
+
* /opt/tools/logger.ts → /opt/tools/logger.ts (treated as external)
|
|
17
|
+
* /src/page.tsx → /src/page.tsx (treated as external)
|
|
18
|
+
*
|
|
19
|
+
* With { isViteStyle: true }:
|
|
20
|
+
* /opt/tools/logger.ts → /opt/tools/logger.ts (resolved as Vite-style)
|
|
21
|
+
* /src/page.tsx, { absolute: true } → /Users/justin/my-app/src/page.tsx
|
|
22
|
+
*/
|
|
23
|
+
export declare function normalizeModulePath(modulePath: string, projectRootDir: string, options?: {
|
|
24
|
+
absolute?: boolean;
|
|
25
|
+
isViteStyle?: boolean;
|
|
26
|
+
}): string;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
import { normalizePath as normalizePathSeparators } from "vite";
|
|
3
|
+
/**
|
|
4
|
+
* Find the number of common ancestor segments between two absolute paths.
|
|
5
|
+
* Returns the count of shared directory segments from the root.
|
|
6
|
+
*/
|
|
7
|
+
function findCommonAncestorDepth(path1, path2) {
|
|
8
|
+
const segments1 = path1.split("/").filter(Boolean);
|
|
9
|
+
const segments2 = path2.split("/").filter(Boolean);
|
|
10
|
+
let commonLength = 0;
|
|
11
|
+
const minLength = Math.min(segments1.length, segments2.length);
|
|
12
|
+
for (let i = 0; i < minLength; i++) {
|
|
13
|
+
if (segments1[i] === segments2[i]) {
|
|
14
|
+
commonLength++;
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return commonLength;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Normalize a module path to a consistent form.
|
|
24
|
+
* Returns slash-prefixed paths for files within project root,
|
|
25
|
+
* or absolute paths for external files.
|
|
26
|
+
*
|
|
27
|
+
* Examples:
|
|
28
|
+
* /Users/justin/my-app/src/page.ts → /src/page.ts
|
|
29
|
+
* ../shared/utils.ts → /Users/justin/shared/utils.ts
|
|
30
|
+
* /src/page.ts (Vite-style) → /src/page.ts
|
|
31
|
+
* node_modules/foo/index.js → /node_modules/foo/index.js
|
|
32
|
+
*
|
|
33
|
+
* With { absolute: true }:
|
|
34
|
+
* /Users/justin/my-app/src/page.ts → /Users/justin/my-app/src/page.ts
|
|
35
|
+
*
|
|
36
|
+
* With { isViteStyle: false }:
|
|
37
|
+
* /opt/tools/logger.ts → /opt/tools/logger.ts (treated as external)
|
|
38
|
+
* /src/page.tsx → /src/page.tsx (treated as external)
|
|
39
|
+
*
|
|
40
|
+
* With { isViteStyle: true }:
|
|
41
|
+
* /opt/tools/logger.ts → /opt/tools/logger.ts (resolved as Vite-style)
|
|
42
|
+
* /src/page.tsx, { absolute: true } → /Users/justin/my-app/src/page.tsx
|
|
43
|
+
*/
|
|
44
|
+
export function normalizeModulePath(modulePath, projectRootDir, options = {}) {
|
|
45
|
+
modulePath = normalizePathSeparators(modulePath);
|
|
46
|
+
projectRootDir = normalizePathSeparators(path.resolve(projectRootDir));
|
|
47
|
+
// Handle empty string or current directory
|
|
48
|
+
if (modulePath === "" || modulePath === ".") {
|
|
49
|
+
return options.absolute ? projectRootDir : "/";
|
|
50
|
+
}
|
|
51
|
+
// For relative paths, resolve them first
|
|
52
|
+
let resolved;
|
|
53
|
+
if (path.isAbsolute(modulePath)) {
|
|
54
|
+
if (modulePath.startsWith(projectRootDir + "/") ||
|
|
55
|
+
modulePath === projectRootDir) {
|
|
56
|
+
// Path starts with project root - it's a real absolute path inside project
|
|
57
|
+
resolved = modulePath;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
// Check how the path relates to the project root
|
|
61
|
+
if (options.isViteStyle !== undefined) {
|
|
62
|
+
// User explicitly specified whether this should be treated as Vite-style
|
|
63
|
+
if (options.isViteStyle) {
|
|
64
|
+
resolved = path.resolve(projectRootDir, modulePath.slice(1));
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
resolved = modulePath;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
// Fall back to heuristics using common ancestor depth
|
|
72
|
+
const commonDepth = findCommonAncestorDepth(modulePath, projectRootDir);
|
|
73
|
+
if (commonDepth > 0) {
|
|
74
|
+
// Paths share meaningful common ancestor - treat as real absolute path
|
|
75
|
+
resolved = modulePath;
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
// No meaningful common ancestor - assume Vite-style path within project
|
|
79
|
+
resolved = path.resolve(projectRootDir, modulePath.slice(1));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
resolved = path.resolve(projectRootDir, modulePath);
|
|
86
|
+
}
|
|
87
|
+
resolved = normalizePathSeparators(resolved);
|
|
88
|
+
// If absolute option is set, always return absolute paths
|
|
89
|
+
if (options.absolute) {
|
|
90
|
+
return resolved;
|
|
91
|
+
}
|
|
92
|
+
// Check if the resolved path is within the project root
|
|
93
|
+
const relative = path.relative(projectRootDir, resolved);
|
|
94
|
+
// If the path goes outside the project root (starts with ..), return absolute
|
|
95
|
+
if (relative.startsWith("..")) {
|
|
96
|
+
return resolved;
|
|
97
|
+
}
|
|
98
|
+
// Path is within project root, return as Vite-style relative path
|
|
99
|
+
const cleanRelative = relative === "." ? "" : relative;
|
|
100
|
+
return "/" + normalizePathSeparators(cleanRelative);
|
|
101
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { normalizeModulePath } from "./normalizeModulePath.mjs";
|
|
3
|
+
describe("normalizeModulePath", () => {
|
|
4
|
+
describe("1. Project-local paths", () => {
|
|
5
|
+
it("Relative file", () => {
|
|
6
|
+
expect(normalizeModulePath("src/page.tsx", "/Users/name/code/my-app")).toBe("/src/page.tsx");
|
|
7
|
+
});
|
|
8
|
+
it("Relative file in subdir", () => {
|
|
9
|
+
expect(normalizeModulePath("src/utils/index.ts", "/Users/name/code/my-app")).toBe("/src/utils/index.ts");
|
|
10
|
+
});
|
|
11
|
+
it("Relative file with ./", () => {
|
|
12
|
+
expect(normalizeModulePath("./src/page.tsx", "/Users/name/code/my-app")).toBe("/src/page.tsx");
|
|
13
|
+
});
|
|
14
|
+
it("Relative file with ../ (external)", () => {
|
|
15
|
+
expect(normalizeModulePath("../shared/foo.ts", "/Users/name/code/my-app")).toBe("/Users/name/code/shared/foo.ts");
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
describe("2. Vite-style absolute paths", () => {
|
|
19
|
+
it("Vite-style root import", () => {
|
|
20
|
+
expect(normalizeModulePath("/src/page.tsx", "/Users/name/code/my-app")).toBe("/src/page.tsx");
|
|
21
|
+
});
|
|
22
|
+
it("Vite-style node_modules", () => {
|
|
23
|
+
expect(normalizeModulePath("/node_modules/foo.js", "/Users/name/code/my-app")).toBe("/node_modules/foo.js");
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
describe("3. Real absolute paths inside project", () => {
|
|
27
|
+
it("Real abs path (inside)", () => {
|
|
28
|
+
expect(normalizeModulePath("/Users/name/code/my-app/src/page.tsx", "/Users/name/code/my-app")).toBe("/src/page.tsx");
|
|
29
|
+
});
|
|
30
|
+
it("Real abs path (deep inside)", () => {
|
|
31
|
+
expect(normalizeModulePath("/Users/name/code/my-app/src/features/auth.ts", "/Users/name/code/my-app")).toBe("/src/features/auth.ts");
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
describe("4. Real absolute paths outside project", () => {
|
|
35
|
+
it("External shared pkg", () => {
|
|
36
|
+
expect(normalizeModulePath("/Users/name/code/my-monorepo/packages/shared/utils.ts", "/Users/name/code/my-monorepo/packages/app")).toBe("/Users/name/code/my-monorepo/packages/shared/utils.ts");
|
|
37
|
+
});
|
|
38
|
+
it("External node_modules", () => {
|
|
39
|
+
expect(normalizeModulePath("/Users/name/code/my-monorepo/node_modules/foo/index.js", "/Users/name/code/my-monorepo/packages/app")).toBe("/Users/name/code/my-monorepo/node_modules/foo/index.js");
|
|
40
|
+
});
|
|
41
|
+
it("Completely external path", () => {
|
|
42
|
+
expect(normalizeModulePath("/opt/tools/logger.ts", "/Users/name/code/my-app")).toBe("/opt/tools/logger.ts");
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
describe("5. Absolute option", () => {
|
|
46
|
+
describe("Project-local paths with absolute option", () => {
|
|
47
|
+
it("Relative file", () => {
|
|
48
|
+
expect(normalizeModulePath("src/page.tsx", "/Users/name/code/my-app", {
|
|
49
|
+
absolute: true,
|
|
50
|
+
})).toBe("/Users/name/code/my-app/src/page.tsx");
|
|
51
|
+
});
|
|
52
|
+
it("Relative file in subdir", () => {
|
|
53
|
+
expect(normalizeModulePath("src/utils/index.ts", "/Users/name/code/my-app", {
|
|
54
|
+
absolute: true,
|
|
55
|
+
})).toBe("/Users/name/code/my-app/src/utils/index.ts");
|
|
56
|
+
});
|
|
57
|
+
it("Relative file with ./", () => {
|
|
58
|
+
expect(normalizeModulePath("./src/page.tsx", "/Users/name/code/my-app", {
|
|
59
|
+
absolute: true,
|
|
60
|
+
})).toBe("/Users/name/code/my-app/src/page.tsx");
|
|
61
|
+
});
|
|
62
|
+
it("Relative file with ../ (external)", () => {
|
|
63
|
+
expect(normalizeModulePath("../shared/foo.ts", "/Users/name/code/my-app", {
|
|
64
|
+
absolute: true,
|
|
65
|
+
})).toBe("/Users/name/code/shared/foo.ts");
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
describe("Vite-style absolute paths with absolute option", () => {
|
|
69
|
+
it("Vite-style root import", () => {
|
|
70
|
+
expect(normalizeModulePath("/src/page.tsx", "/Users/name/code/my-app", {
|
|
71
|
+
absolute: true,
|
|
72
|
+
})).toBe("/Users/name/code/my-app/src/page.tsx");
|
|
73
|
+
});
|
|
74
|
+
it("Vite-style node_modules", () => {
|
|
75
|
+
expect(normalizeModulePath("/node_modules/foo.js", "/Users/name/code/my-app", { absolute: true })).toBe("/Users/name/code/my-app/node_modules/foo.js");
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
describe("Real absolute paths with absolute option", () => {
|
|
79
|
+
it("Real abs path (inside)", () => {
|
|
80
|
+
expect(normalizeModulePath("/Users/name/code/my-app/src/page.tsx", "/Users/name/code/my-app", { absolute: true })).toBe("/Users/name/code/my-app/src/page.tsx");
|
|
81
|
+
});
|
|
82
|
+
it("Real abs path (deep inside)", () => {
|
|
83
|
+
expect(normalizeModulePath("/Users/name/code/my-app/src/features/auth.ts", "/Users/name/code/my-app", { absolute: true })).toBe("/Users/name/code/my-app/src/features/auth.ts");
|
|
84
|
+
});
|
|
85
|
+
it("External shared pkg", () => {
|
|
86
|
+
expect(normalizeModulePath("/Users/name/code/my-monorepo/packages/shared/utils.ts", "/Users/name/code/my-monorepo/packages/app", { absolute: true })).toBe("/Users/name/code/my-monorepo/packages/shared/utils.ts");
|
|
87
|
+
});
|
|
88
|
+
it("External node_modules", () => {
|
|
89
|
+
expect(normalizeModulePath("/Users/name/code/my-monorepo/node_modules/foo/index.js", "/Users/name/code/my-monorepo/packages/app", { absolute: true })).toBe("/Users/name/code/my-monorepo/node_modules/foo/index.js");
|
|
90
|
+
});
|
|
91
|
+
it("Completely external path", () => {
|
|
92
|
+
expect(normalizeModulePath("/opt/tools/logger.ts", "/Users/name/code/my-app", {
|
|
93
|
+
absolute: true,
|
|
94
|
+
isViteStyle: false,
|
|
95
|
+
})).toBe("/opt/tools/logger.ts");
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
describe("Edge cases with absolute option", () => {
|
|
99
|
+
it("Empty string", () => {
|
|
100
|
+
expect(normalizeModulePath("", "/Users/name/code/my-app", {
|
|
101
|
+
absolute: true,
|
|
102
|
+
})).toBe("/Users/name/code/my-app");
|
|
103
|
+
});
|
|
104
|
+
it("Dot current dir", () => {
|
|
105
|
+
expect(normalizeModulePath(".", "/Users/name/code/my-app", {
|
|
106
|
+
absolute: true,
|
|
107
|
+
})).toBe("/Users/name/code/my-app");
|
|
108
|
+
});
|
|
109
|
+
it("Dot parent dir", () => {
|
|
110
|
+
expect(normalizeModulePath("..", "/Users/name/code/my-app", {
|
|
111
|
+
absolute: true,
|
|
112
|
+
})).toBe("/Users/name/code");
|
|
113
|
+
});
|
|
114
|
+
it("Trailing slash", () => {
|
|
115
|
+
expect(normalizeModulePath("src/", "/Users/name/code/my-app", {
|
|
116
|
+
absolute: true,
|
|
117
|
+
})).toBe("/Users/name/code/my-app/src");
|
|
118
|
+
});
|
|
119
|
+
it("Leading and trailing slashes", () => {
|
|
120
|
+
expect(normalizeModulePath("/src/", "/Users/name/code/my-app", {
|
|
121
|
+
absolute: true,
|
|
122
|
+
})).toBe("/Users/name/code/my-app/src");
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
describe("Project root is / with absolute option", () => {
|
|
126
|
+
it("Root-based path", () => {
|
|
127
|
+
expect(normalizeModulePath("/src/index.ts", "/", { absolute: true })).toBe("/src/index.ts");
|
|
128
|
+
});
|
|
129
|
+
it("System path", () => {
|
|
130
|
+
expect(normalizeModulePath("/etc/hosts", "/", { absolute: true })).toBe("/etc/hosts");
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
describe("6. Edge and weird cases", () => {
|
|
135
|
+
it("Empty string", () => {
|
|
136
|
+
expect(normalizeModulePath("", "/Users/name/code/my-app")).toBe("/");
|
|
137
|
+
});
|
|
138
|
+
it("Dot current dir", () => {
|
|
139
|
+
expect(normalizeModulePath(".", "/Users/name/code/my-app")).toBe("/");
|
|
140
|
+
});
|
|
141
|
+
it("Dot parent dir", () => {
|
|
142
|
+
expect(normalizeModulePath("..", "/Users/name/code/my-app")).toBe("/Users/name/code");
|
|
143
|
+
});
|
|
144
|
+
it("Trailing slash", () => {
|
|
145
|
+
expect(normalizeModulePath("src/", "/Users/name/code/my-app")).toBe("/src");
|
|
146
|
+
});
|
|
147
|
+
it("Leading and trailing slashes", () => {
|
|
148
|
+
expect(normalizeModulePath("/src/", "/Users/name/code/my-app")).toBe("/src");
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
describe("7. Project root is /", () => {
|
|
152
|
+
it("Root-based path", () => {
|
|
153
|
+
expect(normalizeModulePath("/src/index.ts", "/")).toBe("/src/index.ts");
|
|
154
|
+
});
|
|
155
|
+
it("System path", () => {
|
|
156
|
+
expect(normalizeModulePath("/etc/hosts", "/")).toBe("/etc/hosts");
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
describe("8. isViteStyle option", () => {
|
|
160
|
+
describe("isViteStyle: false (treat as external)", () => {
|
|
161
|
+
it("System path that would normally be Vite-style", () => {
|
|
162
|
+
expect(normalizeModulePath("/opt/tools/logger.ts", "/Users/name/code/my-app", {
|
|
163
|
+
isViteStyle: false,
|
|
164
|
+
})).toBe("/opt/tools/logger.ts");
|
|
165
|
+
});
|
|
166
|
+
it("Src path with isViteStyle: false", () => {
|
|
167
|
+
expect(normalizeModulePath("/src/page.tsx", "/Users/name/code/my-app", {
|
|
168
|
+
isViteStyle: false,
|
|
169
|
+
})).toBe("/src/page.tsx");
|
|
170
|
+
});
|
|
171
|
+
it("With absolute option", () => {
|
|
172
|
+
expect(normalizeModulePath("/opt/tools/logger.ts", "/Users/name/code/my-app", {
|
|
173
|
+
absolute: true,
|
|
174
|
+
isViteStyle: false,
|
|
175
|
+
})).toBe("/opt/tools/logger.ts");
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
describe("isViteStyle: true (force Vite-style)", () => {
|
|
179
|
+
it("System path forced to Vite-style", () => {
|
|
180
|
+
expect(normalizeModulePath("/opt/tools/logger.ts", "/Users/name/code/my-app", {
|
|
181
|
+
isViteStyle: true,
|
|
182
|
+
})).toBe("/opt/tools/logger.ts");
|
|
183
|
+
});
|
|
184
|
+
it("Src path with isViteStyle: true", () => {
|
|
185
|
+
expect(normalizeModulePath("/src/page.tsx", "/Users/name/code/my-app", {
|
|
186
|
+
isViteStyle: true,
|
|
187
|
+
})).toBe("/src/page.tsx");
|
|
188
|
+
});
|
|
189
|
+
it("With absolute option", () => {
|
|
190
|
+
expect(normalizeModulePath("/src/page.tsx", "/Users/name/code/my-app", {
|
|
191
|
+
absolute: true,
|
|
192
|
+
isViteStyle: true,
|
|
193
|
+
})).toBe("/Users/name/code/my-app/src/page.tsx");
|
|
194
|
+
});
|
|
195
|
+
it("System path forced to Vite-style with absolute option", () => {
|
|
196
|
+
expect(normalizeModulePath("/opt/tools/logger.ts", "/Users/name/code/my-app", {
|
|
197
|
+
absolute: true,
|
|
198
|
+
isViteStyle: true,
|
|
199
|
+
})).toBe("/Users/name/code/my-app/opt/tools/logger.ts");
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
});
|
package/dist/runtime/client.d.ts
CHANGED
|
@@ -6,12 +6,14 @@ export type ActionResponse<Result> = {
|
|
|
6
6
|
};
|
|
7
7
|
type TransportContext = {
|
|
8
8
|
setRscPayload: <Result>(v: Promise<ActionResponse<Result>>) => void;
|
|
9
|
+
handleResponse?: (response: Response) => boolean;
|
|
9
10
|
};
|
|
10
11
|
export type Transport = (context: TransportContext) => CallServerCallback;
|
|
11
12
|
export type CreateCallServer = (context: TransportContext) => <Result>(id: null | string, args: null | unknown[]) => Promise<Result>;
|
|
12
13
|
export declare const fetchTransport: Transport;
|
|
13
|
-
export declare const initClient: ({ transport, hydrateRootOptions, }?: {
|
|
14
|
+
export declare const initClient: ({ transport, hydrateRootOptions, handleResponse, }?: {
|
|
14
15
|
transport?: Transport;
|
|
15
16
|
hydrateRootOptions?: HydrationOptions;
|
|
17
|
+
handleResponse?: (response: Response) => boolean;
|
|
16
18
|
}) => Promise<void>;
|
|
17
19
|
export {};
|
package/dist/runtime/client.js
CHANGED
|
@@ -11,21 +11,41 @@ export const fetchTransport = (transportContext) => {
|
|
|
11
11
|
if (id != null) {
|
|
12
12
|
url.searchParams.set("__rsc_action_id", id);
|
|
13
13
|
}
|
|
14
|
-
const
|
|
14
|
+
const fetchPromise = fetch(url, {
|
|
15
15
|
method: "POST",
|
|
16
16
|
body: args != null ? await encodeReply(args) : null,
|
|
17
|
-
})
|
|
17
|
+
});
|
|
18
|
+
// If there's a response handler, check the response first
|
|
19
|
+
if (transportContext.handleResponse) {
|
|
20
|
+
const response = await fetchPromise;
|
|
21
|
+
const shouldContinue = transportContext.handleResponse(response);
|
|
22
|
+
if (!shouldContinue) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
// Continue with the response if handler returned true
|
|
26
|
+
const streamData = createFromFetch(Promise.resolve(response), {
|
|
27
|
+
callServer: fetchCallServer,
|
|
28
|
+
});
|
|
29
|
+
transportContext.setRscPayload(streamData);
|
|
30
|
+
const result = await streamData;
|
|
31
|
+
return result.actionResult;
|
|
32
|
+
}
|
|
33
|
+
// Original behavior when no handler is present
|
|
34
|
+
const streamData = createFromFetch(fetchPromise, {
|
|
35
|
+
callServer: fetchCallServer,
|
|
36
|
+
});
|
|
18
37
|
transportContext.setRscPayload(streamData);
|
|
19
38
|
const result = await streamData;
|
|
20
39
|
return result.actionResult;
|
|
21
40
|
};
|
|
22
41
|
return fetchCallServer;
|
|
23
42
|
};
|
|
24
|
-
export const initClient = async ({ transport = fetchTransport, hydrateRootOptions, } = {}) => {
|
|
43
|
+
export const initClient = async ({ transport = fetchTransport, hydrateRootOptions, handleResponse, } = {}) => {
|
|
25
44
|
const React = await import("react");
|
|
26
45
|
const { hydrateRoot } = await import("react-dom/client");
|
|
27
46
|
const transportContext = {
|
|
28
47
|
setRscPayload: () => { },
|
|
48
|
+
handleResponse,
|
|
29
49
|
};
|
|
30
50
|
let transportCallServer = transport(transportContext);
|
|
31
51
|
const callServer = (id, args) => transportCallServer(id, args);
|
|
@@ -50,4 +50,15 @@ export function initClientNavigation(opts = {
|
|
|
50
50
|
window.addEventListener("popstate", async function handlePopState() {
|
|
51
51
|
await opts.onNavigate();
|
|
52
52
|
});
|
|
53
|
+
// Return a handleResponse function for use with initClient
|
|
54
|
+
return {
|
|
55
|
+
handleResponse: function handleResponse(response) {
|
|
56
|
+
if (!response.ok) {
|
|
57
|
+
// Redirect to the current page (window.location) to show the error
|
|
58
|
+
window.location.href = window.location.href;
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
return true;
|
|
62
|
+
},
|
|
63
|
+
};
|
|
53
64
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { type Transport } from "../../client";
|
|
2
|
-
export declare const initRealtimeClient: ({ key, }?: {
|
|
2
|
+
export declare const initRealtimeClient: ({ key, handleResponse, }?: {
|
|
3
3
|
key?: string;
|
|
4
|
+
handleResponse?: (response: Response) => boolean;
|
|
4
5
|
}) => Promise<void>;
|
|
5
|
-
export declare const realtimeTransport: ({ key }: {
|
|
6
|
+
export declare const realtimeTransport: ({ key, handleResponse, }: {
|
|
6
7
|
key?: string;
|
|
8
|
+
handleResponse?: (response: Response) => boolean;
|
|
7
9
|
}) => Transport;
|