@chidchanun/bcp 0.1.9 → 0.1.10
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 +41 -0
- package/README.md +141 -8
- package/docs/releasing.md +34 -19
- package/docs/route-guards.md +240 -0
- package/docs/updating.md +130 -0
- package/package.json +1 -1
- package/packages/bundler/src/server-production-guards.ts +497 -0
- package/packages/bundler/src/server-production-middleware.ts +33 -8
- package/packages/cli/src/args.ts +58 -0
- package/packages/cli/src/index.ts +41 -13
- package/packages/cli/src/update.ts +860 -0
- package/packages/client/src/index.tsx +1 -0
- package/packages/client/src/loader-data.tsx +171 -41
- package/packages/server/src/page-guard.ts +529 -0
- package/packages/server/src/page-loader.ts +317 -20
- package/packages/server/src/standalone-production-runtime-v2-guard.ts +815 -0
- package/packages/server/src/standalone-production-runtime-v3.ts +1 -1
|
@@ -7,32 +7,76 @@ import {
|
|
|
7
7
|
|
|
8
8
|
const LOADER_DATA_PARAM =
|
|
9
9
|
"__bcp_loader_data";
|
|
10
|
+
const GUARD_DATA_PARAM =
|
|
11
|
+
"__bcp_guard_data";
|
|
12
|
+
const SERVER_DATA_MARKER =
|
|
13
|
+
"__bcp_server_data";
|
|
10
14
|
const MISSING_LOADER_DATA =
|
|
11
15
|
Symbol(
|
|
12
16
|
"bcp-loader-data"
|
|
13
17
|
);
|
|
18
|
+
const MISSING_GUARD_DATA =
|
|
19
|
+
Symbol(
|
|
20
|
+
"bcp-guard-data"
|
|
21
|
+
);
|
|
14
22
|
|
|
15
23
|
const LoaderDataContext =
|
|
16
24
|
createContext<unknown>(
|
|
17
25
|
MISSING_LOADER_DATA
|
|
18
26
|
);
|
|
27
|
+
const GuardDataContext =
|
|
28
|
+
createContext<unknown>(
|
|
29
|
+
MISSING_GUARD_DATA
|
|
30
|
+
);
|
|
19
31
|
|
|
20
32
|
export interface BcpLoaderDataProviderProps {
|
|
21
33
|
data: unknown;
|
|
22
34
|
children?: ReactNode;
|
|
23
35
|
}
|
|
24
36
|
|
|
37
|
+
interface ServerDataEnvelope {
|
|
38
|
+
__bcp_server_data: true;
|
|
39
|
+
hasPageLoader: boolean;
|
|
40
|
+
hasGuard: boolean;
|
|
41
|
+
loaderData: unknown;
|
|
42
|
+
guardData: unknown;
|
|
43
|
+
}
|
|
44
|
+
|
|
25
45
|
export function BcpLoaderDataProvider({
|
|
26
46
|
data,
|
|
27
47
|
children,
|
|
28
48
|
}: BcpLoaderDataProviderProps) {
|
|
49
|
+
const envelope =
|
|
50
|
+
isServerDataEnvelope(
|
|
51
|
+
data
|
|
52
|
+
)
|
|
53
|
+
? data
|
|
54
|
+
: null;
|
|
55
|
+
const loaderValue =
|
|
56
|
+
envelope
|
|
57
|
+
? envelope.hasPageLoader
|
|
58
|
+
? envelope.loaderData
|
|
59
|
+
: MISSING_LOADER_DATA
|
|
60
|
+
: data;
|
|
61
|
+
const guardValue =
|
|
62
|
+
envelope?.hasGuard
|
|
63
|
+
? envelope.guardData
|
|
64
|
+
: MISSING_GUARD_DATA;
|
|
65
|
+
|
|
29
66
|
return createElement(
|
|
30
|
-
|
|
67
|
+
GuardDataContext.Provider,
|
|
31
68
|
{
|
|
32
69
|
value:
|
|
33
|
-
|
|
70
|
+
guardValue,
|
|
34
71
|
},
|
|
35
|
-
|
|
72
|
+
createElement(
|
|
73
|
+
LoaderDataContext.Provider,
|
|
74
|
+
{
|
|
75
|
+
value:
|
|
76
|
+
loaderValue,
|
|
77
|
+
},
|
|
78
|
+
children
|
|
79
|
+
)
|
|
36
80
|
);
|
|
37
81
|
}
|
|
38
82
|
|
|
@@ -51,49 +95,135 @@ export function useLoaderData<
|
|
|
51
95
|
return contextValue as T;
|
|
52
96
|
}
|
|
53
97
|
|
|
98
|
+
const browserValue =
|
|
99
|
+
readFrameworkParam(
|
|
100
|
+
LOADER_DATA_PARAM
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
if (browserValue.found) {
|
|
104
|
+
return browserValue.value as T;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
throw new Error(
|
|
108
|
+
"BCP Framework: useLoaderData() was used on a route without loader data. Add loader.ts next to page.tsx."
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function useGuardData<
|
|
113
|
+
T = unknown
|
|
114
|
+
>(): T {
|
|
115
|
+
const contextValue =
|
|
116
|
+
useContext(
|
|
117
|
+
GuardDataContext
|
|
118
|
+
);
|
|
119
|
+
|
|
54
120
|
if (
|
|
55
|
-
|
|
121
|
+
contextValue !==
|
|
122
|
+
MISSING_GUARD_DATA
|
|
123
|
+
) {
|
|
124
|
+
return contextValue as T;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const browserValue =
|
|
128
|
+
readFrameworkParam(
|
|
129
|
+
GUARD_DATA_PARAM
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
if (browserValue.found) {
|
|
133
|
+
return browserValue.value as T;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
throw new Error(
|
|
137
|
+
"BCP Framework: useGuardData() was used on a route without guard data. Add guard.ts to the route or an ancestor route directory."
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function readFrameworkParam(
|
|
142
|
+
key: string
|
|
143
|
+
): {
|
|
144
|
+
found: boolean;
|
|
145
|
+
value: unknown;
|
|
146
|
+
} {
|
|
147
|
+
if (
|
|
148
|
+
typeof document ===
|
|
56
149
|
"undefined"
|
|
57
150
|
) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
|
|
151
|
+
return {
|
|
152
|
+
found:
|
|
153
|
+
false,
|
|
154
|
+
value:
|
|
155
|
+
undefined,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const element =
|
|
160
|
+
document.getElementById(
|
|
161
|
+
"__BCP_DATA__"
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
if (!element) {
|
|
165
|
+
return {
|
|
166
|
+
found:
|
|
167
|
+
false,
|
|
168
|
+
value:
|
|
169
|
+
undefined,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
try {
|
|
174
|
+
const frameworkData =
|
|
175
|
+
JSON.parse(
|
|
176
|
+
element.textContent ||
|
|
177
|
+
"{}"
|
|
178
|
+
) as {
|
|
179
|
+
params?: Record<
|
|
180
|
+
string,
|
|
181
|
+
unknown
|
|
182
|
+
>;
|
|
183
|
+
};
|
|
184
|
+
const params =
|
|
185
|
+
frameworkData.params;
|
|
186
|
+
|
|
187
|
+
if (
|
|
188
|
+
params &&
|
|
189
|
+
Object.prototype
|
|
190
|
+
.hasOwnProperty.call(
|
|
191
|
+
params,
|
|
192
|
+
key
|
|
193
|
+
)
|
|
194
|
+
) {
|
|
195
|
+
return {
|
|
196
|
+
found:
|
|
197
|
+
true,
|
|
198
|
+
value:
|
|
199
|
+
params[
|
|
200
|
+
key
|
|
201
|
+
],
|
|
202
|
+
};
|
|
93
203
|
}
|
|
204
|
+
} catch {
|
|
205
|
+
// Fall through to the missing-data result.
|
|
94
206
|
}
|
|
95
207
|
|
|
96
|
-
|
|
97
|
-
|
|
208
|
+
return {
|
|
209
|
+
found:
|
|
210
|
+
false,
|
|
211
|
+
value:
|
|
212
|
+
undefined,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function isServerDataEnvelope(
|
|
217
|
+
value: unknown
|
|
218
|
+
): value is ServerDataEnvelope {
|
|
219
|
+
return (
|
|
220
|
+
value !== null &&
|
|
221
|
+
typeof value ===
|
|
222
|
+
"object" &&
|
|
223
|
+
(
|
|
224
|
+
value as
|
|
225
|
+
Record<string, unknown>
|
|
226
|
+
)[SERVER_DATA_MARKER] ===
|
|
227
|
+
true
|
|
98
228
|
);
|
|
99
229
|
}
|