rwsdk 0.1.16 → 0.1.17
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/$.d.mts +8 -0
- package/dist/lib/$.mjs +5 -0
- package/dist/lib/compileTsModule.d.mts +1 -0
- package/dist/lib/compileTsModule.mjs +27 -0
- package/dist/lib/constants.d.mts +4 -0
- package/dist/lib/constants.mjs +6 -0
- package/dist/lib/findWranglerConfig.d.mts +1 -0
- package/dist/lib/findWranglerConfig.mjs +12 -0
- package/dist/lib/getShortName.d.mts +1 -0
- package/dist/lib/getShortName.mjs +2 -0
- package/dist/lib/getSrcPaths.d.ts +15 -0
- package/dist/lib/getSrcPaths.js +80 -0
- package/dist/lib/hasPkgScript.d.mts +1 -0
- package/dist/lib/hasPkgScript.mjs +9 -0
- package/dist/lib/jsonUtils.d.mts +28 -0
- package/dist/lib/jsonUtils.mjs +167 -0
- package/dist/lib/setupEnvFiles.d.mts +4 -0
- package/dist/lib/setupEnvFiles.mjs +31 -0
- package/dist/lib/smokeTests/artifacts.d.mts +10 -0
- package/dist/lib/smokeTests/artifacts.mjs +164 -0
- package/dist/lib/smokeTests/browser.d.mts +48 -0
- package/dist/lib/smokeTests/browser.mjs +1041 -0
- package/dist/lib/smokeTests/cleanup.d.mts +5 -0
- package/dist/lib/smokeTests/cleanup.mjs +214 -0
- package/dist/lib/smokeTests/codeUpdates.d.mts +8 -0
- package/dist/lib/smokeTests/codeUpdates.mjs +229 -0
- package/dist/lib/smokeTests/constants.d.mts +5 -0
- package/dist/lib/smokeTests/constants.mjs +10 -0
- package/dist/lib/smokeTests/development.d.mts +11 -0
- package/dist/lib/smokeTests/development.mjs +209 -0
- package/dist/lib/smokeTests/environment.d.mts +14 -0
- package/dist/lib/smokeTests/environment.mjs +163 -0
- package/dist/lib/smokeTests/release.d.mts +61 -0
- package/dist/lib/smokeTests/release.mjs +526 -0
- package/dist/lib/smokeTests/reporting.d.mts +13 -0
- package/dist/lib/smokeTests/reporting.mjs +355 -0
- package/dist/lib/smokeTests/runSmokeTests.d.mts +5 -0
- package/dist/lib/smokeTests/runSmokeTests.mjs +144 -0
- package/dist/lib/smokeTests/state.d.mts +48 -0
- package/dist/lib/smokeTests/state.mjs +57 -0
- package/dist/lib/smokeTests/templates/SmokeTest.template.d.ts +1 -0
- package/dist/lib/smokeTests/templates/SmokeTest.template.js +81 -0
- package/dist/lib/smokeTests/templates/SmokeTestClient.template.d.ts +1 -0
- package/dist/lib/smokeTests/templates/SmokeTestClient.template.js +159 -0
- package/dist/lib/smokeTests/templates/smokeTestFunctions.template.d.ts +1 -0
- package/dist/lib/smokeTests/templates/smokeTestFunctions.template.js +19 -0
- package/dist/lib/smokeTests/types.d.mts +75 -0
- package/dist/lib/smokeTests/types.mjs +1 -0
- package/dist/lib/smokeTests/utils.d.mts +15 -0
- package/dist/lib/smokeTests/utils.mjs +147 -0
- package/dist/llms/index.d.ts +3 -0
- package/dist/llms/index.js +35 -0
- package/dist/llms/rules/interruptors.d.ts +1 -0
- package/dist/llms/rules/interruptors.js +243 -0
- package/dist/llms/rules/middleware.d.ts +1 -0
- package/dist/llms/rules/middleware.js +71 -0
- package/dist/llms/rules/react.d.ts +1 -0
- package/dist/llms/rules/react.js +106 -0
- package/dist/llms/rules/request-response.d.ts +1 -0
- package/dist/llms/rules/request-response.js +209 -0
- package/dist/runtime/client.d.ts +17 -0
- package/dist/runtime/client.js +74 -0
- package/dist/runtime/clientNavigation.d.ts +4 -0
- package/dist/runtime/clientNavigation.js +53 -0
- package/dist/runtime/clientNavigation.test.d.ts +1 -0
- package/dist/runtime/clientNavigation.test.js +55 -0
- package/dist/runtime/constants.d.ts +1 -0
- package/dist/runtime/constants.js +1 -0
- package/dist/runtime/entries/auth.d.ts +1 -0
- package/dist/runtime/entries/auth.js +1 -0
- package/dist/runtime/entries/client.d.ts +4 -0
- package/dist/runtime/entries/client.js +4 -0
- package/dist/runtime/entries/clientSSR.d.ts +1 -0
- package/dist/runtime/entries/clientSSR.js +1 -0
- package/dist/runtime/entries/navigation.d.ts +1 -0
- package/dist/runtime/entries/navigation.js +1 -0
- package/dist/runtime/entries/no-react-server.d.ts +0 -0
- package/dist/runtime/entries/no-react-server.js +2 -0
- package/dist/runtime/entries/react-server-only.d.ts +0 -0
- package/dist/runtime/entries/react-server-only.js +2 -0
- package/dist/runtime/entries/router.d.ts +2 -0
- package/dist/runtime/entries/router.js +2 -0
- package/dist/runtime/entries/ssr.d.ts +1 -0
- package/dist/runtime/entries/ssr.js +1 -0
- package/dist/runtime/entries/worker.d.ts +9 -0
- package/dist/runtime/entries/worker.js +9 -0
- package/dist/runtime/error.d.ts +6 -0
- package/dist/runtime/error.js +8 -0
- package/dist/runtime/imports/ClientOnly.d.ts +3 -0
- package/dist/runtime/imports/ClientOnly.js +8 -0
- package/dist/runtime/imports/client.d.ts +4 -0
- package/dist/runtime/imports/client.js +33 -0
- package/dist/runtime/imports/ssr.d.ts +5 -0
- package/dist/runtime/imports/ssr.js +20 -0
- package/dist/runtime/imports/worker.d.ts +5 -0
- package/dist/runtime/imports/worker.js +22 -0
- package/dist/runtime/lib/auth/index.d.ts +1 -0
- package/dist/runtime/lib/auth/index.js +1 -0
- package/dist/runtime/lib/auth/session.d.ts +50 -0
- package/dist/runtime/lib/auth/session.js +148 -0
- package/dist/runtime/lib/db/DOWorkerDialect.d.ts +29 -0
- package/dist/runtime/lib/db/DOWorkerDialect.js +66 -0
- package/dist/runtime/lib/db/SqliteDurableObject.d.ts +14 -0
- package/dist/runtime/lib/db/SqliteDurableObject.js +42 -0
- package/dist/runtime/lib/db/createDb.d.ts +2 -0
- package/dist/runtime/lib/db/createDb.js +33 -0
- package/dist/runtime/lib/db/index.d.ts +4 -0
- package/dist/runtime/lib/db/index.js +3 -0
- package/dist/runtime/lib/db/migrations.d.ts +23 -0
- package/dist/runtime/lib/db/migrations.js +34 -0
- package/dist/runtime/lib/db/typeInference/assert.d.ts +2 -0
- package/dist/runtime/lib/db/typeInference/assert.js +1 -0
- package/dist/runtime/lib/db/typeInference/builders/alterColumn.d.ts +27 -0
- package/dist/runtime/lib/db/typeInference/builders/alterColumn.js +1 -0
- package/dist/runtime/lib/db/typeInference/builders/alterTable.d.ts +53 -0
- package/dist/runtime/lib/db/typeInference/builders/alterTable.js +1 -0
- package/dist/runtime/lib/db/typeInference/builders/columnDefinition.d.ts +26 -0
- package/dist/runtime/lib/db/typeInference/builders/columnDefinition.js +1 -0
- package/dist/runtime/lib/db/typeInference/builders/createTable.d.ts +49 -0
- package/dist/runtime/lib/db/typeInference/builders/createTable.js +1 -0
- package/dist/runtime/lib/db/typeInference/builders/createView.d.ts +17 -0
- package/dist/runtime/lib/db/typeInference/builders/createView.js +1 -0
- package/dist/runtime/lib/db/typeInference/builders/dropTable.d.ts +11 -0
- package/dist/runtime/lib/db/typeInference/builders/dropTable.js +1 -0
- package/dist/runtime/lib/db/typeInference/builders/dropView.d.ts +12 -0
- package/dist/runtime/lib/db/typeInference/builders/dropView.js +1 -0
- package/dist/runtime/lib/db/typeInference/builders/schema.d.ts +24 -0
- package/dist/runtime/lib/db/typeInference/builders/schema.js +1 -0
- package/dist/runtime/lib/db/typeInference/database.d.ts +27 -0
- package/dist/runtime/lib/db/typeInference/database.js +1 -0
- package/dist/runtime/lib/db/typeInference/typetests/alterTable.typetest.d.ts +1 -0
- package/dist/runtime/lib/db/typeInference/typetests/alterTable.typetest.js +360 -0
- package/dist/runtime/lib/db/typeInference/typetests/createTable.typetest.d.ts +1 -0
- package/dist/runtime/lib/db/typeInference/typetests/createTable.typetest.js +33 -0
- package/dist/runtime/lib/db/typeInference/typetests/dropTable.typetest.d.ts +1 -0
- package/dist/runtime/lib/db/typeInference/typetests/dropTable.typetest.js +143 -0
- package/dist/runtime/lib/db/typeInference/typetests/print.d.ts +3 -0
- package/dist/runtime/lib/db/typeInference/typetests/print.js +1 -0
- package/dist/runtime/lib/db/typeInference/typetests/testUtils.d.ts +2 -0
- package/dist/runtime/lib/db/typeInference/typetests/testUtils.js +1 -0
- package/dist/runtime/lib/db/typeInference/typetests/typeInference.typetest.d.ts +1 -0
- package/dist/runtime/lib/db/typeInference/typetests/typeInference.typetest.js +17 -0
- package/dist/runtime/lib/db/typeInference/utils.d.ts +82 -0
- package/dist/runtime/lib/db/typeInference/utils.js +2 -0
- package/dist/runtime/lib/debug.d.ts +2 -0
- package/dist/runtime/lib/debug.js +36 -0
- package/dist/runtime/lib/links.d.ts +14 -0
- package/dist/runtime/lib/links.js +38 -0
- package/dist/runtime/lib/realtime/client.d.ts +7 -0
- package/dist/runtime/lib/realtime/client.js +166 -0
- package/dist/runtime/lib/realtime/constants.d.ts +1 -0
- package/dist/runtime/lib/realtime/constants.js +1 -0
- package/dist/runtime/lib/realtime/durableObject.d.ts +29 -0
- package/dist/runtime/lib/realtime/durableObject.js +187 -0
- package/dist/runtime/lib/realtime/renderRealtimeClients.d.ts +7 -0
- package/dist/runtime/lib/realtime/renderRealtimeClients.js +6 -0
- package/dist/runtime/lib/realtime/shared.d.ts +10 -0
- package/dist/runtime/lib/realtime/shared.js +10 -0
- package/dist/runtime/lib/realtime/validateUpgradeRequest.d.ts +6 -0
- package/dist/runtime/lib/realtime/validateUpgradeRequest.js +29 -0
- package/dist/runtime/lib/realtime/worker.d.ts +3 -0
- package/dist/runtime/lib/realtime/worker.js +16 -0
- package/dist/runtime/lib/router.d.ts +56 -0
- package/dist/runtime/lib/router.js +210 -0
- package/dist/runtime/lib/router.test.d.ts +1 -0
- package/dist/runtime/lib/router.test.js +58 -0
- package/dist/runtime/lib/streams/consumeEventStream.d.ts +4 -0
- package/dist/runtime/lib/streams/consumeEventStream.js +13 -0
- package/dist/runtime/lib/turnstile/TurnstileScript.d.ts +1 -0
- package/dist/runtime/lib/turnstile/TurnstileScript.js +2 -0
- package/dist/runtime/lib/turnstile/turnstile.d.ts +3 -0
- package/dist/runtime/lib/turnstile/turnstile.js +3 -0
- package/dist/runtime/lib/turnstile/useTurnstile.d.ts +4 -0
- package/dist/runtime/lib/turnstile/useTurnstile.js +23 -0
- package/dist/runtime/lib/turnstile/verifyTurnstileToken.d.ts +4 -0
- package/dist/runtime/lib/turnstile/verifyTurnstileToken.js +15 -0
- package/dist/runtime/lib/utils.d.ts +1 -0
- package/dist/runtime/lib/utils.js +1 -0
- package/dist/runtime/register/client.d.ts +1 -0
- package/dist/runtime/register/client.js +5 -0
- package/dist/runtime/register/ssr.d.ts +3 -0
- package/dist/runtime/register/ssr.js +26 -0
- package/dist/runtime/register/worker.d.ts +4 -0
- package/dist/runtime/register/worker.js +42 -0
- package/dist/runtime/render/createClientManifest.d.ts +1 -0
- package/dist/runtime/render/createClientManifest.js +7 -0
- package/dist/runtime/render/createModuleMap.d.ts +1 -0
- package/dist/runtime/render/createModuleMap.js +13 -0
- package/dist/runtime/render/injectRSCPayload.d.ts +3 -0
- package/dist/runtime/render/injectRSCPayload.js +79 -0
- package/dist/runtime/render/renderRscThenableToHtmlStream.d.ts +9 -0
- package/dist/runtime/render/renderRscThenableToHtmlStream.js +49 -0
- package/dist/runtime/render/renderToRscStream.d.ts +5 -0
- package/dist/runtime/render/renderToRscStream.js +46 -0
- package/dist/runtime/render/renderToStream.d.ts +9 -0
- package/dist/runtime/render/renderToStream.js +27 -0
- package/dist/runtime/render/renderToString.d.ts +7 -0
- package/dist/runtime/render/renderToString.js +26 -0
- package/dist/runtime/render/transformRscToHtmlStream.d.ts +8 -0
- package/dist/runtime/render/transformRscToHtmlStream.js +19 -0
- package/dist/runtime/requestInfo/types.d.ts +11 -0
- package/dist/runtime/requestInfo/types.js +1 -0
- package/dist/runtime/requestInfo/worker.d.ts +5 -0
- package/dist/runtime/requestInfo/worker.js +33 -0
- package/dist/runtime/script.d.ts +5 -0
- package/dist/runtime/script.js +8 -0
- package/dist/runtime/ssrBridge.d.ts +2 -0
- package/dist/runtime/ssrBridge.js +11 -0
- package/dist/runtime/worker.d.ts +18 -0
- package/dist/runtime/worker.js +173 -0
- package/dist/scripts/__sdk.d.mts +1 -0
- package/dist/scripts/__sdk.mjs +14 -0
- package/dist/scripts/build-vendor-bundles.d.mts +1 -0
- package/dist/scripts/build-vendor-bundles.mjs +92 -0
- package/dist/scripts/debug-sync.d.mts +6 -0
- package/dist/scripts/debug-sync.mjs +224 -0
- package/dist/scripts/dev-init.d.mts +1 -0
- package/dist/scripts/dev-init.mjs +25 -0
- package/dist/scripts/ensure-deploy-env.d.mts +1 -0
- package/dist/scripts/ensure-deploy-env.mjs +271 -0
- package/dist/scripts/ensure-env.d.mts +1 -0
- package/dist/scripts/ensure-env.mjs +9 -0
- package/dist/scripts/migrate-new.d.mts +1 -0
- package/dist/scripts/migrate-new.mjs +51 -0
- package/dist/scripts/smoke-test.d.mts +1 -0
- package/dist/scripts/smoke-test.mjs +166 -0
- package/dist/scripts/worker-run.d.mts +1 -0
- package/dist/scripts/worker-run.mjs +82 -0
- package/dist/vite/aliasByEnvPlugin.d.mts +2 -0
- package/dist/vite/aliasByEnvPlugin.mjs +11 -0
- package/dist/vite/asyncSetupPlugin.d.mts +6 -0
- package/dist/vite/asyncSetupPlugin.mjs +23 -0
- package/dist/vite/checkIsUsingPrisma.d.mts +6 -0
- package/dist/vite/checkIsUsingPrisma.mjs +18 -0
- package/dist/vite/configPlugin.d.mts +9 -0
- package/dist/vite/configPlugin.mjs +169 -0
- package/dist/vite/copyPrismaWasmPlugin.d.mts +4 -0
- package/dist/vite/copyPrismaWasmPlugin.mjs +32 -0
- package/dist/vite/createDirectiveLookupPlugin.d.mts +21 -0
- package/dist/vite/createDirectiveLookupPlugin.mjs +231 -0
- package/dist/vite/customReactBuildPlugin.d.mts +4 -0
- package/dist/vite/customReactBuildPlugin.mjs +61 -0
- package/dist/vite/devServerTimingPlugin.d.mts +2 -0
- package/dist/vite/devServerTimingPlugin.mjs +24 -0
- package/dist/vite/directivesPlugin.d.mts +6 -0
- package/dist/vite/directivesPlugin.mjs +200 -0
- package/dist/vite/ensureAliasArray.d.mts +2 -0
- package/dist/vite/ensureAliasArray.mjs +17 -0
- package/dist/vite/findSpecifiers.d.mts +31 -0
- package/dist/vite/findSpecifiers.mjs +230 -0
- package/dist/vite/findSsrSpecifiers.d.mts +11 -0
- package/dist/vite/findSsrSpecifiers.mjs +67 -0
- package/dist/vite/hasDirective.d.mts +7 -0
- package/dist/vite/hasDirective.mjs +54 -0
- package/dist/vite/hasOwnCloudflareVitePlugin.d.mts +3 -0
- package/dist/vite/hasOwnCloudflareVitePlugin.mjs +14 -0
- package/dist/vite/index.d.mts +1 -0
- package/dist/vite/index.mjs +1 -0
- package/dist/vite/injectHmrPreambleJsxPlugin.d.mts +2 -0
- package/dist/vite/injectHmrPreambleJsxPlugin.mjs +22 -0
- package/dist/vite/injectVitePreamblePlugin.d.mts +4 -0
- package/dist/vite/injectVitePreamblePlugin.mjs +23 -0
- package/dist/vite/invalidateCacheIfPrismaClientChanged.d.mts +3 -0
- package/dist/vite/invalidateCacheIfPrismaClientChanged.mjs +27 -0
- package/dist/vite/invalidateModule.d.mts +6 -0
- package/dist/vite/invalidateModule.mjs +30 -0
- package/dist/vite/miniflareHMRPlugin.d.mts +10 -0
- package/dist/vite/miniflareHMRPlugin.mjs +209 -0
- package/dist/vite/miniflarePlugin.d.mts +9 -0
- package/dist/vite/miniflarePlugin.mjs +135 -0
- package/dist/vite/moveStaticAssetsPlugin.d.mts +4 -0
- package/dist/vite/moveStaticAssetsPlugin.mjs +12 -0
- package/dist/vite/normalizeModulePath.d.mts +1 -0
- package/dist/vite/normalizeModulePath.mjs +13 -0
- package/dist/vite/prismaPlugin.d.mts +4 -0
- package/dist/vite/prismaPlugin.mjs +43 -0
- package/dist/vite/reactConditionsResolverPlugin.d.mts +16 -0
- package/dist/vite/reactConditionsResolverPlugin.mjs +179 -0
- package/dist/vite/redwoodPlugin.d.mts +12 -0
- package/dist/vite/redwoodPlugin.mjs +105 -0
- package/dist/vite/requestUtils.d.mts +6 -0
- package/dist/vite/requestUtils.mjs +35 -0
- package/dist/vite/setupEnvFiles.d.mts +4 -0
- package/dist/vite/setupEnvFiles.mjs +31 -0
- package/dist/vite/ssrBridgePlugin.d.mts +7 -0
- package/dist/vite/ssrBridgePlugin.mjs +137 -0
- package/dist/vite/transformClientComponents.d.mts +12 -0
- package/dist/vite/transformClientComponents.mjs +116 -0
- package/dist/vite/transformClientComponents.test.d.mts +1 -0
- package/dist/vite/transformClientComponents.test.mjs +264 -0
- package/dist/vite/transformJsxScriptTagsPlugin.d.mts +8 -0
- package/dist/vite/transformJsxScriptTagsPlugin.mjs +315 -0
- package/dist/vite/transformJsxScriptTagsPlugin.test.d.mts +1 -0
- package/dist/vite/transformJsxScriptTagsPlugin.test.mjs +334 -0
- package/dist/vite/transformServerFunctions.d.mts +16 -0
- package/dist/vite/transformServerFunctions.mjs +296 -0
- package/dist/vite/transformServerFunctions.test.d.mts +1 -0
- package/dist/vite/transformServerFunctions.test.mjs +124 -0
- package/dist/vite/useClientLookupPlugin.d.mts +5 -0
- package/dist/vite/useClientLookupPlugin.mjs +15 -0
- package/dist/vite/useClientPlugin.d.mts +8 -0
- package/dist/vite/useClientPlugin.mjs +295 -0
- package/dist/vite/useClientPlugin.test.d.mts +1 -0
- package/dist/vite/useClientPlugin.test.mjs +1204 -0
- package/dist/vite/useServerLookupPlugin.d.mts +5 -0
- package/dist/vite/useServerLookupPlugin.mjs +15 -0
- package/dist/vite/useServerPlugin.d.mts +1 -0
- package/dist/vite/useServerPlugin.mjs +1 -0
- package/dist/vite/virtualPlugin.d.mts +2 -0
- package/dist/vite/virtualPlugin.mjs +18 -0
- package/dist/vite/vitePreamblePlugin.d.mts +1 -0
- package/dist/vite/vitePreamblePlugin.mjs +11 -0
- package/dist/worker/__ssr_bridge.js +8947 -0
- package/dist/worker/__ssr_bridge.js.map +1 -0
- package/package.json +1 -1
- package/dist/vite/invalidateClientModule.d.mts +0 -2
- package/dist/vite/invalidateClientModule.mjs +0 -8
- package/dist/vite/invalidateModule copy.d.mts +0 -2
- package/dist/vite/invalidateModule copy.mjs +0 -14
- package/dist/vite/invalidateSSRModule.d.mts +0 -2
- package/dist/vite/invalidateSSRModule.mjs +0 -7
- package/dist/vite/mode.d.mts +0 -5
- package/dist/vite/mode.mjs +0 -25
- package/dist/vite/modePlugin.d.mts +0 -2
- package/dist/vite/modePlugin.mjs +0 -10
- /package/dist/vite/{isJsFile.d.ts → isJsFile.d.mts} +0 -0
- /package/dist/vite/{isJsFile.js → isJsFile.mjs} +0 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Simple debug function with DEBUG environment variable filtering
|
|
2
|
+
// Supports patterns like: DEBUG=passkey:* or DEBUG=passkey:database,passkey:functions
|
|
3
|
+
function isEnabled(namespace) {
|
|
4
|
+
const debug = process.env.DEBUG;
|
|
5
|
+
if (!debug)
|
|
6
|
+
return false;
|
|
7
|
+
const patterns = debug.split(",").map((p) => p.trim());
|
|
8
|
+
for (const pattern of patterns) {
|
|
9
|
+
if (pattern.startsWith("-")) {
|
|
10
|
+
const excludePattern = pattern.slice(1);
|
|
11
|
+
if (matchesPattern(namespace, excludePattern)) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
if (matchesPattern(namespace, pattern)) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
function matchesPattern(namespace, pattern) {
|
|
23
|
+
// Convert pattern to regex (handle * wildcards)
|
|
24
|
+
const regex = pattern
|
|
25
|
+
.replace(/\*/g, ".*") // * becomes .*
|
|
26
|
+
.replace(/:/g, "\\:"); // escape colons
|
|
27
|
+
return new RegExp(`^${regex}$`).test(namespace);
|
|
28
|
+
}
|
|
29
|
+
const debug = (namespace) => {
|
|
30
|
+
return (...args) => {
|
|
31
|
+
if (isEnabled(namespace)) {
|
|
32
|
+
console.log(`[${namespace}]`, ...args);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
export default debug;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
type ParseRoute<T extends string> = T extends `${infer Start}:${infer Param}/${infer Rest}` ? {
|
|
2
|
+
[K in Param]: string;
|
|
3
|
+
} & ParseRoute<Rest> : T extends `${infer Start}:${infer Param}` ? {
|
|
4
|
+
[K in Param]: string;
|
|
5
|
+
} : T extends `${infer Start}*${infer Rest}` ? {
|
|
6
|
+
$0: string;
|
|
7
|
+
} & ParseRoute<Rest> : T extends `${infer Start}*` ? {
|
|
8
|
+
$0: string;
|
|
9
|
+
} : {};
|
|
10
|
+
type LinkFunction<T extends readonly string[]> = {
|
|
11
|
+
<Path extends T[number]>(path: Path, params?: ParseRoute<Path> extends Record<string, never> ? undefined : ParseRoute<Path>): string;
|
|
12
|
+
};
|
|
13
|
+
export declare function defineLinks<const T extends readonly string[]>(routes: T): LinkFunction<T>;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export function defineLinks(routes) {
|
|
2
|
+
// Validate routes at runtime
|
|
3
|
+
routes.forEach((route) => {
|
|
4
|
+
if (typeof route !== "string") {
|
|
5
|
+
throw new Error(`Invalid route: ${route}. Routes must be strings.`);
|
|
6
|
+
}
|
|
7
|
+
});
|
|
8
|
+
return (path, params) => {
|
|
9
|
+
if (!routes.includes(path)) {
|
|
10
|
+
throw new Error(`Invalid route: ${path}`);
|
|
11
|
+
}
|
|
12
|
+
if (!params)
|
|
13
|
+
return path;
|
|
14
|
+
let result = path;
|
|
15
|
+
// Replace named parameters
|
|
16
|
+
for (const [key, value] of Object.entries(params)) {
|
|
17
|
+
if (key.startsWith("$")) {
|
|
18
|
+
// Replace each star with its corresponding $ parameter
|
|
19
|
+
const starIndex = parseInt(key.slice(1));
|
|
20
|
+
const stars = result.match(/\*/g) || [];
|
|
21
|
+
if (starIndex >= stars.length) {
|
|
22
|
+
throw new Error(`Parameter ${key} has no corresponding * in route`);
|
|
23
|
+
}
|
|
24
|
+
// Replace the nth star with the value
|
|
25
|
+
let count = 0;
|
|
26
|
+
result = result.replace(/\*/g, (match) => count++ === starIndex ? value : match);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
// Handle named parameters
|
|
30
|
+
if (typeof value !== "string") {
|
|
31
|
+
throw new Error(`Parameter ${key} must be a string`);
|
|
32
|
+
}
|
|
33
|
+
result = result.replace(`:${key}`, value);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { initClient } from "../../client";
|
|
2
|
+
import { createFromReadableStream } from "react-server-dom-webpack/client.browser";
|
|
3
|
+
import { MESSAGE_TYPE } from "./shared";
|
|
4
|
+
const DEFAULT_KEY = "default";
|
|
5
|
+
export const initRealtimeClient = ({ key = DEFAULT_KEY, } = {}) => {
|
|
6
|
+
const transport = realtimeTransport({ key });
|
|
7
|
+
return initClient({ transport });
|
|
8
|
+
};
|
|
9
|
+
export const realtimeTransport = ({ key = DEFAULT_KEY }) => (transportContext) => {
|
|
10
|
+
let ws = null;
|
|
11
|
+
let isConnected = false;
|
|
12
|
+
const clientId = crypto.randomUUID();
|
|
13
|
+
const clientUrl = new URL(window.location.href);
|
|
14
|
+
const isHttps = clientUrl.protocol === "https:";
|
|
15
|
+
clientUrl.protocol = "";
|
|
16
|
+
clientUrl.host = "";
|
|
17
|
+
const setupWebSocket = () => {
|
|
18
|
+
if (ws)
|
|
19
|
+
return;
|
|
20
|
+
const protocol = isHttps ? "wss" : "ws";
|
|
21
|
+
ws = new WebSocket(`${protocol}://${window.location.host}/__realtime?` +
|
|
22
|
+
`key=${encodeURIComponent(key)}&` +
|
|
23
|
+
`url=${encodeURIComponent(clientUrl.toString())}&` +
|
|
24
|
+
`clientId=${encodeURIComponent(clientId)}`);
|
|
25
|
+
ws.binaryType = "arraybuffer";
|
|
26
|
+
ws.addEventListener("open", () => {
|
|
27
|
+
isConnected = true;
|
|
28
|
+
});
|
|
29
|
+
ws.addEventListener("error", (event) => {
|
|
30
|
+
console.error("[Realtime] WebSocket error", event);
|
|
31
|
+
});
|
|
32
|
+
ws.addEventListener("message", (event) => {
|
|
33
|
+
const data = new Uint8Array(event.data);
|
|
34
|
+
const messageType = data[0];
|
|
35
|
+
if (messageType === MESSAGE_TYPE.RSC_START) {
|
|
36
|
+
const decoder = new TextDecoder();
|
|
37
|
+
const rscId = decoder.decode(data.slice(1, 37)); // Extract RSC stream ID
|
|
38
|
+
const stream = new ReadableStream({
|
|
39
|
+
start(controller) {
|
|
40
|
+
ws.addEventListener("message", function streamHandler(event) {
|
|
41
|
+
const data = new Uint8Array(event.data);
|
|
42
|
+
const messageType = data[0];
|
|
43
|
+
// Extract the RSC stream ID and verify it matches
|
|
44
|
+
const responseId = decoder.decode(data.slice(1, 37));
|
|
45
|
+
if (responseId !== rscId) {
|
|
46
|
+
return; // Not for this stream
|
|
47
|
+
}
|
|
48
|
+
const payload = data.slice(37);
|
|
49
|
+
if (messageType === MESSAGE_TYPE.RSC_CHUNK) {
|
|
50
|
+
controller.enqueue(payload);
|
|
51
|
+
}
|
|
52
|
+
else if (messageType === MESSAGE_TYPE.RSC_END) {
|
|
53
|
+
controller.close();
|
|
54
|
+
ws.removeEventListener("message", streamHandler);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
const rscPayload = createFromReadableStream(stream, {
|
|
60
|
+
callServer: realtimeCallServer,
|
|
61
|
+
});
|
|
62
|
+
transportContext.setRscPayload(rscPayload);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
ws.addEventListener("close", () => {
|
|
66
|
+
console.warn("[Realtime] WebSocket closed, attempting to reconnect...");
|
|
67
|
+
ws = null;
|
|
68
|
+
isConnected = false;
|
|
69
|
+
setTimeout(setupWebSocket, 5000);
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
const ensureWs = () => {
|
|
73
|
+
if (!ws && isConnected) {
|
|
74
|
+
throw new Error("Inconsistent state: WebSocket is null but marked as connected");
|
|
75
|
+
}
|
|
76
|
+
if (!ws || !isConnected) {
|
|
77
|
+
throw new Error("WebSocket is not connected");
|
|
78
|
+
}
|
|
79
|
+
return ws;
|
|
80
|
+
};
|
|
81
|
+
const realtimeCallServer = async (id, args) => {
|
|
82
|
+
try {
|
|
83
|
+
const socket = ensureWs();
|
|
84
|
+
const { encodeReply } = await import("react-server-dom-webpack/client.browser");
|
|
85
|
+
// Note(peterp, 2025-07-02): We need to send the "current URL" per message,
|
|
86
|
+
// in case the user has enabled client side navigation.
|
|
87
|
+
const clientUrl = new URL(window.location.href);
|
|
88
|
+
clientUrl.protocol = "";
|
|
89
|
+
clientUrl.host = "";
|
|
90
|
+
const encodedArgs = args != null ? await encodeReply(args) : null;
|
|
91
|
+
const requestId = crypto.randomUUID();
|
|
92
|
+
const messageData = JSON.stringify({
|
|
93
|
+
id,
|
|
94
|
+
args: encodedArgs,
|
|
95
|
+
requestId,
|
|
96
|
+
clientUrl,
|
|
97
|
+
});
|
|
98
|
+
const encoder = new TextEncoder();
|
|
99
|
+
const messageBytes = encoder.encode(messageData);
|
|
100
|
+
const message = new Uint8Array(messageBytes.length + 1);
|
|
101
|
+
message[0] = MESSAGE_TYPE.ACTION_REQUEST;
|
|
102
|
+
message.set(messageBytes, 1);
|
|
103
|
+
socket.send(message);
|
|
104
|
+
return new Promise(async (resolve, reject) => {
|
|
105
|
+
const stream = new ReadableStream({
|
|
106
|
+
start(controller) {
|
|
107
|
+
const messageHandler = (event) => {
|
|
108
|
+
const data = new Uint8Array(event.data);
|
|
109
|
+
const messageType = data[0];
|
|
110
|
+
// First byte is message type
|
|
111
|
+
// Next 36 bytes (or fixed size) should be UUID as requestId
|
|
112
|
+
// Remaining bytes are the payload
|
|
113
|
+
// Extract the requestId from the message
|
|
114
|
+
const decoder = new TextDecoder();
|
|
115
|
+
const responseId = decoder.decode(data.slice(1, 37)); // Assuming UUID is 36 chars
|
|
116
|
+
// Only process messages meant for this request
|
|
117
|
+
if (responseId !== requestId) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
// The actual payload starts after the requestId
|
|
121
|
+
const payload = data.slice(37);
|
|
122
|
+
if (messageType === MESSAGE_TYPE.ACTION_CHUNK) {
|
|
123
|
+
controller.enqueue(payload);
|
|
124
|
+
}
|
|
125
|
+
else if (messageType === MESSAGE_TYPE.ACTION_END) {
|
|
126
|
+
controller.close();
|
|
127
|
+
socket.removeEventListener("message", messageHandler);
|
|
128
|
+
}
|
|
129
|
+
else if (messageType === MESSAGE_TYPE.ACTION_ERROR) {
|
|
130
|
+
const errorJson = decoder.decode(payload);
|
|
131
|
+
let errorMsg = "Unknown error";
|
|
132
|
+
try {
|
|
133
|
+
const errorObj = JSON.parse(errorJson);
|
|
134
|
+
errorMsg = errorObj.error || errorMsg;
|
|
135
|
+
}
|
|
136
|
+
catch (e) {
|
|
137
|
+
// Use default error message
|
|
138
|
+
}
|
|
139
|
+
controller.error(new Error(errorMsg));
|
|
140
|
+
socket.removeEventListener("message", messageHandler);
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
socket.addEventListener("message", messageHandler);
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
const rscPayload = createFromReadableStream(stream, {
|
|
147
|
+
callServer: realtimeCallServer,
|
|
148
|
+
});
|
|
149
|
+
transportContext.setRscPayload(rscPayload);
|
|
150
|
+
try {
|
|
151
|
+
const result = await rscPayload;
|
|
152
|
+
resolve(result.actionResult);
|
|
153
|
+
}
|
|
154
|
+
catch (rscPayloadError) {
|
|
155
|
+
reject(rscPayloadError);
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
catch (e) {
|
|
160
|
+
console.error("[Realtime] Error calling server", e);
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
setupWebSocket();
|
|
165
|
+
return realtimeCallServer;
|
|
166
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const DEFAULT_REALTIME_KEY = "default";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const DEFAULT_REALTIME_KEY = "default";
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { DurableObject } from "cloudflare:workers";
|
|
2
|
+
interface ClientInfo {
|
|
3
|
+
url: string;
|
|
4
|
+
clientId: string;
|
|
5
|
+
cookieHeaders: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class RealtimeDurableObject extends DurableObject {
|
|
8
|
+
state: DurableObjectState;
|
|
9
|
+
env: Env;
|
|
10
|
+
storage: DurableObjectStorage;
|
|
11
|
+
clientInfoCache: Map<string, ClientInfo>;
|
|
12
|
+
constructor(state: DurableObjectState, env: Env);
|
|
13
|
+
fetch(request: Request): Promise<Response>;
|
|
14
|
+
private createClientInfo;
|
|
15
|
+
private storeClientInfo;
|
|
16
|
+
private getClientInfo;
|
|
17
|
+
private handleWebSocket;
|
|
18
|
+
webSocketMessage(ws: WebSocket, data: ArrayBuffer): Promise<void>;
|
|
19
|
+
private streamResponse;
|
|
20
|
+
private handleAction;
|
|
21
|
+
private determineSockets;
|
|
22
|
+
render({ include, exclude, }?: {
|
|
23
|
+
include?: string[];
|
|
24
|
+
exclude?: string[];
|
|
25
|
+
}): Promise<void>;
|
|
26
|
+
private removeClientInfo;
|
|
27
|
+
webSocketClose(ws: WebSocket): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { DurableObject } from "cloudflare:workers";
|
|
2
|
+
import { MESSAGE_TYPE } from "./shared";
|
|
3
|
+
import { validateUpgradeRequest } from "./validateUpgradeRequest";
|
|
4
|
+
export class RealtimeDurableObject extends DurableObject {
|
|
5
|
+
constructor(state, env) {
|
|
6
|
+
super(state, env);
|
|
7
|
+
this.state = state;
|
|
8
|
+
this.env = env;
|
|
9
|
+
this.storage = state.storage;
|
|
10
|
+
this.clientInfoCache = new Map();
|
|
11
|
+
}
|
|
12
|
+
async fetch(request) {
|
|
13
|
+
const validation = validateUpgradeRequest(request);
|
|
14
|
+
if (!validation.valid) {
|
|
15
|
+
return validation.response;
|
|
16
|
+
}
|
|
17
|
+
const url = new URL(request.url);
|
|
18
|
+
const clientInfo = this.createClientInfo(url, request);
|
|
19
|
+
return this.handleWebSocket(request, clientInfo);
|
|
20
|
+
}
|
|
21
|
+
createClientInfo(url, request) {
|
|
22
|
+
return {
|
|
23
|
+
url: url.searchParams.get("url"),
|
|
24
|
+
clientId: url.searchParams.get("clientId"),
|
|
25
|
+
cookieHeaders: request.headers.get("Cookie") || "",
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
async storeClientInfo(clientInfo) {
|
|
29
|
+
this.clientInfoCache.set(clientInfo.clientId, clientInfo);
|
|
30
|
+
await this.storage.put(`client:${clientInfo.clientId}`, clientInfo);
|
|
31
|
+
}
|
|
32
|
+
async getClientInfo(clientId) {
|
|
33
|
+
const cachedInfo = this.clientInfoCache.get(clientId);
|
|
34
|
+
if (cachedInfo) {
|
|
35
|
+
return cachedInfo;
|
|
36
|
+
}
|
|
37
|
+
const clientInfo = await this.storage.get(`client:${clientId}`);
|
|
38
|
+
if (!clientInfo) {
|
|
39
|
+
throw new Error(`Client info not found for clientId: ${clientId}`);
|
|
40
|
+
}
|
|
41
|
+
this.clientInfoCache.set(clientId, clientInfo);
|
|
42
|
+
return clientInfo;
|
|
43
|
+
}
|
|
44
|
+
async handleWebSocket(request, clientInfo) {
|
|
45
|
+
const { 0: client, 1: server } = new WebSocketPair();
|
|
46
|
+
await this.storeClientInfo(clientInfo);
|
|
47
|
+
server.serializeAttachment(clientInfo.clientId);
|
|
48
|
+
this.state.acceptWebSocket(server);
|
|
49
|
+
return new Response(null, { status: 101, webSocket: client });
|
|
50
|
+
}
|
|
51
|
+
async webSocketMessage(ws, data) {
|
|
52
|
+
const clientId = ws.deserializeAttachment();
|
|
53
|
+
const clientInfo = await this.getClientInfo(clientId);
|
|
54
|
+
const message = new Uint8Array(data);
|
|
55
|
+
const messageType = message[0];
|
|
56
|
+
if (messageType === MESSAGE_TYPE.ACTION_REQUEST) {
|
|
57
|
+
const decoder = new TextDecoder();
|
|
58
|
+
const jsonData = decoder.decode(message.slice(1));
|
|
59
|
+
const { id, args, requestId, clientUrl } = JSON.parse(jsonData);
|
|
60
|
+
try {
|
|
61
|
+
await this.handleAction(ws, id, args, clientInfo, requestId, clientUrl);
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
const encoder = new TextEncoder();
|
|
65
|
+
const requestIdBytes = encoder.encode(requestId);
|
|
66
|
+
const errorData = JSON.stringify({
|
|
67
|
+
error: error instanceof Error ? error.message : String(error),
|
|
68
|
+
});
|
|
69
|
+
const errorBytes = encoder.encode(errorData);
|
|
70
|
+
const errorResponse = new Uint8Array(1 + requestIdBytes.length + errorBytes.length);
|
|
71
|
+
errorResponse[0] = MESSAGE_TYPE.ACTION_ERROR;
|
|
72
|
+
errorResponse.set(requestIdBytes, 1);
|
|
73
|
+
errorResponse.set(errorBytes, 1 + requestIdBytes.length);
|
|
74
|
+
ws.send(errorResponse);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async streamResponse(response, ws, messageTypes, streamId) {
|
|
79
|
+
const reader = response.body.getReader();
|
|
80
|
+
const encoder = new TextEncoder();
|
|
81
|
+
const streamIdBytes = encoder.encode(streamId);
|
|
82
|
+
try {
|
|
83
|
+
while (true) {
|
|
84
|
+
const { done, value } = await reader.read();
|
|
85
|
+
if (done) {
|
|
86
|
+
const endMessage = new Uint8Array(1 + streamIdBytes.length);
|
|
87
|
+
endMessage[0] = messageTypes.end;
|
|
88
|
+
endMessage.set(streamIdBytes, 1);
|
|
89
|
+
ws.send(endMessage);
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
const chunkMessage = new Uint8Array(1 + streamIdBytes.length + value.length);
|
|
93
|
+
chunkMessage[0] = messageTypes.chunk;
|
|
94
|
+
chunkMessage.set(streamIdBytes, 1);
|
|
95
|
+
chunkMessage.set(value, 1 + streamIdBytes.length);
|
|
96
|
+
ws.send(chunkMessage);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
reader.releaseLock();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
async handleAction(ws, id, args, clientInfo, requestId, clientUrl) {
|
|
104
|
+
const url = new URL(clientUrl);
|
|
105
|
+
url.searchParams.set("__rsc", "");
|
|
106
|
+
if (id != null) {
|
|
107
|
+
url.searchParams.set("__rsc_action_id", id);
|
|
108
|
+
}
|
|
109
|
+
const response = await fetch(url.toString(), {
|
|
110
|
+
method: "POST",
|
|
111
|
+
body: args,
|
|
112
|
+
headers: {
|
|
113
|
+
"Content-Type": "application/json",
|
|
114
|
+
Cookie: clientInfo.cookieHeaders,
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
if (!response.ok) {
|
|
118
|
+
throw new Error(`Action failed: ${response.statusText}`);
|
|
119
|
+
}
|
|
120
|
+
this.render({
|
|
121
|
+
exclude: [clientInfo.clientId],
|
|
122
|
+
});
|
|
123
|
+
await this.streamResponse(response, ws, {
|
|
124
|
+
chunk: MESSAGE_TYPE.ACTION_CHUNK,
|
|
125
|
+
end: MESSAGE_TYPE.ACTION_END,
|
|
126
|
+
}, requestId);
|
|
127
|
+
}
|
|
128
|
+
async determineSockets({ include = [], exclude = [], } = {}) {
|
|
129
|
+
const sockets = Array.from(this.state.getWebSockets());
|
|
130
|
+
const includeSet = include.length > 0 ? new Set(include) : null;
|
|
131
|
+
const excludeSet = exclude.length > 0 ? new Set(exclude) : null;
|
|
132
|
+
const results = [];
|
|
133
|
+
for (const socket of sockets) {
|
|
134
|
+
const clientId = socket.deserializeAttachment();
|
|
135
|
+
if (excludeSet?.has(clientId)) {
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (includeSet && !includeSet.has(clientId)) {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
const clientInfo = await this.getClientInfo(clientId);
|
|
142
|
+
results.push({ socket, clientInfo });
|
|
143
|
+
}
|
|
144
|
+
return results;
|
|
145
|
+
}
|
|
146
|
+
async render({ include, exclude, } = {}) {
|
|
147
|
+
const sockets = await this.determineSockets({ include, exclude });
|
|
148
|
+
if (sockets.length === 0)
|
|
149
|
+
return;
|
|
150
|
+
await Promise.all(sockets.map(async ({ socket, clientInfo }) => {
|
|
151
|
+
try {
|
|
152
|
+
const url = new URL(clientInfo.url);
|
|
153
|
+
url.searchParams.set("__rsc", "true");
|
|
154
|
+
const response = await fetch(url.toString(), {
|
|
155
|
+
headers: {
|
|
156
|
+
"Content-Type": "application/json",
|
|
157
|
+
Cookie: clientInfo.cookieHeaders,
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
if (!response.ok) {
|
|
161
|
+
console.error(`Failed to fetch RSC update: ${response.statusText}`);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const rscId = crypto.randomUUID();
|
|
165
|
+
const startMessage = new Uint8Array(1 + 36);
|
|
166
|
+
startMessage[0] = MESSAGE_TYPE.RSC_START;
|
|
167
|
+
startMessage.set(new TextEncoder().encode(rscId), 1);
|
|
168
|
+
socket.send(startMessage);
|
|
169
|
+
await this.streamResponse(response, socket, {
|
|
170
|
+
chunk: MESSAGE_TYPE.RSC_CHUNK,
|
|
171
|
+
end: MESSAGE_TYPE.RSC_END,
|
|
172
|
+
}, rscId);
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
console.error("Failed to process socket:", err);
|
|
176
|
+
}
|
|
177
|
+
}));
|
|
178
|
+
}
|
|
179
|
+
async removeClientInfo(clientId) {
|
|
180
|
+
this.clientInfoCache.delete(clientId);
|
|
181
|
+
await this.storage.delete(`client:${clientId}`);
|
|
182
|
+
}
|
|
183
|
+
async webSocketClose(ws) {
|
|
184
|
+
const clientId = ws.deserializeAttachment();
|
|
185
|
+
await this.removeClientInfo(clientId);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { RealtimeDurableObject } from "./durableObject";
|
|
2
|
+
export declare const renderRealtimeClients: ({ durableObjectNamespace, key, include, exclude, }: {
|
|
3
|
+
durableObjectNamespace: DurableObjectNamespace<RealtimeDurableObject>;
|
|
4
|
+
key?: string;
|
|
5
|
+
include?: string[];
|
|
6
|
+
exclude?: string[];
|
|
7
|
+
}) => Promise<void>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { DEFAULT_REALTIME_KEY } from "./constants";
|
|
2
|
+
export const renderRealtimeClients = async ({ durableObjectNamespace, key = DEFAULT_REALTIME_KEY, include, exclude, }) => {
|
|
3
|
+
const id = durableObjectNamespace.idFromName(key);
|
|
4
|
+
const durableObject = durableObjectNamespace.get(id);
|
|
5
|
+
await durableObject.render({ include, exclude });
|
|
6
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export const validateUpgradeRequest = (request) => {
|
|
2
|
+
if (request.headers.get("Upgrade") !== "websocket") {
|
|
3
|
+
return {
|
|
4
|
+
valid: false,
|
|
5
|
+
response: new Response("Expected WebSocket", { status: 400 }),
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
const requestOrigin = request.headers.get("Origin");
|
|
9
|
+
if (!requestOrigin) {
|
|
10
|
+
return {
|
|
11
|
+
valid: false,
|
|
12
|
+
response: new Response("Invalid origin", { status: 403 }),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
const requestOriginUrl = new URL(requestOrigin);
|
|
16
|
+
const url = new URL(request.url);
|
|
17
|
+
// context(justinvdm, 19 Mar 2025): Origin header doesnt include port, yet
|
|
18
|
+
// the request url does for non-standard ports.
|
|
19
|
+
if (requestOriginUrl.protocol === url.protocol &&
|
|
20
|
+
requestOriginUrl.hostname === url.hostname) {
|
|
21
|
+
return {
|
|
22
|
+
valid: true,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
valid: false,
|
|
27
|
+
response: new Response("Invalid origin", { status: 403 }),
|
|
28
|
+
};
|
|
29
|
+
};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { RealtimeDurableObject } from "./durableObject";
|
|
2
|
+
export { renderRealtimeClients } from "./renderRealtimeClients";
|
|
3
|
+
export declare const realtimeRoute: (getDurableObjectNamespace: (env: Cloudflare.Env) => DurableObjectNamespace<RealtimeDurableObject>) => import("../router").RouteDefinition<import("../../requestInfo/types").RequestInfo<any, import("../../requestInfo/types").DefaultAppContext>>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { route } from "../../entries/router";
|
|
2
|
+
import { validateUpgradeRequest } from "./validateUpgradeRequest";
|
|
3
|
+
import { DEFAULT_REALTIME_KEY } from "./constants";
|
|
4
|
+
import { env } from "cloudflare:workers";
|
|
5
|
+
export { renderRealtimeClients } from "./renderRealtimeClients";
|
|
6
|
+
export const realtimeRoute = (getDurableObjectNamespace) => route("/__realtime", async function ({ request }) {
|
|
7
|
+
const validation = validateUpgradeRequest(request);
|
|
8
|
+
if (!validation.valid) {
|
|
9
|
+
return validation.response;
|
|
10
|
+
}
|
|
11
|
+
const url = new URL(request.url);
|
|
12
|
+
const key = url.searchParams.get("key") || DEFAULT_REALTIME_KEY;
|
|
13
|
+
const id = getDurableObjectNamespace(env).idFromName(key);
|
|
14
|
+
const durableObject = getDurableObjectNamespace(env).get(id);
|
|
15
|
+
return durableObject.fetch(request);
|
|
16
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { RequestInfo } from "../requestInfo/types";
|
|
3
|
+
import type { Kysely } from "kysely";
|
|
4
|
+
export type DocumentProps<T extends RequestInfo = RequestInfo> = T & {
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
};
|
|
7
|
+
export type LayoutProps<T extends RequestInfo = RequestInfo> = {
|
|
8
|
+
children?: React.ReactNode;
|
|
9
|
+
requestInfo?: T;
|
|
10
|
+
};
|
|
11
|
+
export type RwContext = {
|
|
12
|
+
nonce: string;
|
|
13
|
+
Document: React.FC<DocumentProps<any>>;
|
|
14
|
+
rscPayload: boolean;
|
|
15
|
+
ssr: boolean;
|
|
16
|
+
layouts?: React.FC<LayoutProps<any>>[];
|
|
17
|
+
databases: Map<string, Kysely<any>>;
|
|
18
|
+
};
|
|
19
|
+
export type RouteMiddleware<T extends RequestInfo = RequestInfo> = (requestInfo: T) => Response | Promise<Response> | void | Promise<void> | Promise<Response | void>;
|
|
20
|
+
type RouteFunction<T extends RequestInfo = RequestInfo> = (requestInfo: T) => Response | Promise<Response>;
|
|
21
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
22
|
+
type RouteComponent<T extends RequestInfo = RequestInfo> = (requestInfo: T) => MaybePromise<React.JSX.Element | Response>;
|
|
23
|
+
type RouteHandler<T extends RequestInfo = RequestInfo> = RouteFunction<T> | RouteComponent<T> | [...RouteMiddleware<T>[], RouteFunction<T> | RouteComponent<T>];
|
|
24
|
+
export type Route<T extends RequestInfo = RequestInfo> = RouteMiddleware<T> | RouteDefinition<T> | Array<Route<T>>;
|
|
25
|
+
export type RouteDefinition<T extends RequestInfo = RequestInfo> = {
|
|
26
|
+
path: string;
|
|
27
|
+
handler: RouteHandler<T>;
|
|
28
|
+
layouts?: React.FC<LayoutProps<T>>[];
|
|
29
|
+
};
|
|
30
|
+
export declare function matchPath<T extends RequestInfo = RequestInfo>(routePath: string, requestPath: string): T["params"] | null;
|
|
31
|
+
export declare function defineRoutes<T extends RequestInfo = RequestInfo>(routes: Route<T>[]): {
|
|
32
|
+
routes: Route<T>[];
|
|
33
|
+
handle: ({ request, renderPage, getRequestInfo, onError, runWithRequestInfoOverrides, }: {
|
|
34
|
+
request: Request;
|
|
35
|
+
renderPage: (requestInfo: T, Page: React.FC, onError: (error: unknown) => void) => Promise<Response>;
|
|
36
|
+
getRequestInfo: () => T;
|
|
37
|
+
onError: (error: unknown) => void;
|
|
38
|
+
runWithRequestInfoOverrides: <Result>(overrides: Partial<T>, fn: () => Promise<Result>) => Promise<Result>;
|
|
39
|
+
}) => Response | Promise<Response>;
|
|
40
|
+
};
|
|
41
|
+
export declare function route<T extends RequestInfo = RequestInfo>(path: string, handler: RouteHandler<T>): RouteDefinition<T>;
|
|
42
|
+
export declare function index<T extends RequestInfo = RequestInfo>(handler: RouteHandler<T>): RouteDefinition<T>;
|
|
43
|
+
export declare function prefix<T extends RequestInfo = RequestInfo>(prefixPath: string, routes: Route<T>[]): Route<T>[];
|
|
44
|
+
export declare function layout<T extends RequestInfo = RequestInfo>(LayoutComponent: React.FC<LayoutProps<T>>, routes: Route<T>[]): Route<T>[];
|
|
45
|
+
export declare function render<T extends RequestInfo = RequestInfo>(Document: React.FC<DocumentProps<T>>, routes: Route<T>[],
|
|
46
|
+
/**
|
|
47
|
+
* @param options - Configuration options for rendering.
|
|
48
|
+
* @param options.rscPayload - Toggle the RSC payload that's appended to the Document. Disabling this will mean that interactivity no longer works.
|
|
49
|
+
* @param options.ssr - Disable sever side rendering for all these routes. This only allow client side rendering`, which requires `rscPayload` to be enabled.
|
|
50
|
+
*/
|
|
51
|
+
options?: {
|
|
52
|
+
rscPayload?: boolean;
|
|
53
|
+
ssr?: boolean;
|
|
54
|
+
}): Route<T>[];
|
|
55
|
+
export declare const isClientReference: (Component: React.FC<any>) => boolean;
|
|
56
|
+
export {};
|