@chidchanun/bcp 0.1.7 → 0.1.9
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 +71 -0
- package/README.md +190 -4
- package/docs/application-modules.md +63 -3
- package/docs/server-data-loaders.md +240 -0
- package/docs/session-auth.md +186 -0
- package/package.json +1 -1
- package/packages/bundler/src/server-production.ts +25 -0
- package/packages/client/src/index.tsx +4 -0
- package/packages/client/src/loader-data.tsx +99 -0
- package/packages/client/src/router-v2.tsx +254 -29
- package/packages/client/src/server.ts +13 -0
- package/packages/server/src/dev-navigation-target.ts +188 -0
- package/packages/server/src/index.ts +209 -119
- package/packages/server/src/navigation-payload.ts +24 -1
- package/packages/server/src/navigation-response.ts +284 -0
- package/packages/server/src/page-loader.ts +346 -0
- package/packages/server/src/session.ts +694 -0
- package/packages/server/src/standalone-production-runtime-v2-navigation.ts +785 -0
- package/packages/server/src/standalone-production-runtime-v2.ts +131 -19
- package/packages/server/src/standalone-production-runtime-v3.ts +1 -1
- package/packages/server/src/standalone-production-runtime-v4.ts +42 -2
- package/packages/server/src/static-dev-server.ts +21 -17
|
@@ -20,6 +20,10 @@ import type {
|
|
|
20
20
|
ProductionRouteAsset,
|
|
21
21
|
} from "../../bundler/src/production.js";
|
|
22
22
|
|
|
23
|
+
import {
|
|
24
|
+
BcpLoaderDataProvider,
|
|
25
|
+
} from "../../client/src/loader-data.js";
|
|
26
|
+
|
|
23
27
|
import {
|
|
24
28
|
createMetadataHeadEntries,
|
|
25
29
|
type ResolvedMetadata,
|
|
@@ -49,6 +53,13 @@ import {
|
|
|
49
53
|
type MetadataSource,
|
|
50
54
|
} from "./metadata.js";
|
|
51
55
|
|
|
56
|
+
import {
|
|
57
|
+
attachLoaderDataToParams,
|
|
58
|
+
executePageLoaderFunction,
|
|
59
|
+
type PageLoader,
|
|
60
|
+
type PageLoaderExecution,
|
|
61
|
+
} from "./page-loader.js";
|
|
62
|
+
|
|
52
63
|
import {
|
|
53
64
|
applyResponseCookies,
|
|
54
65
|
runWithRequestContext,
|
|
@@ -69,6 +80,7 @@ export interface StandalonePageRoute {
|
|
|
69
80
|
error: ComponentType<any> | null;
|
|
70
81
|
notFound: ComponentType<any> | null;
|
|
71
82
|
metadataSources: MetadataSource[];
|
|
83
|
+
loader: PageLoader | null;
|
|
72
84
|
client: ProductionRouteAsset;
|
|
73
85
|
}
|
|
74
86
|
|
|
@@ -345,6 +357,7 @@ export function createStandaloneProductionServer(
|
|
|
345
357
|
await sendPage(
|
|
346
358
|
req,
|
|
347
359
|
res,
|
|
360
|
+
requestUrl,
|
|
348
361
|
definition,
|
|
349
362
|
match.params,
|
|
350
363
|
options
|
|
@@ -453,29 +466,99 @@ export function createStandaloneProductionServer(
|
|
|
453
466
|
async function sendPage(
|
|
454
467
|
req: http.IncomingMessage,
|
|
455
468
|
res: http.ServerResponse,
|
|
469
|
+
requestUrl: URL,
|
|
456
470
|
definition: StandalonePageRoute,
|
|
457
471
|
params: Record<string, string>,
|
|
458
472
|
options: StandaloneProductionServerOptions
|
|
459
473
|
): Promise<void> {
|
|
460
474
|
try {
|
|
461
|
-
const
|
|
462
|
-
await
|
|
463
|
-
|
|
464
|
-
|
|
475
|
+
const request =
|
|
476
|
+
await createWebRequest(
|
|
477
|
+
req,
|
|
478
|
+
requestUrl
|
|
465
479
|
);
|
|
466
480
|
|
|
467
|
-
const
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
481
|
+
const response =
|
|
482
|
+
await runWithRequestContext(
|
|
483
|
+
request,
|
|
484
|
+
async () => {
|
|
485
|
+
const loaderExecution:
|
|
486
|
+
PageLoaderExecution =
|
|
487
|
+
definition.loader
|
|
488
|
+
? await executePageLoaderFunction(
|
|
489
|
+
definition.loader,
|
|
490
|
+
params,
|
|
491
|
+
requestUrl,
|
|
492
|
+
definition.pathname
|
|
493
|
+
)
|
|
494
|
+
: {
|
|
495
|
+
hasLoader:
|
|
496
|
+
false,
|
|
497
|
+
data:
|
|
498
|
+
undefined,
|
|
499
|
+
response:
|
|
500
|
+
null,
|
|
501
|
+
};
|
|
502
|
+
|
|
503
|
+
if (
|
|
504
|
+
loaderExecution.response
|
|
505
|
+
) {
|
|
506
|
+
return applyResponseCookies(
|
|
507
|
+
loaderExecution.response
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
const metadata =
|
|
512
|
+
await resolveRouteMetadata(
|
|
513
|
+
definition.metadataSources,
|
|
514
|
+
params
|
|
515
|
+
);
|
|
516
|
+
|
|
517
|
+
const frameworkParams =
|
|
518
|
+
attachLoaderDataToParams(
|
|
519
|
+
params,
|
|
520
|
+
loaderExecution
|
|
521
|
+
);
|
|
522
|
+
|
|
523
|
+
const html =
|
|
524
|
+
renderPageDocument(
|
|
525
|
+
definition,
|
|
526
|
+
frameworkParams,
|
|
527
|
+
metadata,
|
|
528
|
+
loaderExecution
|
|
529
|
+
);
|
|
530
|
+
|
|
531
|
+
return applyResponseCookies(
|
|
532
|
+
new Response(
|
|
533
|
+
html,
|
|
534
|
+
{
|
|
535
|
+
status:
|
|
536
|
+
200,
|
|
537
|
+
headers: {
|
|
538
|
+
"Content-Type":
|
|
539
|
+
"text/html; charset=utf-8",
|
|
540
|
+
"Cache-Control":
|
|
541
|
+
"no-store",
|
|
542
|
+
},
|
|
543
|
+
}
|
|
544
|
+
)
|
|
545
|
+
);
|
|
546
|
+
},
|
|
547
|
+
{
|
|
548
|
+
remoteAddress:
|
|
549
|
+
req.socket
|
|
550
|
+
.remoteAddress ??
|
|
551
|
+
null,
|
|
552
|
+
}
|
|
472
553
|
);
|
|
473
554
|
|
|
474
|
-
|
|
555
|
+
await sendWebResponse(
|
|
475
556
|
req,
|
|
476
557
|
res,
|
|
477
|
-
|
|
478
|
-
|
|
558
|
+
response,
|
|
559
|
+
normalizeHttpMethod(
|
|
560
|
+
req.method
|
|
561
|
+
) === "HEAD"
|
|
479
562
|
);
|
|
480
563
|
} catch (error) {
|
|
481
564
|
if (isNotFoundError(error)) {
|
|
@@ -561,10 +644,11 @@ function sendGlobalNotFound(
|
|
|
561
644
|
|
|
562
645
|
function renderPageDocument(
|
|
563
646
|
definition: StandalonePageRoute,
|
|
564
|
-
params: Record<string,
|
|
565
|
-
metadata: ResolvedMetadata
|
|
647
|
+
params: Record<string, any>,
|
|
648
|
+
metadata: ResolvedMetadata,
|
|
649
|
+
loaderExecution: PageLoaderExecution
|
|
566
650
|
): string {
|
|
567
|
-
|
|
651
|
+
let element =
|
|
568
652
|
wrapWithLayouts(
|
|
569
653
|
createElement(
|
|
570
654
|
definition.page,
|
|
@@ -576,6 +660,20 @@ function renderPageDocument(
|
|
|
576
660
|
params
|
|
577
661
|
);
|
|
578
662
|
|
|
663
|
+
if (
|
|
664
|
+
loaderExecution.hasLoader
|
|
665
|
+
) {
|
|
666
|
+
element =
|
|
667
|
+
createElement(
|
|
668
|
+
BcpLoaderDataProvider,
|
|
669
|
+
{
|
|
670
|
+
data:
|
|
671
|
+
loaderExecution.data,
|
|
672
|
+
},
|
|
673
|
+
element
|
|
674
|
+
);
|
|
675
|
+
}
|
|
676
|
+
|
|
579
677
|
const content =
|
|
580
678
|
renderToString(
|
|
581
679
|
element
|
|
@@ -595,7 +693,7 @@ function renderPageDocument(
|
|
|
595
693
|
function renderFallbackDocument(
|
|
596
694
|
Component: ComponentType<any> | null,
|
|
597
695
|
layouts: ComponentType<any>[],
|
|
598
|
-
params: Record<string,
|
|
696
|
+
params: Record<string, any>,
|
|
599
697
|
fallback:
|
|
600
698
|
| {
|
|
601
699
|
kind: "not-found";
|
|
@@ -700,7 +798,7 @@ function renderFallbackDocument(
|
|
|
700
798
|
function wrapWithLayouts(
|
|
701
799
|
child: ReactElement,
|
|
702
800
|
layouts: ComponentType<any>[],
|
|
703
|
-
params: Record<string,
|
|
801
|
+
params: Record<string, any>
|
|
704
802
|
): ReactElement {
|
|
705
803
|
let element =
|
|
706
804
|
child;
|
|
@@ -728,7 +826,7 @@ function renderDocument(
|
|
|
728
826
|
input: {
|
|
729
827
|
content: string;
|
|
730
828
|
route: string | null;
|
|
731
|
-
params: Record<string,
|
|
829
|
+
params: Record<string, any> | null;
|
|
732
830
|
client: ProductionRouteAsset | null;
|
|
733
831
|
metadata: ResolvedMetadata;
|
|
734
832
|
}
|
|
@@ -1029,6 +1127,19 @@ async function handleNavigation(
|
|
|
1029
1127
|
return;
|
|
1030
1128
|
}
|
|
1031
1129
|
|
|
1130
|
+
if (definition.loader) {
|
|
1131
|
+
sendJson(
|
|
1132
|
+
req,
|
|
1133
|
+
res,
|
|
1134
|
+
409,
|
|
1135
|
+
{
|
|
1136
|
+
error:
|
|
1137
|
+
"Loader routes require document navigation.",
|
|
1138
|
+
}
|
|
1139
|
+
);
|
|
1140
|
+
return;
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1032
1143
|
let metadata:
|
|
1033
1144
|
ResolvedMetadata;
|
|
1034
1145
|
|
|
@@ -1699,7 +1810,8 @@ async function sendWebResponse(
|
|
|
1699
1810
|
|
|
1700
1811
|
if (
|
|
1701
1812
|
cookies &&
|
|
1702
|
-
cookies.length >
|
|
1813
|
+
cookies.length >
|
|
1814
|
+
0
|
|
1703
1815
|
) {
|
|
1704
1816
|
res.setHeader(
|
|
1705
1817
|
"Set-Cookie",
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
type StandaloneApiRoute,
|
|
19
19
|
type StandalonePageRoute,
|
|
20
20
|
type StandaloneProductionServerOptions as BaseStandaloneProductionServerOptions,
|
|
21
|
-
} from "./standalone-production-runtime-v2.js";
|
|
21
|
+
} from "./standalone-production-runtime-v2-navigation.js";
|
|
22
22
|
|
|
23
23
|
import type {
|
|
24
24
|
MiddlewareModule,
|
|
@@ -46,8 +46,11 @@ export function createStandaloneProductionServer(
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
const manifest =
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
excludeLoaderPagesFromCache(
|
|
50
|
+
readCacheManifest(
|
|
51
|
+
options.buildDirectory
|
|
52
|
+
),
|
|
53
|
+
options.routes
|
|
51
54
|
);
|
|
52
55
|
|
|
53
56
|
const responseCacheEnabled =
|
|
@@ -156,6 +159,43 @@ export function createStandaloneProductionServer(
|
|
|
156
159
|
};
|
|
157
160
|
}
|
|
158
161
|
|
|
162
|
+
function excludeLoaderPagesFromCache(
|
|
163
|
+
manifest: ResponseCacheManifest,
|
|
164
|
+
routes: StandalonePageRoute[]
|
|
165
|
+
): ResponseCacheManifest {
|
|
166
|
+
const loaderRoutes =
|
|
167
|
+
new Set(
|
|
168
|
+
routes
|
|
169
|
+
.filter(
|
|
170
|
+
(route) =>
|
|
171
|
+
route.loader !==
|
|
172
|
+
null
|
|
173
|
+
)
|
|
174
|
+
.map(
|
|
175
|
+
(route) =>
|
|
176
|
+
route.pathname
|
|
177
|
+
)
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
if (
|
|
181
|
+
loaderRoutes.size ===
|
|
182
|
+
0
|
|
183
|
+
) {
|
|
184
|
+
return manifest;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return {
|
|
188
|
+
...manifest,
|
|
189
|
+
pages:
|
|
190
|
+
manifest.pages.filter(
|
|
191
|
+
(route) =>
|
|
192
|
+
!loaderRoutes.has(
|
|
193
|
+
route.pathname
|
|
194
|
+
)
|
|
195
|
+
),
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
159
199
|
function readCacheManifest(
|
|
160
200
|
buildDirectory: string
|
|
161
201
|
): ResponseCacheManifest {
|
|
@@ -11,12 +11,19 @@ import {
|
|
|
11
11
|
applyDevDocumentMetadata,
|
|
12
12
|
} from "./dev-document-metadata.js";
|
|
13
13
|
|
|
14
|
+
import {
|
|
15
|
+
createDevNavigationTargetResponse,
|
|
16
|
+
} from "./dev-navigation-target.js";
|
|
17
|
+
|
|
14
18
|
import {
|
|
15
19
|
resolveNavigationPayload,
|
|
16
20
|
sendNavigationError,
|
|
17
|
-
sendNavigationPayload,
|
|
18
21
|
} from "./navigation-payload.js";
|
|
19
22
|
|
|
23
|
+
import {
|
|
24
|
+
sendNavigationWebResponse,
|
|
25
|
+
} from "./navigation-response.js";
|
|
26
|
+
|
|
20
27
|
import {
|
|
21
28
|
readPublicAsset,
|
|
22
29
|
type StaticAsset,
|
|
@@ -405,7 +412,11 @@ async function sendHtmlWithMetadata(
|
|
|
405
412
|
const payload =
|
|
406
413
|
await resolveNavigationPayload(
|
|
407
414
|
rootDirectory,
|
|
408
|
-
pathname
|
|
415
|
+
pathname,
|
|
416
|
+
{
|
|
417
|
+
allowLoaderRoute:
|
|
418
|
+
true,
|
|
419
|
+
}
|
|
409
420
|
);
|
|
410
421
|
|
|
411
422
|
const html =
|
|
@@ -595,34 +606,27 @@ async function handleNavigationRequest(
|
|
|
595
606
|
return;
|
|
596
607
|
}
|
|
597
608
|
|
|
598
|
-
const
|
|
599
|
-
await
|
|
609
|
+
const response =
|
|
610
|
+
await createDevNavigationTargetResponse(
|
|
611
|
+
req,
|
|
600
612
|
rootDirectory,
|
|
601
|
-
target
|
|
613
|
+
target
|
|
602
614
|
);
|
|
603
615
|
|
|
604
|
-
if (!
|
|
616
|
+
if (!response) {
|
|
605
617
|
sendNavigationError(
|
|
606
618
|
res,
|
|
607
619
|
404,
|
|
608
620
|
"Route not found."
|
|
609
621
|
);
|
|
610
|
-
|
|
611
|
-
|
|
622
|
+
} else {
|
|
623
|
+
await sendNavigationWebResponse(
|
|
612
624
|
req,
|
|
613
|
-
requestUrl.pathname,
|
|
614
625
|
res,
|
|
615
|
-
|
|
626
|
+
response
|
|
616
627
|
);
|
|
617
|
-
|
|
618
|
-
return;
|
|
619
628
|
}
|
|
620
629
|
|
|
621
|
-
sendNavigationPayload(
|
|
622
|
-
res,
|
|
623
|
-
payload
|
|
624
|
-
);
|
|
625
|
-
|
|
626
630
|
logRequest(
|
|
627
631
|
req,
|
|
628
632
|
requestUrl.pathname,
|