@chidchanun/bcp 0.1.0
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 +49 -0
- package/LICENSE +21 -0
- package/README.md +241 -0
- package/docs/caching.md +76 -0
- package/docs/configuration.md +97 -0
- package/docs/deployment.md +74 -0
- package/docs/getting-started.md +82 -0
- package/docs/middleware.md +58 -0
- package/docs/releasing.md +299 -0
- package/docs/routing.md +103 -0
- package/docs/security.md +57 -0
- package/package.json +68 -0
- package/packages/bundler/src/client-islands.ts +1457 -0
- package/packages/bundler/src/incremental-context.ts +206 -0
- package/packages/bundler/src/index.ts +1991 -0
- package/packages/bundler/src/module-graph.ts +317 -0
- package/packages/bundler/src/partial-hydration.ts +414 -0
- package/packages/bundler/src/production.ts +974 -0
- package/packages/bundler/src/server-production-middleware.ts +447 -0
- package/packages/bundler/src/server-production.ts +1193 -0
- package/packages/bundler/src/special-files.ts +131 -0
- package/packages/cache/src/index.ts +761 -0
- package/packages/cli/bin/bcp.mjs +93 -0
- package/packages/cli/src/args.ts +305 -0
- package/packages/cli/src/bootstrap.ts +514 -0
- package/packages/cli/src/index.ts +504 -0
- package/packages/cli/src/version.ts +45 -0
- package/packages/client/src/cache.ts +11 -0
- package/packages/client/src/config.ts +18 -0
- package/packages/client/src/error-boundary.tsx +149 -0
- package/packages/client/src/hydration.ts +3 -0
- package/packages/client/src/index.tsx +57 -0
- package/packages/client/src/islands.tsx +315 -0
- package/packages/client/src/metadata.ts +281 -0
- package/packages/client/src/navigation-loading.ts +52 -0
- package/packages/client/src/navigation-state.ts +80 -0
- package/packages/client/src/not-found.ts +34 -0
- package/packages/client/src/persistent-layout-runtime.ts +273 -0
- package/packages/client/src/router-v2.tsx +969 -0
- package/packages/client/src/router.tsx +1 -0
- package/packages/config/src/index.ts +1038 -0
- package/packages/env/src/index.ts +593 -0
- package/packages/router/src/advanced-router.ts +1032 -0
- package/packages/router/src/index.ts +1 -0
- package/packages/server/src/compression.ts +249 -0
- package/packages/server/src/dev-document-metadata.ts +154 -0
- package/packages/server/src/dev-hmr.ts +225 -0
- package/packages/server/src/index.ts +2265 -0
- package/packages/server/src/metadata.ts +478 -0
- package/packages/server/src/middleware-dev-server.ts +260 -0
- package/packages/server/src/middleware-loader.ts +140 -0
- package/packages/server/src/middleware-proxy.ts +516 -0
- package/packages/server/src/middleware.ts +704 -0
- package/packages/server/src/navigation-payload.ts +471 -0
- package/packages/server/src/production-server.ts +1746 -0
- package/packages/server/src/response-cache-proxy.ts +828 -0
- package/packages/server/src/security-proxy.ts +406 -0
- package/packages/server/src/security.ts +451 -0
- package/packages/server/src/standalone-production-runtime-v2.ts +2047 -0
- package/packages/server/src/standalone-production-runtime-v3.ts +250 -0
- package/packages/server/src/standalone-production-runtime-v4.ts +289 -0
- package/packages/server/src/standalone-production-runtime-v5.ts +289 -0
- package/packages/server/src/standalone-production-runtime.ts +1951 -0
- package/packages/server/src/standalone-production-server.ts +6 -0
- package/packages/server/src/static-assets.ts +262 -0
- package/packages/server/src/static-dev-server.ts +854 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useSyncExternalStore,
|
|
3
|
+
} from "react";
|
|
4
|
+
|
|
5
|
+
export interface NavigationState {
|
|
6
|
+
isNavigating: boolean;
|
|
7
|
+
|
|
8
|
+
targetHref: string | null;
|
|
9
|
+
|
|
10
|
+
targetRoute: string | null;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const serverSnapshot: NavigationState = {
|
|
14
|
+
isNavigating: false,
|
|
15
|
+
targetHref: null,
|
|
16
|
+
targetRoute: null,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
let currentState: NavigationState =
|
|
20
|
+
serverSnapshot;
|
|
21
|
+
|
|
22
|
+
const listeners =
|
|
23
|
+
new Set<() => void>();
|
|
24
|
+
|
|
25
|
+
export function getNavigationState(): NavigationState {
|
|
26
|
+
return currentState;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function setNavigationState(
|
|
30
|
+
nextState: Partial<NavigationState>
|
|
31
|
+
): void {
|
|
32
|
+
currentState = {
|
|
33
|
+
...currentState,
|
|
34
|
+
...nextState,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
for (
|
|
38
|
+
const listener
|
|
39
|
+
of listeners
|
|
40
|
+
) {
|
|
41
|
+
listener();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function resetNavigationState(): void {
|
|
46
|
+
currentState = {
|
|
47
|
+
isNavigating: false,
|
|
48
|
+
targetHref: null,
|
|
49
|
+
targetRoute: null,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
for (
|
|
53
|
+
const listener
|
|
54
|
+
of listeners
|
|
55
|
+
) {
|
|
56
|
+
listener();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function useNavigation(): NavigationState {
|
|
61
|
+
return useSyncExternalStore(
|
|
62
|
+
subscribe,
|
|
63
|
+
getNavigationState,
|
|
64
|
+
() => serverSnapshot
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function subscribe(
|
|
69
|
+
listener: () => void
|
|
70
|
+
): () => void {
|
|
71
|
+
listeners.add(
|
|
72
|
+
listener
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
return () => {
|
|
76
|
+
listeners.delete(
|
|
77
|
+
listener
|
|
78
|
+
);
|
|
79
|
+
};
|
|
80
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const NOT_FOUND_CODE =
|
|
2
|
+
"BCP_NOT_FOUND";
|
|
3
|
+
|
|
4
|
+
export interface BcpNotFoundError
|
|
5
|
+
extends Error {
|
|
6
|
+
code:
|
|
7
|
+
typeof NOT_FOUND_CODE;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function notFound(): never {
|
|
11
|
+
const error =
|
|
12
|
+
new Error(
|
|
13
|
+
"BCP Framework: notFound() was called."
|
|
14
|
+
) as BcpNotFoundError;
|
|
15
|
+
|
|
16
|
+
error.name =
|
|
17
|
+
"BcpNotFoundError";
|
|
18
|
+
error.code =
|
|
19
|
+
NOT_FOUND_CODE;
|
|
20
|
+
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function isNotFoundError(
|
|
25
|
+
error: unknown
|
|
26
|
+
): error is BcpNotFoundError {
|
|
27
|
+
return (
|
|
28
|
+
typeof error === "object" &&
|
|
29
|
+
error !== null &&
|
|
30
|
+
"code" in error &&
|
|
31
|
+
error.code ===
|
|
32
|
+
NOT_FOUND_CODE
|
|
33
|
+
);
|
|
34
|
+
}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createElement,
|
|
3
|
+
isValidElement,
|
|
4
|
+
type ReactElement,
|
|
5
|
+
type ReactNode,
|
|
6
|
+
} from "react";
|
|
7
|
+
|
|
8
|
+
declare global {
|
|
9
|
+
var __BCP_LAYOUT_RUNTIME_INSTALLED__:
|
|
10
|
+
| boolean
|
|
11
|
+
| undefined;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const layoutTypes =
|
|
15
|
+
new Map<string, ReactElement["type"]>();
|
|
16
|
+
|
|
17
|
+
function installPersistentLayoutRuntime(): void {
|
|
18
|
+
if (
|
|
19
|
+
typeof window === "undefined"
|
|
20
|
+
) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (
|
|
25
|
+
globalThis.__BCP_LAYOUT_RUNTIME_INSTALLED__
|
|
26
|
+
) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const root =
|
|
31
|
+
globalThis.__BCP_REACT_ROOT__;
|
|
32
|
+
|
|
33
|
+
if (!root) {
|
|
34
|
+
queueMicrotask(
|
|
35
|
+
installPersistentLayoutRuntime
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const originalRender =
|
|
42
|
+
root.render.bind(root);
|
|
43
|
+
|
|
44
|
+
root.render = (
|
|
45
|
+
tree: ReactNode
|
|
46
|
+
) => {
|
|
47
|
+
originalRender(
|
|
48
|
+
normalizeLayoutTree(
|
|
49
|
+
tree
|
|
50
|
+
)
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
globalThis.__BCP_LAYOUT_RUNTIME_INSTALLED__ =
|
|
55
|
+
true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
queueMicrotask(
|
|
59
|
+
installPersistentLayoutRuntime
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
function normalizeLayoutTree(
|
|
63
|
+
tree: ReactNode
|
|
64
|
+
): ReactNode {
|
|
65
|
+
const route =
|
|
66
|
+
getCurrentRoutePattern();
|
|
67
|
+
|
|
68
|
+
const layoutKeys =
|
|
69
|
+
getLayoutSegmentKeys(
|
|
70
|
+
route
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
const chain:
|
|
74
|
+
ReactElement[] = [];
|
|
75
|
+
|
|
76
|
+
let current =
|
|
77
|
+
tree;
|
|
78
|
+
|
|
79
|
+
let depth = 0;
|
|
80
|
+
|
|
81
|
+
while (
|
|
82
|
+
isValidElement(
|
|
83
|
+
current
|
|
84
|
+
)
|
|
85
|
+
) {
|
|
86
|
+
const props =
|
|
87
|
+
current.props as {
|
|
88
|
+
children?: ReactNode;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
if (
|
|
92
|
+
!isValidElement(
|
|
93
|
+
props.children
|
|
94
|
+
)
|
|
95
|
+
) {
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (
|
|
100
|
+
typeof current.type !==
|
|
101
|
+
"function"
|
|
102
|
+
) {
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const layoutKey =
|
|
107
|
+
layoutKeys[depth] ??
|
|
108
|
+
`depth:${depth}`;
|
|
109
|
+
|
|
110
|
+
const existingType =
|
|
111
|
+
layoutTypes.get(
|
|
112
|
+
layoutKey
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
if (
|
|
116
|
+
existingType
|
|
117
|
+
) {
|
|
118
|
+
chain.push(
|
|
119
|
+
createElement(
|
|
120
|
+
existingType,
|
|
121
|
+
createElementProps(
|
|
122
|
+
current
|
|
123
|
+
),
|
|
124
|
+
props.children
|
|
125
|
+
)
|
|
126
|
+
);
|
|
127
|
+
} else {
|
|
128
|
+
layoutTypes.set(
|
|
129
|
+
layoutKey,
|
|
130
|
+
current.type
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
chain.push(
|
|
134
|
+
current
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
current =
|
|
139
|
+
props.children;
|
|
140
|
+
|
|
141
|
+
depth++;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (
|
|
145
|
+
chain.length === 0
|
|
146
|
+
) {
|
|
147
|
+
return tree;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
let result =
|
|
151
|
+
current;
|
|
152
|
+
|
|
153
|
+
for (
|
|
154
|
+
let index =
|
|
155
|
+
chain.length - 1;
|
|
156
|
+
index >= 0;
|
|
157
|
+
index--
|
|
158
|
+
) {
|
|
159
|
+
const layout =
|
|
160
|
+
chain[index];
|
|
161
|
+
|
|
162
|
+
const props =
|
|
163
|
+
layout.props as
|
|
164
|
+
Record<string, unknown>;
|
|
165
|
+
|
|
166
|
+
result =
|
|
167
|
+
createElement(
|
|
168
|
+
layout.type,
|
|
169
|
+
{
|
|
170
|
+
...props,
|
|
171
|
+
...(layout.key !==
|
|
172
|
+
null
|
|
173
|
+
? {
|
|
174
|
+
key:
|
|
175
|
+
layout.key,
|
|
176
|
+
}
|
|
177
|
+
: {}),
|
|
178
|
+
},
|
|
179
|
+
result
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return result;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function getCurrentRoutePattern(): string {
|
|
187
|
+
if (
|
|
188
|
+
typeof document !==
|
|
189
|
+
"undefined"
|
|
190
|
+
) {
|
|
191
|
+
const dataElement =
|
|
192
|
+
document.getElementById(
|
|
193
|
+
"__BCP_DATA__"
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
if (
|
|
197
|
+
dataElement?.textContent
|
|
198
|
+
) {
|
|
199
|
+
try {
|
|
200
|
+
const data =
|
|
201
|
+
JSON.parse(
|
|
202
|
+
dataElement.textContent
|
|
203
|
+
) as {
|
|
204
|
+
route?: unknown;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
if (
|
|
208
|
+
typeof data.route ===
|
|
209
|
+
"string"
|
|
210
|
+
) {
|
|
211
|
+
return data.route;
|
|
212
|
+
}
|
|
213
|
+
} catch {
|
|
214
|
+
// Fall through to the runtime URL.
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return (
|
|
220
|
+
globalThis.__BCP_DEV_CONFIG__
|
|
221
|
+
?.route ??
|
|
222
|
+
window.location.pathname
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function createElementProps(
|
|
227
|
+
element: ReactElement
|
|
228
|
+
): Record<string, unknown> {
|
|
229
|
+
return {
|
|
230
|
+
...(element.props as
|
|
231
|
+
Record<string, unknown>),
|
|
232
|
+
|
|
233
|
+
...(element.key !== null
|
|
234
|
+
? {
|
|
235
|
+
key:
|
|
236
|
+
element.key,
|
|
237
|
+
}
|
|
238
|
+
: {}),
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function getLayoutSegmentKeys(
|
|
243
|
+
route: string
|
|
244
|
+
): string[] {
|
|
245
|
+
const pathname =
|
|
246
|
+
route.split("?")[0] ||
|
|
247
|
+
"/";
|
|
248
|
+
|
|
249
|
+
const segments =
|
|
250
|
+
pathname
|
|
251
|
+
.split("/")
|
|
252
|
+
.filter(Boolean);
|
|
253
|
+
|
|
254
|
+
const keys = [
|
|
255
|
+
"/",
|
|
256
|
+
];
|
|
257
|
+
|
|
258
|
+
let prefix = "";
|
|
259
|
+
|
|
260
|
+
for (
|
|
261
|
+
const segment
|
|
262
|
+
of segments
|
|
263
|
+
) {
|
|
264
|
+
prefix +=
|
|
265
|
+
`/${segment}`;
|
|
266
|
+
|
|
267
|
+
keys.push(
|
|
268
|
+
prefix
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return keys;
|
|
273
|
+
}
|