dinou 4.0.13 → 4.0.14
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/CHANGELOG.md +6 -0
- package/dinou/core/client-error-webpack.jsx +2 -2
- package/dinou/core/client-error.jsx +2 -2
- package/dinou/core/client-redirect.jsx +11 -4
- package/dinou/core/client-webpack.jsx +28 -17
- package/dinou/core/client.jsx +28 -17
- package/dinou/core/link.jsx +3 -3
- package/dinou/core/navigation-utils.js +31 -0
- package/dinou/core/server-function-proxy-webpack.js +17 -11
- package/dinou/core/server-function-proxy.js +17 -10
- package/dinou/package.json +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
7
7
|
|
|
8
|
+
## [4.0.14] - 2026-06-29
|
|
9
|
+
### Added
|
|
10
|
+
- **Soft Redirects**: Exposes the SPA transition navigation internally via `window.__DINOU_ROUTER_NAVIGATE__` to enable smooth client-side redirects from both Server Functions and RSC payloads, keeping the React client state intact and preventing full browser page reloads.
|
|
11
|
+
### Fixed
|
|
12
|
+
- **External Links Interception**: Restored native browser navigation for external domains, protocol-relative links (`//...`), and special protocols (`mailto:`, `tel:`, etc.) by preventing the SPA router from capturing or prefetching non-internal routes.
|
|
13
|
+
|
|
8
14
|
## [4.0.13] - 2026-06-29
|
|
9
15
|
|
|
10
16
|
### Added
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import { createFromFetch } from "react-server-dom-webpack/client";
|
|
10
10
|
import { hydrateRoot } from "react-dom/client";
|
|
11
11
|
import { RouterContext } from "./navigation.js";
|
|
12
|
-
import { resolveUrl } from "./navigation-utils.js";
|
|
12
|
+
import { resolveUrl, isExternalUrl } from "./navigation-utils.js";
|
|
13
13
|
|
|
14
14
|
// ====================================================================
|
|
15
15
|
// 1. GLOBAL STATE (Outside the component)
|
|
@@ -167,7 +167,7 @@ function Router() {
|
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
const href = anchor.getAttribute("href");
|
|
170
|
-
if (!href || href.startsWith("mailto:") || href.startsWith("tel:"))
|
|
170
|
+
if (!href || href.startsWith("mailto:") || href.startsWith("tel:") || isExternalUrl(href))
|
|
171
171
|
return;
|
|
172
172
|
|
|
173
173
|
// We use the unified helper
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import { createFromFetch } from "@roggc/react-server-dom-esm/client";
|
|
10
10
|
import { hydrateRoot } from "react-dom/client";
|
|
11
11
|
import { RouterContext } from "./navigation.js";
|
|
12
|
-
import { resolveUrl } from "./navigation-utils.js";
|
|
12
|
+
import { resolveUrl, isExternalUrl } from "./navigation-utils.js";
|
|
13
13
|
|
|
14
14
|
// ====================================================================
|
|
15
15
|
// 1. GLOBAL STATE (Outside the component)
|
|
@@ -167,7 +167,7 @@ function Router() {
|
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
const href = anchor.getAttribute("href");
|
|
170
|
-
if (!href || href.startsWith("mailto:") || href.startsWith("tel:"))
|
|
170
|
+
if (!href || href.startsWith("mailto:") || href.startsWith("tel:") || isExternalUrl(href))
|
|
171
171
|
return;
|
|
172
172
|
|
|
173
173
|
// We use the unified helper
|
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
// dinou/core/client-redirect.jsx
|
|
2
2
|
"use client";
|
|
3
3
|
|
|
4
|
-
import { useEffect } from "react";
|
|
5
4
|
import { useRouter } from "./navigation.js";
|
|
6
5
|
|
|
7
6
|
export function ClientRedirect({ to }) {
|
|
8
7
|
const router = useRouter();
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
if (typeof window !== "undefined") {
|
|
10
|
+
Promise.resolve().then(() => {
|
|
11
|
+
if (window.__DINOU_ROUTER_NAVIGATE__) {
|
|
12
|
+
window.__DINOU_ROUTER_NAVIGATE__(to, { replace: true });
|
|
13
|
+
} else {
|
|
14
|
+
router.replace(to);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
// Suspend to prevent React from committing this intermediate page
|
|
18
|
+
throw new Promise(() => {});
|
|
19
|
+
}
|
|
13
20
|
|
|
14
21
|
return null;
|
|
15
22
|
}
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import { createFromFetch } from "react-server-dom-webpack/client";
|
|
10
10
|
import { hydrateRoot } from "react-dom/client";
|
|
11
11
|
import { RouterContext } from "./navigation.js";
|
|
12
|
-
import { resolveUrl } from "./navigation-utils.js";
|
|
12
|
+
import { resolveUrl, isExternalUrl } from "./navigation-utils.js";
|
|
13
13
|
|
|
14
14
|
// ====================================================================
|
|
15
15
|
// 1. GLOBAL STATE (Outside the component)
|
|
@@ -68,10 +68,13 @@ const getRSCPayload = (rscKey, isPrefetch = false) => {
|
|
|
68
68
|
fetch(payloadUrl).then((res) => {
|
|
69
69
|
if (res.headers.has("x-rsc-redirect")) {
|
|
70
70
|
const redirectUrl = res.headers.get("x-rsc-redirect");
|
|
71
|
+
cache.delete(url);
|
|
71
72
|
if (!isPrefetch) {
|
|
72
|
-
window.
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
if (window.__DINOU_ROUTER_NAVIGATE__) {
|
|
74
|
+
window.__DINOU_ROUTER_NAVIGATE__(redirectUrl, { replace: true });
|
|
75
|
+
} else {
|
|
76
|
+
window.location.href = redirectUrl;
|
|
77
|
+
}
|
|
75
78
|
}
|
|
76
79
|
// Return a promise that never resolves to avoid React Server DOM throwing "Connection closed"
|
|
77
80
|
return new Promise(() => {});
|
|
@@ -93,18 +96,6 @@ function Router() {
|
|
|
93
96
|
const [isPending, startTransition] = useTransition();
|
|
94
97
|
const [version, setVersion] = useState(0);
|
|
95
98
|
|
|
96
|
-
// 🔌 EFFECT 1: Expose Global Prefetch
|
|
97
|
-
useEffect(() => {
|
|
98
|
-
window.__DINOU_PREFETCH__ = (url) => {
|
|
99
|
-
// 🛡️ PREFETCH PROTECTION: If it's a local hash, do nothing
|
|
100
|
-
if (isHashChangeOnly(url)) return;
|
|
101
|
-
getRSCPayload(url, true);
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
// Hydration
|
|
105
|
-
document.body.setAttribute("data-hydrated", "true");
|
|
106
|
-
}, []); // Only on mount
|
|
107
|
-
|
|
108
99
|
// 🧭 NAVIGATE FUNCTION (Core Logic)
|
|
109
100
|
const navigate = (href, options = {}) => {
|
|
110
101
|
const finalPath = resolveUrl(href, window.location.pathname);
|
|
@@ -150,6 +141,26 @@ function Router() {
|
|
|
150
141
|
});
|
|
151
142
|
};
|
|
152
143
|
|
|
144
|
+
// 🔌 EFFECT 1: Expose Global Prefetch & Navigation
|
|
145
|
+
useEffect(() => {
|
|
146
|
+
window.__DINOU_PREFETCH__ = (url) => {
|
|
147
|
+
// 🛡️ PREFETCH PROTECTION: If it's a local hash, do nothing
|
|
148
|
+
if (isHashChangeOnly(url)) return;
|
|
149
|
+
getRSCPayload(url, true);
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
window.__DINOU_ROUTER_NAVIGATE__ = navigate;
|
|
153
|
+
|
|
154
|
+
// Hydration
|
|
155
|
+
document.body.setAttribute("data-hydrated", "true");
|
|
156
|
+
|
|
157
|
+
return () => {
|
|
158
|
+
if (window.__DINOU_ROUTER_NAVIGATE__ === navigate) {
|
|
159
|
+
window.__DINOU_ROUTER_NAVIGATE__ = undefined;
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
}, [navigate]);
|
|
163
|
+
|
|
153
164
|
const back = () => window.history.back();
|
|
154
165
|
const forward = () => window.history.forward();
|
|
155
166
|
const refresh = () => {
|
|
@@ -188,7 +199,7 @@ function Router() {
|
|
|
188
199
|
}
|
|
189
200
|
|
|
190
201
|
const href = anchor.getAttribute("href");
|
|
191
|
-
if (!href || href.startsWith("mailto:") || href.startsWith("tel:"))
|
|
202
|
+
if (!href || href.startsWith("mailto:") || href.startsWith("tel:") || isExternalUrl(href))
|
|
192
203
|
return;
|
|
193
204
|
|
|
194
205
|
// We use the unified helper
|
package/dinou/core/client.jsx
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
import { createFromFetch } from "@roggc/react-server-dom-esm/client";
|
|
11
11
|
import { hydrateRoot } from "react-dom/client";
|
|
12
12
|
import { RouterContext } from "./navigation.js";
|
|
13
|
-
import { resolveUrl } from "./navigation-utils.js";
|
|
13
|
+
import { resolveUrl, isExternalUrl } from "./navigation-utils.js";
|
|
14
14
|
|
|
15
15
|
// ====================================================================
|
|
16
16
|
// 1. GLOBAL STATE (Outside the component)
|
|
@@ -69,10 +69,13 @@ const getRSCPayload = (rscKey, isPrefetch = false) => {
|
|
|
69
69
|
fetch(payloadUrl).then((res) => {
|
|
70
70
|
if (res.headers.has("x-rsc-redirect")) {
|
|
71
71
|
const redirectUrl = res.headers.get("x-rsc-redirect");
|
|
72
|
+
cache.delete(url);
|
|
72
73
|
if (!isPrefetch) {
|
|
73
|
-
window.
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
if (window.__DINOU_ROUTER_NAVIGATE__) {
|
|
75
|
+
window.__DINOU_ROUTER_NAVIGATE__(redirectUrl, { replace: true });
|
|
76
|
+
} else {
|
|
77
|
+
window.location.href = redirectUrl;
|
|
78
|
+
}
|
|
76
79
|
}
|
|
77
80
|
// Return a promise that never resolves to avoid React Server DOM throwing "Connection closed"
|
|
78
81
|
return new Promise(() => {});
|
|
@@ -94,18 +97,6 @@ function Router() {
|
|
|
94
97
|
const [isPending, startTransition] = useTransition();
|
|
95
98
|
const [version, setVersion] = useState(0);
|
|
96
99
|
|
|
97
|
-
// 🔌 EFFECT 1: Expose Global Prefetch
|
|
98
|
-
useEffect(() => {
|
|
99
|
-
window.__DINOU_PREFETCH__ = (url) => {
|
|
100
|
-
// 🛡️ PREFETCH PROTECTION: If it's a local hash, do nothing
|
|
101
|
-
if (isHashChangeOnly(url)) return;
|
|
102
|
-
getRSCPayload(url, true);
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
// Hydration
|
|
106
|
-
document.body.setAttribute("data-hydrated", "true");
|
|
107
|
-
}, []); // Only on mount
|
|
108
|
-
|
|
109
100
|
// 🧭 NAVIGATE FUNCTION (Core Logic)
|
|
110
101
|
const navigate = (href, options = {}) => {
|
|
111
102
|
const finalPath = resolveUrl(href, window.location.pathname);
|
|
@@ -151,6 +142,26 @@ function Router() {
|
|
|
151
142
|
});
|
|
152
143
|
};
|
|
153
144
|
|
|
145
|
+
// 🔌 EFFECT 1: Expose Global Prefetch & Navigation
|
|
146
|
+
useEffect(() => {
|
|
147
|
+
window.__DINOU_PREFETCH__ = (url) => {
|
|
148
|
+
// 🛡️ PREFETCH PROTECTION: If it's a local hash, do nothing
|
|
149
|
+
if (isHashChangeOnly(url)) return;
|
|
150
|
+
getRSCPayload(url, true);
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
window.__DINOU_ROUTER_NAVIGATE__ = navigate;
|
|
154
|
+
|
|
155
|
+
// Hydration
|
|
156
|
+
document.body.setAttribute("data-hydrated", "true");
|
|
157
|
+
|
|
158
|
+
return () => {
|
|
159
|
+
if (window.__DINOU_ROUTER_NAVIGATE__ === navigate) {
|
|
160
|
+
window.__DINOU_ROUTER_NAVIGATE__ = undefined;
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
}, [navigate]);
|
|
164
|
+
|
|
154
165
|
const back = () => window.history.back();
|
|
155
166
|
const forward = () => window.history.forward();
|
|
156
167
|
const refresh = () => {
|
|
@@ -189,7 +200,7 @@ function Router() {
|
|
|
189
200
|
}
|
|
190
201
|
|
|
191
202
|
const href = anchor.getAttribute("href");
|
|
192
|
-
if (!href || href.startsWith("mailto:") || href.startsWith("tel:"))
|
|
203
|
+
if (!href || href.startsWith("mailto:") || href.startsWith("tel:") || isExternalUrl(href))
|
|
193
204
|
return;
|
|
194
205
|
|
|
195
206
|
// We use the unified helper
|
package/dinou/core/link.jsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { useRouter, usePathname } from "./navigation.js";
|
|
4
|
-
import { resolveUrl } from "./navigation-utils.js";
|
|
4
|
+
import { resolveUrl, isExternalUrl } from "./navigation-utils.js";
|
|
5
5
|
|
|
6
6
|
export function Link({
|
|
7
7
|
href,
|
|
@@ -15,14 +15,14 @@ export function Link({
|
|
|
15
15
|
const resolvedHref = resolveUrl(href, pathname);
|
|
16
16
|
|
|
17
17
|
const handlePrefetch = () => {
|
|
18
|
-
if (!prefetch || !href || fresh) return;
|
|
18
|
+
if (!prefetch || !href || fresh || isExternalUrl(href)) return;
|
|
19
19
|
if (window.__DINOU_PREFETCH__) {
|
|
20
20
|
window.__DINOU_PREFETCH__(resolvedHref);
|
|
21
21
|
}
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
const handleClick = (e) => {
|
|
25
|
-
if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
|
|
25
|
+
if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || isExternalUrl(href)) return;
|
|
26
26
|
|
|
27
27
|
e.preventDefault();
|
|
28
28
|
push(href, { fresh });
|
|
@@ -1,4 +1,35 @@
|
|
|
1
|
+
export function isExternalUrl(href) {
|
|
2
|
+
if (!href) return false;
|
|
3
|
+
|
|
4
|
+
// Protocol-relative (e.g. //google.com)
|
|
5
|
+
if (href.startsWith("//")) {
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// Absolute with protocol (e.g. https://google.com)
|
|
10
|
+
if (href.includes("://")) {
|
|
11
|
+
try {
|
|
12
|
+
const origin = typeof window !== "undefined" ? window.location.origin : "http://localhost";
|
|
13
|
+
const url = new URL(href, origin);
|
|
14
|
+
return url.origin !== origin;
|
|
15
|
+
} catch (e) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Other protocols (mailto:, tel:, javascript:, etc.)
|
|
21
|
+
if (/^[a-zA-Z0-9+-.]+:[^//]/.test(href) || href.startsWith("mailto:") || href.startsWith("tel:") || href.startsWith("javascript:")) {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
|
|
1
28
|
export function resolveUrl(href, currentPathname) {
|
|
29
|
+
if (isExternalUrl(href)) {
|
|
30
|
+
return href;
|
|
31
|
+
}
|
|
32
|
+
|
|
2
33
|
const origin = typeof window !== "undefined" ? window.location.origin : "http://localhost";
|
|
3
34
|
|
|
4
35
|
if (href.startsWith("/") || href.includes("://")) {
|
|
@@ -4,6 +4,16 @@ function isSafeRedirect(url) {
|
|
|
4
4
|
return typeof url === "string" && url.startsWith("/") && !url.startsWith("//");
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
+
function executeRedirect(url) {
|
|
8
|
+
const safeUrl = isSafeRedirect(url) ? url : "/";
|
|
9
|
+
const isInternal = safeUrl.startsWith("/") && !safeUrl.startsWith("//");
|
|
10
|
+
if (isInternal && typeof window !== "undefined" && window.__DINOU_ROUTER_NAVIGATE__) {
|
|
11
|
+
window.__DINOU_ROUTER_NAVIGATE__(safeUrl);
|
|
12
|
+
} else if (typeof window !== "undefined") {
|
|
13
|
+
window.location.href = safeUrl;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
7
17
|
function createServerFunctionProxy(id) {
|
|
8
18
|
return new Proxy(() => { }, {
|
|
9
19
|
apply: async (_target, _thisArg, args) => {
|
|
@@ -37,8 +47,8 @@ function createServerFunctionProxy(id) {
|
|
|
37
47
|
// Check header first
|
|
38
48
|
const redirectUrl = res.headers.get("X-Dinou-Redirect");
|
|
39
49
|
if (redirectUrl) {
|
|
40
|
-
|
|
41
|
-
return
|
|
50
|
+
executeRedirect(redirectUrl);
|
|
51
|
+
return Promise.resolve();
|
|
42
52
|
}
|
|
43
53
|
|
|
44
54
|
const contentType = res.headers.get("content-type") || "";
|
|
@@ -54,8 +64,8 @@ function createServerFunctionProxy(id) {
|
|
|
54
64
|
if (contentType.includes("application/json")) {
|
|
55
65
|
const data = await res.json();
|
|
56
66
|
if (data && data.redirect) {
|
|
57
|
-
|
|
58
|
-
return
|
|
67
|
+
executeRedirect(data.redirect);
|
|
68
|
+
return Promise.resolve();
|
|
59
69
|
}
|
|
60
70
|
return data;
|
|
61
71
|
}
|
|
@@ -82,7 +92,7 @@ function createServerFunctionProxy(id) {
|
|
|
82
92
|
const payload = JSON.parse(buffer.slice(2));
|
|
83
93
|
if (payload.type === "redirect") {
|
|
84
94
|
isRedirecting = true;
|
|
85
|
-
|
|
95
|
+
executeRedirect(payload.url);
|
|
86
96
|
} else if (payload.type === "cookie") {
|
|
87
97
|
document.cookie = payload.cookie;
|
|
88
98
|
}
|
|
@@ -119,7 +129,7 @@ function createServerFunctionProxy(id) {
|
|
|
119
129
|
const payload = JSON.parse(line.slice(2));
|
|
120
130
|
if (payload.type === "redirect") {
|
|
121
131
|
isRedirecting = true;
|
|
122
|
-
|
|
132
|
+
executeRedirect(payload.url);
|
|
123
133
|
} else if (payload.type === "cookie") {
|
|
124
134
|
document.cookie = payload.cookie;
|
|
125
135
|
}
|
|
@@ -130,18 +140,14 @@ function createServerFunctionProxy(id) {
|
|
|
130
140
|
cleanChunk += line + "\n";
|
|
131
141
|
}
|
|
132
142
|
}
|
|
133
|
-
|
|
134
143
|
if (cleanChunk) {
|
|
135
144
|
controller.enqueue(encoder.encode(cleanChunk));
|
|
136
145
|
}
|
|
137
146
|
}
|
|
138
147
|
}
|
|
148
|
+
controller.close();
|
|
139
149
|
} catch (err) {
|
|
140
150
|
controller.error(err);
|
|
141
|
-
} finally {
|
|
142
|
-
if (!isRedirecting) {
|
|
143
|
-
controller.close();
|
|
144
|
-
}
|
|
145
151
|
}
|
|
146
152
|
},
|
|
147
153
|
});
|
|
@@ -5,6 +5,16 @@ function isSafeRedirect(url) {
|
|
|
5
5
|
return typeof url === "string" && url.startsWith("/") && !url.startsWith("//");
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
function executeRedirect(url) {
|
|
9
|
+
const safeUrl = isSafeRedirect(url) ? url : "/";
|
|
10
|
+
const isInternal = safeUrl.startsWith("/") && !safeUrl.startsWith("//");
|
|
11
|
+
if (isInternal && typeof window !== "undefined" && window.__DINOU_ROUTER_NAVIGATE__) {
|
|
12
|
+
window.__DINOU_ROUTER_NAVIGATE__(safeUrl);
|
|
13
|
+
} else if (typeof window !== "undefined") {
|
|
14
|
+
window.location.href = safeUrl;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
8
18
|
export function createServerFunctionProxy(id) {
|
|
9
19
|
return new Proxy(() => {}, {
|
|
10
20
|
apply: async (_target, _thisArg, args) => {
|
|
@@ -38,8 +48,8 @@ export function createServerFunctionProxy(id) {
|
|
|
38
48
|
// Check header first
|
|
39
49
|
const redirectUrl = res.headers.get("X-Dinou-Redirect");
|
|
40
50
|
if (redirectUrl) {
|
|
41
|
-
|
|
42
|
-
return
|
|
51
|
+
executeRedirect(redirectUrl);
|
|
52
|
+
return Promise.resolve();
|
|
43
53
|
}
|
|
44
54
|
|
|
45
55
|
const contentType = res.headers.get("content-type") || "";
|
|
@@ -55,8 +65,8 @@ export function createServerFunctionProxy(id) {
|
|
|
55
65
|
if (contentType.includes("application/json")) {
|
|
56
66
|
const data = await res.json();
|
|
57
67
|
if (data && data.redirect) {
|
|
58
|
-
|
|
59
|
-
return
|
|
68
|
+
executeRedirect(data.redirect);
|
|
69
|
+
return Promise.resolve();
|
|
60
70
|
}
|
|
61
71
|
return data;
|
|
62
72
|
}
|
|
@@ -83,7 +93,7 @@ export function createServerFunctionProxy(id) {
|
|
|
83
93
|
const payload = JSON.parse(buffer.slice(2));
|
|
84
94
|
if (payload.type === "redirect") {
|
|
85
95
|
isRedirecting = true;
|
|
86
|
-
|
|
96
|
+
executeRedirect(payload.url);
|
|
87
97
|
} else if (payload.type === "cookie") {
|
|
88
98
|
document.cookie = payload.cookie;
|
|
89
99
|
}
|
|
@@ -120,7 +130,7 @@ export function createServerFunctionProxy(id) {
|
|
|
120
130
|
const payload = JSON.parse(line.slice(2));
|
|
121
131
|
if (payload.type === "redirect") {
|
|
122
132
|
isRedirecting = true;
|
|
123
|
-
|
|
133
|
+
executeRedirect(payload.url);
|
|
124
134
|
} else if (payload.type === "cookie") {
|
|
125
135
|
document.cookie = payload.cookie;
|
|
126
136
|
}
|
|
@@ -137,12 +147,9 @@ export function createServerFunctionProxy(id) {
|
|
|
137
147
|
}
|
|
138
148
|
}
|
|
139
149
|
}
|
|
150
|
+
controller.close();
|
|
140
151
|
} catch (err) {
|
|
141
152
|
controller.error(err);
|
|
142
|
-
} finally {
|
|
143
|
-
if (!isRedirecting) {
|
|
144
|
-
controller.close();
|
|
145
|
-
}
|
|
146
153
|
}
|
|
147
154
|
},
|
|
148
155
|
});
|
package/dinou/package.json
CHANGED