rwsdk 1.0.0-beta.4 → 1.0.0-beta.41
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/constants.d.mts +1 -0
- package/dist/lib/constants.mjs +7 -4
- package/dist/lib/e2e/browser.mjs +6 -2
- package/dist/lib/e2e/constants.d.mts +4 -0
- package/dist/lib/e2e/constants.mjs +49 -12
- package/dist/lib/e2e/dev.mjs +37 -49
- package/dist/lib/e2e/environment.d.mts +2 -0
- package/dist/lib/e2e/environment.mjs +201 -64
- package/dist/lib/e2e/index.d.mts +1 -0
- package/dist/lib/e2e/index.mjs +1 -0
- package/dist/lib/e2e/poll.d.mts +1 -1
- package/dist/lib/e2e/release.d.mts +1 -0
- package/dist/lib/e2e/release.mjs +16 -32
- package/dist/lib/e2e/tarball.mjs +2 -34
- package/dist/lib/e2e/testHarness.d.mts +34 -3
- package/dist/lib/e2e/testHarness.mjs +219 -90
- package/dist/lib/e2e/utils.d.mts +1 -0
- package/dist/lib/e2e/utils.mjs +15 -0
- package/dist/runtime/client/client.d.ts +35 -0
- package/dist/runtime/client/client.js +35 -0
- package/dist/runtime/client/navigation.d.ts +49 -0
- package/dist/runtime/client/navigation.js +80 -31
- package/dist/runtime/entries/clientSSR.d.ts +1 -0
- package/dist/runtime/entries/clientSSR.js +3 -0
- package/dist/runtime/entries/no-react-server-ssr-bridge.d.ts +0 -0
- package/dist/runtime/entries/no-react-server-ssr-bridge.js +2 -0
- package/dist/runtime/entries/router.d.ts +1 -0
- package/dist/runtime/entries/routerClient.d.ts +1 -0
- package/dist/runtime/entries/routerClient.js +1 -0
- package/dist/runtime/entries/worker.d.ts +2 -0
- package/dist/runtime/entries/worker.js +2 -0
- package/dist/runtime/imports/__mocks__/use-client-lookup.d.ts +6 -0
- package/dist/runtime/imports/__mocks__/use-client-lookup.js +6 -0
- package/dist/runtime/lib/db/SqliteDurableObject.d.ts +2 -2
- package/dist/runtime/lib/db/SqliteDurableObject.js +2 -2
- package/dist/runtime/lib/db/createDb.d.ts +1 -2
- package/dist/runtime/lib/db/createDb.js +4 -0
- package/dist/runtime/lib/db/typeInference/builders/alterTable.d.ts +13 -3
- package/dist/runtime/lib/db/typeInference/builders/columnDefinition.d.ts +35 -21
- package/dist/runtime/lib/db/typeInference/builders/createTable.d.ts +9 -2
- package/dist/runtime/lib/db/typeInference/database.d.ts +16 -2
- package/dist/runtime/lib/db/typeInference/typetests/alterTable.typetest.js +80 -5
- package/dist/runtime/lib/db/typeInference/typetests/createTable.typetest.js +104 -2
- package/dist/runtime/lib/db/typeInference/typetests/testUtils.d.ts +1 -0
- package/dist/runtime/lib/db/typeInference/utils.d.ts +59 -9
- package/dist/runtime/lib/links.d.ts +21 -7
- package/dist/runtime/lib/links.js +82 -24
- package/dist/runtime/lib/links.test.js +20 -0
- package/dist/runtime/lib/manifest.d.ts +1 -1
- package/dist/runtime/lib/manifest.js +7 -4
- package/dist/runtime/lib/realtime/client.js +8 -2
- package/dist/runtime/lib/realtime/worker.d.ts +1 -1
- package/dist/runtime/lib/router.d.ts +153 -36
- package/dist/runtime/lib/router.js +169 -20
- package/dist/runtime/lib/router.test.js +241 -0
- package/dist/runtime/lib/stitchDocumentAndAppStreams.d.ts +66 -0
- package/dist/runtime/lib/stitchDocumentAndAppStreams.js +302 -35
- package/dist/runtime/lib/stitchDocumentAndAppStreams.test.d.ts +1 -0
- package/dist/runtime/lib/stitchDocumentAndAppStreams.test.js +418 -0
- package/dist/runtime/lib/{rwContext.d.ts → types.d.ts} +1 -0
- package/dist/runtime/lib/types.js +1 -0
- package/dist/runtime/render/renderDocumentHtmlStream.d.ts +1 -1
- package/dist/runtime/render/renderToStream.d.ts +4 -2
- package/dist/runtime/render/renderToStream.js +53 -24
- package/dist/runtime/render/renderToString.d.ts +3 -6
- package/dist/runtime/requestInfo/types.d.ts +4 -1
- package/dist/runtime/requestInfo/utils.d.ts +9 -0
- package/dist/runtime/requestInfo/utils.js +44 -0
- package/dist/runtime/requestInfo/worker.d.ts +0 -1
- package/dist/runtime/requestInfo/worker.js +3 -10
- package/dist/runtime/script.d.ts +1 -3
- package/dist/runtime/script.js +1 -10
- package/dist/runtime/state.d.ts +3 -0
- package/dist/runtime/state.js +13 -0
- package/dist/runtime/worker.d.ts +3 -1
- package/dist/runtime/worker.js +32 -0
- package/dist/scripts/debug-sync.mjs +18 -20
- package/dist/scripts/worker-run.d.mts +1 -1
- package/dist/scripts/worker-run.mjs +59 -113
- package/dist/use-synced-state/SyncedStateServer.d.mts +21 -0
- package/dist/use-synced-state/SyncedStateServer.mjs +128 -0
- package/dist/use-synced-state/__tests__/SyncStateServer.test.d.mts +1 -0
- package/dist/use-synced-state/__tests__/SyncStateServer.test.mjs +109 -0
- package/dist/use-synced-state/__tests__/useSyncState.test.d.ts +1 -0
- package/dist/use-synced-state/__tests__/useSyncState.test.js +115 -0
- package/dist/use-synced-state/__tests__/useSyncedState.test.d.ts +1 -0
- package/dist/use-synced-state/__tests__/useSyncedState.test.js +115 -0
- package/dist/use-synced-state/__tests__/worker.test.d.mts +1 -0
- package/dist/use-synced-state/__tests__/worker.test.mjs +69 -0
- package/dist/use-synced-state/client-core.d.ts +26 -0
- package/dist/use-synced-state/client-core.js +39 -0
- package/dist/use-synced-state/client.d.ts +3 -0
- package/dist/use-synced-state/client.js +4 -0
- package/dist/use-synced-state/constants.d.mts +1 -0
- package/dist/use-synced-state/constants.mjs +1 -0
- package/dist/use-synced-state/useSyncedState.d.ts +20 -0
- package/dist/use-synced-state/useSyncedState.js +58 -0
- package/dist/use-synced-state/worker.d.mts +13 -0
- package/dist/use-synced-state/worker.mjs +69 -0
- package/dist/vite/buildApp.mjs +34 -2
- package/dist/vite/cloudflarePreInitPlugin.d.mts +11 -0
- package/dist/vite/cloudflarePreInitPlugin.mjs +40 -0
- package/dist/vite/configPlugin.mjs +9 -14
- package/dist/vite/constants.d.mts +1 -0
- package/dist/vite/constants.mjs +1 -0
- package/dist/vite/createDirectiveLookupPlugin.mjs +10 -7
- package/dist/vite/devServerTimingPlugin.mjs +4 -0
- package/dist/vite/diagnosticAssetGraphPlugin.d.mts +4 -0
- package/dist/vite/diagnosticAssetGraphPlugin.mjs +41 -0
- package/dist/vite/directiveModulesDevPlugin.mjs +9 -1
- package/dist/vite/directivesPlugin.mjs +4 -4
- package/dist/vite/envResolvers.d.mts +11 -0
- package/dist/vite/envResolvers.mjs +20 -0
- package/dist/vite/getViteEsbuild.mjs +2 -1
- package/dist/vite/hmrStabilityPlugin.d.mts +2 -0
- package/dist/vite/hmrStabilityPlugin.mjs +73 -0
- package/dist/vite/injectVitePreamblePlugin.mjs +0 -4
- package/dist/vite/knownDepsResolverPlugin.d.mts +0 -6
- package/dist/vite/knownDepsResolverPlugin.mjs +25 -17
- package/dist/vite/linkerPlugin.d.mts +2 -1
- package/dist/vite/linkerPlugin.mjs +11 -3
- package/dist/vite/linkerPlugin.test.mjs +15 -0
- package/dist/vite/miniflareHMRPlugin.mjs +6 -38
- package/dist/vite/moveStaticAssetsPlugin.mjs +35 -4
- package/dist/vite/redwoodPlugin.mjs +8 -10
- package/dist/vite/runDirectivesScan.mjs +72 -18
- package/dist/vite/ssrBridgePlugin.mjs +132 -40
- package/dist/vite/ssrBridgeWrapPlugin.d.mts +2 -0
- package/dist/vite/ssrBridgeWrapPlugin.mjs +85 -0
- package/dist/vite/staleDepRetryPlugin.d.mts +2 -0
- package/dist/vite/staleDepRetryPlugin.mjs +74 -0
- package/dist/vite/statePlugin.d.mts +4 -0
- package/dist/vite/statePlugin.mjs +62 -0
- package/dist/vite/transformJsxScriptTagsPlugin.mjs +0 -5
- package/dist/vite/virtualPlugin.mjs +6 -7
- package/package.json +27 -10
- package/dist/vite/manifestPlugin.d.mts +0 -4
- package/dist/vite/manifestPlugin.mjs +0 -63
- /package/dist/runtime/lib/{rwContext.js → links.test.d.ts} +0 -0
|
@@ -71,6 +71,8 @@ describe("defineRoutes - Request Handling Behavior", () => {
|
|
|
71
71
|
ssr: true,
|
|
72
72
|
databases: new Map(),
|
|
73
73
|
scriptsToBeLoaded: new Set(),
|
|
74
|
+
entryScripts: new Set(),
|
|
75
|
+
inlineScripts: new Set(),
|
|
74
76
|
pageRouteResolved: undefined,
|
|
75
77
|
},
|
|
76
78
|
cf: {},
|
|
@@ -593,6 +595,245 @@ describe("defineRoutes - Request Handling Behavior", () => {
|
|
|
593
595
|
expect(extractedParams).toEqual({ id: "123" });
|
|
594
596
|
});
|
|
595
597
|
});
|
|
598
|
+
describe("HTTP Method Routing", () => {
|
|
599
|
+
it("should route GET request to get handler", async () => {
|
|
600
|
+
const router = defineRoutes([
|
|
601
|
+
route("/test/", {
|
|
602
|
+
get: () => new Response("GET Response"),
|
|
603
|
+
post: () => new Response("POST Response"),
|
|
604
|
+
}),
|
|
605
|
+
]);
|
|
606
|
+
const deps = createMockDependencies();
|
|
607
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/test/", {
|
|
608
|
+
method: "GET",
|
|
609
|
+
});
|
|
610
|
+
const request = new Request("http://localhost:3000/test/", {
|
|
611
|
+
method: "GET",
|
|
612
|
+
});
|
|
613
|
+
const response = await router.handle({
|
|
614
|
+
request,
|
|
615
|
+
renderPage: deps.mockRenderPage,
|
|
616
|
+
getRequestInfo: deps.getRequestInfo,
|
|
617
|
+
onError: deps.onError,
|
|
618
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
619
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
620
|
+
});
|
|
621
|
+
expect(await response.text()).toBe("GET Response");
|
|
622
|
+
});
|
|
623
|
+
it("should route POST request to post handler", async () => {
|
|
624
|
+
const router = defineRoutes([
|
|
625
|
+
route("/test/", {
|
|
626
|
+
get: () => new Response("GET Response"),
|
|
627
|
+
post: () => new Response("POST Response"),
|
|
628
|
+
}),
|
|
629
|
+
]);
|
|
630
|
+
const deps = createMockDependencies();
|
|
631
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/test/", {
|
|
632
|
+
method: "POST",
|
|
633
|
+
});
|
|
634
|
+
const request = new Request("http://localhost:3000/test/", {
|
|
635
|
+
method: "POST",
|
|
636
|
+
});
|
|
637
|
+
const response = await router.handle({
|
|
638
|
+
request,
|
|
639
|
+
renderPage: deps.mockRenderPage,
|
|
640
|
+
getRequestInfo: deps.getRequestInfo,
|
|
641
|
+
onError: deps.onError,
|
|
642
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
643
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
644
|
+
});
|
|
645
|
+
expect(await response.text()).toBe("POST Response");
|
|
646
|
+
});
|
|
647
|
+
it("should return 405 for unsupported method with Allow header", async () => {
|
|
648
|
+
const router = defineRoutes([
|
|
649
|
+
route("/test/", {
|
|
650
|
+
get: () => new Response("GET Response"),
|
|
651
|
+
post: () => new Response("POST Response"),
|
|
652
|
+
}),
|
|
653
|
+
]);
|
|
654
|
+
const deps = createMockDependencies();
|
|
655
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/test/", {
|
|
656
|
+
method: "DELETE",
|
|
657
|
+
});
|
|
658
|
+
const request = new Request("http://localhost:3000/test/", {
|
|
659
|
+
method: "DELETE",
|
|
660
|
+
});
|
|
661
|
+
const response = await router.handle({
|
|
662
|
+
request,
|
|
663
|
+
renderPage: deps.mockRenderPage,
|
|
664
|
+
getRequestInfo: deps.getRequestInfo,
|
|
665
|
+
onError: deps.onError,
|
|
666
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
667
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
668
|
+
});
|
|
669
|
+
expect(response.status).toBe(405);
|
|
670
|
+
expect(await response.text()).toBe("Method Not Allowed");
|
|
671
|
+
expect(response.headers.get("Allow")).toBe("GET, OPTIONS, POST");
|
|
672
|
+
});
|
|
673
|
+
it("should handle OPTIONS request with Allow header", async () => {
|
|
674
|
+
const router = defineRoutes([
|
|
675
|
+
route("/test/", {
|
|
676
|
+
get: () => new Response("GET Response"),
|
|
677
|
+
post: () => new Response("POST Response"),
|
|
678
|
+
}),
|
|
679
|
+
]);
|
|
680
|
+
const deps = createMockDependencies();
|
|
681
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/test/", {
|
|
682
|
+
method: "OPTIONS",
|
|
683
|
+
});
|
|
684
|
+
const request = new Request("http://localhost:3000/test/", {
|
|
685
|
+
method: "OPTIONS",
|
|
686
|
+
});
|
|
687
|
+
const response = await router.handle({
|
|
688
|
+
request,
|
|
689
|
+
renderPage: deps.mockRenderPage,
|
|
690
|
+
getRequestInfo: deps.getRequestInfo,
|
|
691
|
+
onError: deps.onError,
|
|
692
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
693
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
694
|
+
});
|
|
695
|
+
expect(response.status).toBe(204);
|
|
696
|
+
expect(response.headers.get("Allow")).toBe("GET, OPTIONS, POST");
|
|
697
|
+
});
|
|
698
|
+
it("should support custom methods (case-insensitive)", async () => {
|
|
699
|
+
const router = defineRoutes([
|
|
700
|
+
route("/test/", {
|
|
701
|
+
custom: {
|
|
702
|
+
report: () => new Response("REPORT Response"),
|
|
703
|
+
},
|
|
704
|
+
}),
|
|
705
|
+
]);
|
|
706
|
+
const deps = createMockDependencies();
|
|
707
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/test/", {
|
|
708
|
+
method: "REPORT",
|
|
709
|
+
});
|
|
710
|
+
const request = new Request("http://localhost:3000/test/", {
|
|
711
|
+
method: "REPORT",
|
|
712
|
+
});
|
|
713
|
+
const response = await router.handle({
|
|
714
|
+
request,
|
|
715
|
+
renderPage: deps.mockRenderPage,
|
|
716
|
+
getRequestInfo: deps.getRequestInfo,
|
|
717
|
+
onError: deps.onError,
|
|
718
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
719
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
720
|
+
});
|
|
721
|
+
expect(await response.text()).toBe("REPORT Response");
|
|
722
|
+
});
|
|
723
|
+
it("should normalize custom method keys to lowercase", async () => {
|
|
724
|
+
const router = defineRoutes([
|
|
725
|
+
route("/test/", {
|
|
726
|
+
custom: {
|
|
727
|
+
REPORT: () => new Response("REPORT Response"),
|
|
728
|
+
},
|
|
729
|
+
}),
|
|
730
|
+
]);
|
|
731
|
+
const deps = createMockDependencies();
|
|
732
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/test/", {
|
|
733
|
+
method: "report",
|
|
734
|
+
});
|
|
735
|
+
const request = new Request("http://localhost:3000/test/", {
|
|
736
|
+
method: "report",
|
|
737
|
+
});
|
|
738
|
+
const response = await router.handle({
|
|
739
|
+
request,
|
|
740
|
+
renderPage: deps.mockRenderPage,
|
|
741
|
+
getRequestInfo: deps.getRequestInfo,
|
|
742
|
+
onError: deps.onError,
|
|
743
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
744
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
745
|
+
});
|
|
746
|
+
expect(await response.text()).toBe("REPORT Response");
|
|
747
|
+
});
|
|
748
|
+
it("should disable 405 when config.disable405 is true", async () => {
|
|
749
|
+
const router = defineRoutes([
|
|
750
|
+
route("/test/", {
|
|
751
|
+
get: () => new Response("GET Response"),
|
|
752
|
+
config: {
|
|
753
|
+
disable405: true,
|
|
754
|
+
},
|
|
755
|
+
}),
|
|
756
|
+
]);
|
|
757
|
+
const deps = createMockDependencies();
|
|
758
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/test/", {
|
|
759
|
+
method: "POST",
|
|
760
|
+
});
|
|
761
|
+
const request = new Request("http://localhost:3000/test/", {
|
|
762
|
+
method: "POST",
|
|
763
|
+
});
|
|
764
|
+
const response = await router.handle({
|
|
765
|
+
request,
|
|
766
|
+
renderPage: deps.mockRenderPage,
|
|
767
|
+
getRequestInfo: deps.getRequestInfo,
|
|
768
|
+
onError: deps.onError,
|
|
769
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
770
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
771
|
+
});
|
|
772
|
+
expect(response.status).toBe(404);
|
|
773
|
+
expect(await response.text()).toBe("Not Found");
|
|
774
|
+
});
|
|
775
|
+
it("should disable OPTIONS when config.disableOptions is true", async () => {
|
|
776
|
+
const router = defineRoutes([
|
|
777
|
+
route("/test/", {
|
|
778
|
+
get: () => new Response("GET Response"),
|
|
779
|
+
post: () => new Response("POST Response"),
|
|
780
|
+
config: {
|
|
781
|
+
disableOptions: true,
|
|
782
|
+
},
|
|
783
|
+
}),
|
|
784
|
+
]);
|
|
785
|
+
const deps = createMockDependencies();
|
|
786
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/test/", {
|
|
787
|
+
method: "OPTIONS",
|
|
788
|
+
});
|
|
789
|
+
const request = new Request("http://localhost:3000/test/", {
|
|
790
|
+
method: "OPTIONS",
|
|
791
|
+
});
|
|
792
|
+
const response = await router.handle({
|
|
793
|
+
request,
|
|
794
|
+
renderPage: deps.mockRenderPage,
|
|
795
|
+
getRequestInfo: deps.getRequestInfo,
|
|
796
|
+
onError: deps.onError,
|
|
797
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
798
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
799
|
+
});
|
|
800
|
+
expect(response.status).toBe(405);
|
|
801
|
+
expect(await response.text()).toBe("Method Not Allowed");
|
|
802
|
+
expect(response.headers.get("Allow")).toBe("GET, POST");
|
|
803
|
+
});
|
|
804
|
+
it("should support middleware arrays in method handlers", async () => {
|
|
805
|
+
const executionOrder = [];
|
|
806
|
+
const authMiddleware = () => {
|
|
807
|
+
executionOrder.push("authMiddleware");
|
|
808
|
+
};
|
|
809
|
+
const getHandler = () => {
|
|
810
|
+
executionOrder.push("getHandler");
|
|
811
|
+
return new Response("GET Response");
|
|
812
|
+
};
|
|
813
|
+
const router = defineRoutes([
|
|
814
|
+
route("/test/", {
|
|
815
|
+
get: [authMiddleware, getHandler],
|
|
816
|
+
}),
|
|
817
|
+
]);
|
|
818
|
+
const deps = createMockDependencies();
|
|
819
|
+
deps.mockRequestInfo.request = new Request("http://localhost:3000/test/", {
|
|
820
|
+
method: "GET",
|
|
821
|
+
});
|
|
822
|
+
const request = new Request("http://localhost:3000/test/", {
|
|
823
|
+
method: "GET",
|
|
824
|
+
});
|
|
825
|
+
const response = await router.handle({
|
|
826
|
+
request,
|
|
827
|
+
renderPage: deps.mockRenderPage,
|
|
828
|
+
getRequestInfo: deps.getRequestInfo,
|
|
829
|
+
onError: deps.onError,
|
|
830
|
+
runWithRequestInfoOverrides: deps.mockRunWithRequestInfoOverrides,
|
|
831
|
+
rscActionHandler: deps.mockRscActionHandler,
|
|
832
|
+
});
|
|
833
|
+
expect(executionOrder).toEqual(["authMiddleware", "getHandler"]);
|
|
834
|
+
expect(await response.text()).toBe("GET Response");
|
|
835
|
+
});
|
|
836
|
+
});
|
|
596
837
|
describe("Edge Cases", () => {
|
|
597
838
|
it("should handle middleware-only apps with RSC actions", async () => {
|
|
598
839
|
const executionOrder = [];
|
|
@@ -15,4 +15,70 @@
|
|
|
15
15
|
* @param startMarker The marker in the document to start injecting the app.
|
|
16
16
|
* @param endMarker The marker in the app stream that signals the end of the initial, non-suspended render.
|
|
17
17
|
*/
|
|
18
|
+
/**
|
|
19
|
+
* A utility that orchestrates and interleaves three ReadableStreams to produce a
|
|
20
|
+
* single, valid HTML response stream. It uses two special markers:
|
|
21
|
+
*
|
|
22
|
+
* - `startMarker`: Placed in the `outerHtml` stream (the document shell) to
|
|
23
|
+
* designate where the application's content should be injected.
|
|
24
|
+
* - `endMarker`: Injected into the `innerHtml` stream's RSC payload to signal
|
|
25
|
+
* the end of the initial, non-suspended render. This marker is needed for
|
|
26
|
+
* non-blocking hydration, as it allows the stitching process to send the
|
|
27
|
+
* client `<script>` tags before all suspended content has resolved.
|
|
28
|
+
*
|
|
29
|
+
* It manages three main stream readers:
|
|
30
|
+
*
|
|
31
|
+
* - `hoistedTagsReader`: Reads from the `hoistedTagsStream`, which contains only
|
|
32
|
+
* the hoisted meta tags (e.g., `<title>`, `<meta>`).
|
|
33
|
+
* - `outerReader`: Reads from the `outerHtml` stream, which is the server-rendered
|
|
34
|
+
* document shell (containing `<html>`, `<head>`, etc.).
|
|
35
|
+
* - `innerReader`: Reads from the `appBodyStream`, which contains the main
|
|
36
|
+
* application content, stripped of its hoisted tags.
|
|
37
|
+
*
|
|
38
|
+
* The function proceeds through a multi-phase state machine, managed by the
|
|
39
|
+
* `pump` function, to correctly interleave these streams.
|
|
40
|
+
*
|
|
41
|
+
* The state machine moves through the following phases:
|
|
42
|
+
*
|
|
43
|
+
* 1. `read-hoisted`:
|
|
44
|
+
* - **Goal:** Buffer all hoisted tags from the `hoistedTagsStream`.
|
|
45
|
+
* - **Action:** Reads from `hoistedTagsReader` and appends all content into
|
|
46
|
+
* the `hoistedTagsBuffer`. Does not enqueue anything yet.
|
|
47
|
+
* - **Transition:** Moves to `outer-head` when the stream is exhausted.
|
|
48
|
+
*
|
|
49
|
+
* 2. `outer-head`:
|
|
50
|
+
* - **Goal:** Stream the document up to the closing `</head>` tag, inject the
|
|
51
|
+
* hoisted tags, and then continue until the app `startMarker`.
|
|
52
|
+
* - **Action:** Reads from `outerReader`. When it finds `</head>`, it enqueues
|
|
53
|
+
* the content before it, then enqueues the `hoistedTagsBuffer`, and finally
|
|
54
|
+
* enqueues the `</head>` tag itself. It then continues reading from
|
|
55
|
+
* `outerReader` until it finds the `startMarker`.
|
|
56
|
+
* - **Transition:** Moves to `inner-shell` after finding and discarding the
|
|
57
|
+
* `startMarker`.
|
|
58
|
+
*
|
|
59
|
+
* 3. `inner-shell`:
|
|
60
|
+
* - **Goal:** Stream the initial, non-suspended part of the application.
|
|
61
|
+
* - **Action:** Switches to `innerReader`. It enqueues chunks until it finds
|
|
62
|
+
* the `endMarker`. Any content after the marker is stored in
|
|
63
|
+
* `innerSuspendedRemains`.
|
|
64
|
+
* - **Transition:** Moves to `outer-tail` after finding the `endMarker`.
|
|
65
|
+
*
|
|
66
|
+
* 4. `outer-tail`:
|
|
67
|
+
* - **Goal:** Stream the rest of the document's `<body>`, including client
|
|
68
|
+
* `<script>` tags.
|
|
69
|
+
* - **Action:** Switches back to `outerReader` and enqueues chunks until it
|
|
70
|
+
* finds the `</body>` tag.
|
|
71
|
+
* - **Transition:** Moves to `inner-suspended` after finding `</body>`.
|
|
72
|
+
*
|
|
73
|
+
* 5. `inner-suspended`:
|
|
74
|
+
* - **Goal:** Stream any suspended content from the React app.
|
|
75
|
+
* - **Action:** First enqueues any content from `innerSuspendedRemains`, then
|
|
76
|
+
* continues reading from `innerReader` until the stream is exhausted.
|
|
77
|
+
* - **Transition:** Moves to `outer-end` when the stream is exhausted.
|
|
78
|
+
*
|
|
79
|
+
* 6. `outer-end`:
|
|
80
|
+
* - **Goal:** Finish the document.
|
|
81
|
+
* - **Action:** Switches back to `outerReader` for the last time to send the
|
|
82
|
+
* closing `</body>` and `</html>` tags.
|
|
83
|
+
*/
|
|
18
84
|
export declare function stitchDocumentAndAppStreams(outerHtml: ReadableStream<Uint8Array>, innerHtml: ReadableStream<Uint8Array>, startMarker: string, endMarker: string): ReadableStream<Uint8Array>;
|