rwsdk 1.0.0-alpha.2 → 1.0.0-alpha.20-test.20250929144616

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.
Files changed (214) hide show
  1. package/dist/lib/constants.mjs +1 -2
  2. package/dist/lib/e2e/browser.d.mts +10 -0
  3. package/dist/lib/e2e/browser.mjs +123 -0
  4. package/dist/lib/e2e/dev.d.mts +8 -0
  5. package/dist/lib/e2e/dev.mjs +242 -0
  6. package/dist/lib/e2e/environment.d.mts +10 -0
  7. package/dist/lib/e2e/environment.mjs +210 -0
  8. package/dist/lib/e2e/index.d.mts +8 -0
  9. package/dist/lib/e2e/index.mjs +8 -0
  10. package/dist/lib/e2e/poll.d.mts +8 -0
  11. package/dist/lib/e2e/poll.mjs +31 -0
  12. package/dist/lib/e2e/release.d.mts +56 -0
  13. package/dist/lib/e2e/release.mjs +559 -0
  14. package/dist/lib/e2e/retry.d.mts +4 -0
  15. package/dist/lib/e2e/retry.mjs +16 -0
  16. package/dist/lib/e2e/setup.d.mts +2 -0
  17. package/dist/lib/e2e/setup.mjs +1 -0
  18. package/dist/lib/e2e/tarball.d.mts +14 -0
  19. package/dist/lib/e2e/tarball.mjs +99 -0
  20. package/dist/lib/e2e/testHarness.d.mts +132 -0
  21. package/dist/lib/e2e/testHarness.mjs +436 -0
  22. package/dist/lib/e2e/types.d.mts +32 -0
  23. package/dist/lib/getShortName.mjs +6 -2
  24. package/dist/lib/getShortName.test.d.mts +1 -0
  25. package/dist/lib/getShortName.test.mjs +25 -0
  26. package/dist/lib/getSrcPaths.js +2 -2
  27. package/dist/lib/hasPkgScript.d.mts +4 -1
  28. package/dist/lib/hasPkgScript.mjs +9 -6
  29. package/dist/lib/hasPkgScript.test.d.mts +1 -0
  30. package/dist/lib/hasPkgScript.test.mjs +33 -0
  31. package/dist/lib/jsonUtils.mjs +3 -0
  32. package/dist/lib/jsonUtils.test.d.mts +1 -0
  33. package/dist/lib/jsonUtils.test.mjs +90 -0
  34. package/dist/lib/normalizeModulePath.d.mts +5 -0
  35. package/dist/lib/normalizeModulePath.mjs +1 -1
  36. package/dist/lib/normalizeModulePath.test.d.mts +1 -0
  37. package/dist/lib/{normalizeModulePath.test.js → normalizeModulePath.test.mjs} +21 -2
  38. package/dist/lib/setupEnvFiles.mjs +2 -2
  39. package/dist/lib/smokeTests/artifacts.mjs +2 -2
  40. package/dist/lib/smokeTests/browser.d.mts +1 -1
  41. package/dist/lib/smokeTests/browser.mjs +8 -100
  42. package/dist/lib/smokeTests/cleanup.mjs +6 -9
  43. package/dist/lib/smokeTests/codeUpdates.mjs +5 -5
  44. package/dist/lib/smokeTests/development.mjs +3 -224
  45. package/dist/lib/smokeTests/environment.d.mts +3 -11
  46. package/dist/lib/smokeTests/environment.mjs +17 -151
  47. package/dist/lib/smokeTests/release.d.mts +2 -49
  48. package/dist/lib/smokeTests/release.mjs +4 -504
  49. package/dist/lib/smokeTests/reporting.mjs +2 -2
  50. package/dist/lib/smokeTests/runSmokeTests.mjs +4 -4
  51. package/dist/lib/smokeTests/utils.mjs +3 -3
  52. package/dist/lib/testUtils/stubEnvVars.mjs +1 -1
  53. package/dist/llms/rules/middleware.d.ts +1 -1
  54. package/dist/llms/rules/middleware.js +4 -4
  55. package/dist/runtime/client/client.d.ts +2 -2
  56. package/dist/runtime/client/client.js +2 -2
  57. package/dist/runtime/client/navigation.test.js +1 -1
  58. package/dist/runtime/client/types.d.ts +1 -1
  59. package/dist/runtime/entries/client.d.ts +2 -2
  60. package/dist/runtime/entries/client.js +2 -2
  61. package/dist/runtime/entries/router.d.ts +1 -1
  62. package/dist/runtime/entries/router.js +1 -1
  63. package/dist/runtime/entries/worker.d.ts +5 -6
  64. package/dist/runtime/entries/worker.js +5 -6
  65. package/dist/runtime/imports/worker.js +1 -1
  66. package/dist/runtime/lib/auth/session.d.ts +2 -2
  67. package/dist/runtime/lib/auth/session.js +5 -5
  68. package/dist/runtime/lib/db/DOWorkerDialect.d.ts +1 -1
  69. package/dist/runtime/lib/db/DOWorkerDialect.js +1 -1
  70. package/dist/runtime/lib/db/SqliteDurableObject.js +2 -2
  71. package/dist/runtime/lib/db/index.d.ts +2 -2
  72. package/dist/runtime/lib/db/index.js +2 -2
  73. package/dist/runtime/lib/db/migrations.d.ts +1 -1
  74. package/dist/runtime/lib/db/typeInference/builders/alterTable.d.ts +3 -3
  75. package/dist/runtime/lib/db/typeInference/builders/columnDefinition.d.ts +1 -1
  76. package/dist/runtime/lib/db/typeInference/builders/createTable.d.ts +2 -2
  77. package/dist/runtime/lib/db/typeInference/builders/createView.d.ts +1 -1
  78. package/dist/runtime/lib/db/typeInference/builders/dropTable.d.ts +1 -1
  79. package/dist/runtime/lib/db/typeInference/builders/dropView.d.ts +1 -1
  80. package/dist/runtime/lib/db/typeInference/builders/schema.d.ts +3 -3
  81. package/dist/runtime/lib/db/typeInference/database.d.ts +2 -2
  82. package/dist/runtime/lib/memoizeOnId.test.d.ts +1 -0
  83. package/dist/runtime/lib/memoizeOnId.test.js +49 -0
  84. package/dist/runtime/lib/realtime/client.js +2 -2
  85. package/dist/runtime/lib/realtime/durableObject.js +1 -1
  86. package/dist/runtime/lib/realtime/protocol.test.d.ts +1 -0
  87. package/dist/runtime/lib/realtime/protocol.test.js +107 -0
  88. package/dist/runtime/lib/realtime/shared.test.d.ts +1 -0
  89. package/dist/runtime/lib/realtime/shared.test.js +18 -0
  90. package/dist/runtime/lib/realtime/validateUpgradeRequest.test.d.ts +1 -0
  91. package/dist/runtime/lib/realtime/validateUpgradeRequest.test.js +66 -0
  92. package/dist/runtime/lib/realtime/worker.d.ts +1 -1
  93. package/dist/runtime/lib/realtime/worker.js +2 -2
  94. package/dist/runtime/lib/router.d.ts +1 -1
  95. package/dist/runtime/lib/router.js +40 -22
  96. package/dist/runtime/lib/router.test.js +591 -3
  97. package/dist/runtime/lib/rwContext.d.ts +22 -0
  98. package/dist/runtime/lib/rwContext.js +1 -0
  99. package/dist/runtime/lib/stitchDocumentAndAppStreams.d.ts +18 -0
  100. package/dist/runtime/lib/stitchDocumentAndAppStreams.js +143 -0
  101. package/dist/runtime/lib/turnstile/useTurnstile.js +1 -1
  102. package/dist/runtime/lib/turnstile/verifyTurnstileToken.d.ts +2 -1
  103. package/dist/runtime/lib/turnstile/verifyTurnstileToken.js +6 -6
  104. package/dist/runtime/lib/turnstile/verifyTurnstileToken.test.d.ts +1 -0
  105. package/dist/runtime/lib/turnstile/verifyTurnstileToken.test.js +49 -0
  106. package/dist/runtime/register/worker.d.ts +1 -1
  107. package/dist/runtime/register/worker.js +34 -22
  108. package/dist/runtime/render/assembleDocument.d.ts +6 -0
  109. package/dist/runtime/render/assembleDocument.js +22 -0
  110. package/dist/runtime/render/createThenableFromReadableStream.d.ts +1 -0
  111. package/dist/runtime/render/createThenableFromReadableStream.js +9 -0
  112. package/dist/runtime/render/normalizeActionResult.d.ts +1 -0
  113. package/dist/runtime/render/normalizeActionResult.js +43 -0
  114. package/dist/runtime/render/preloads.d.ts +3 -3
  115. package/dist/runtime/render/preloads.js +2 -3
  116. package/dist/runtime/render/{renderRscThenableToHtmlStream.d.ts → renderDocumentHtmlStream.d.ts} +3 -3
  117. package/dist/runtime/render/renderDocumentHtmlStream.js +39 -0
  118. package/dist/runtime/render/renderHtmlStream.d.ts +7 -0
  119. package/dist/runtime/render/renderHtmlStream.js +31 -0
  120. package/dist/runtime/render/renderToRscStream.d.ts +5 -3
  121. package/dist/runtime/render/renderToRscStream.js +12 -41
  122. package/dist/runtime/render/renderToStream.d.ts +3 -2
  123. package/dist/runtime/render/renderToStream.js +17 -10
  124. package/dist/runtime/render/stylesheets.d.ts +2 -2
  125. package/dist/runtime/render/stylesheets.js +2 -3
  126. package/dist/runtime/requestInfo/types.d.ts +0 -2
  127. package/dist/runtime/requestInfo/worker.d.ts +1 -1
  128. package/dist/runtime/requestInfo/worker.js +1 -9
  129. package/dist/runtime/script.js +1 -1
  130. package/dist/runtime/ssrBridge.d.ts +3 -2
  131. package/dist/runtime/ssrBridge.js +3 -2
  132. package/dist/runtime/worker.d.ts +2 -1
  133. package/dist/runtime/worker.js +13 -16
  134. package/dist/scripts/addon.d.mts +1 -0
  135. package/dist/scripts/addon.mjs +75 -0
  136. package/dist/scripts/debug-sync.mjs +106 -137
  137. package/dist/scripts/ensure-deploy-env.mjs +6 -6
  138. package/dist/scripts/migrate-new.mjs +3 -4
  139. package/dist/scripts/smoke-test.mjs +2 -2
  140. package/dist/scripts/worker-run.mjs +7 -9
  141. package/dist/vite/buildApp.d.mts +2 -1
  142. package/dist/vite/buildApp.mjs +10 -6
  143. package/dist/vite/checkIsUsingPrisma.d.mts +4 -0
  144. package/dist/vite/checkIsUsingPrisma.mjs +2 -2
  145. package/dist/vite/checkIsUsingPrisma.test.d.mts +1 -0
  146. package/dist/vite/checkIsUsingPrisma.test.mjs +30 -0
  147. package/dist/vite/configPlugin.mjs +55 -15
  148. package/dist/vite/createDirectiveLookupPlugin.d.mts +9 -0
  149. package/dist/vite/createDirectiveLookupPlugin.mjs +34 -30
  150. package/dist/vite/createDirectiveLookupPlugin.test.d.mts +1 -0
  151. package/dist/vite/createDirectiveLookupPlugin.test.mjs +40 -0
  152. package/dist/vite/createViteAwareResolver.d.mts +1 -2
  153. package/dist/vite/createViteAwareResolver.mjs +1 -1
  154. package/dist/vite/directiveModulesDevPlugin.d.mts +4 -1
  155. package/dist/vite/directiveModulesDevPlugin.mjs +9 -8
  156. package/dist/vite/directiveModulesDevPlugin.test.d.mts +1 -0
  157. package/dist/vite/directiveModulesDevPlugin.test.mjs +59 -0
  158. package/dist/vite/directivesPlugin.d.mts +1 -0
  159. package/dist/vite/directivesPlugin.mjs +4 -4
  160. package/dist/vite/directivesPlugin.test.d.mts +1 -0
  161. package/dist/vite/directivesPlugin.test.mjs +24 -0
  162. package/dist/vite/ensureAliasArray.test.d.mts +1 -0
  163. package/dist/vite/ensureAliasArray.test.mjs +71 -0
  164. package/dist/vite/findSpecifiers.mjs +3 -2
  165. package/dist/vite/findSpecifiers.test.d.mts +1 -0
  166. package/dist/vite/findSpecifiers.test.mjs +202 -0
  167. package/dist/vite/findSsrSpecifiers.mjs +1 -1
  168. package/dist/vite/findSsrSpecifiers.test.d.mts +1 -0
  169. package/dist/vite/findSsrSpecifiers.test.mjs +99 -0
  170. package/dist/vite/getViteEsbuild.mjs +1 -1
  171. package/dist/vite/hasDirective.d.mts +6 -3
  172. package/dist/vite/hasDirective.mjs +43 -27
  173. package/dist/vite/hasDirective.test.d.mts +1 -0
  174. package/dist/vite/hasDirective.test.mjs +107 -0
  175. package/dist/vite/index.d.mts +1 -1
  176. package/dist/vite/invalidateCacheIfPrismaClientChanged.mjs +2 -2
  177. package/dist/vite/isJsFile.test.d.mts +1 -0
  178. package/dist/vite/isJsFile.test.mjs +38 -0
  179. package/dist/vite/{reactConditionsResolverPlugin.d.mts → knownDepsResolverPlugin.d.mts} +3 -3
  180. package/dist/vite/{reactConditionsResolverPlugin.mjs → knownDepsResolverPlugin.mjs} +29 -24
  181. package/dist/vite/linkerPlugin.d.mts +8 -0
  182. package/dist/vite/linkerPlugin.mjs +32 -24
  183. package/dist/vite/linkerPlugin.test.d.mts +1 -0
  184. package/dist/vite/linkerPlugin.test.mjs +41 -0
  185. package/dist/vite/miniflareHMRPlugin.d.mts +5 -0
  186. package/dist/vite/miniflareHMRPlugin.mjs +7 -7
  187. package/dist/vite/miniflareHMRPlugin.test.d.mts +1 -0
  188. package/dist/vite/miniflareHMRPlugin.test.mjs +42 -0
  189. package/dist/vite/prismaPlugin.mjs +1 -1
  190. package/dist/vite/redwoodPlugin.d.mts +9 -0
  191. package/dist/vite/redwoodPlugin.mjs +44 -20
  192. package/dist/vite/redwoodPlugin.test.d.mts +1 -0
  193. package/dist/vite/redwoodPlugin.test.mjs +34 -0
  194. package/dist/vite/resolveForcedPaths.d.mts +4 -0
  195. package/dist/vite/resolveForcedPaths.mjs +9 -0
  196. package/dist/vite/runDirectivesScan.d.mts +22 -1
  197. package/dist/vite/runDirectivesScan.mjs +109 -61
  198. package/dist/vite/runDirectivesScan.test.d.mts +1 -0
  199. package/dist/vite/runDirectivesScan.test.mjs +73 -0
  200. package/dist/vite/ssrBridgePlugin.mjs +10 -3
  201. package/dist/vite/transformClientComponents.mjs +8 -6
  202. package/dist/vite/transformClientComponents.test.mjs +117 -59
  203. package/dist/vite/transformJsxScriptTagsPlugin.mjs +1 -1
  204. package/dist/vite/transformJsxScriptTagsPlugin.test.mjs +2 -2
  205. package/dist/vite/transformServerFunctions.d.mts +1 -1
  206. package/dist/vite/transformServerFunctions.mjs +5 -5
  207. package/dist/vite/transformServerFunctions.test.mjs +3 -3
  208. package/package.json +61 -47
  209. package/dist/runtime/imports/resolveSSRValue.d.ts +0 -1
  210. package/dist/runtime/imports/resolveSSRValue.js +0 -8
  211. package/dist/runtime/render/renderRscThenableToHtmlStream.js +0 -54
  212. package/dist/runtime/render/transformRscToHtmlStream.d.ts +0 -8
  213. package/dist/runtime/render/transformRscToHtmlStream.js +0 -19
  214. /package/dist/lib/{normalizeModulePath.test.d.ts → e2e/types.mjs} +0 -0
@@ -1,3 +1,3 @@
1
1
  import "./types/shared";
2
- export * from "../lib/router";
3
2
  export * from "../lib/links";
3
+ export * from "../lib/router";
@@ -1,3 +1,3 @@
1
1
  import "./types/shared";
2
- export * from "../lib/router";
3
2
  export * from "../lib/links";
3
+ export * from "../lib/router";
@@ -1,11 +1,10 @@
1
1
  import "./types/worker";
2
- export * from "../register/worker";
3
- export * from "../worker";
4
2
  export * from "../error";
5
- export * from "../script";
6
3
  export * from "../lib/utils";
4
+ export * from "../register/worker";
5
+ export * from "../render/renderToStream";
6
+ export * from "../render/renderToString";
7
7
  export * from "../requestInfo/types";
8
8
  export * from "../requestInfo/worker";
9
- export * from "../render/renderToString";
10
- export * from "../render/renderToStream";
11
- export * from "../imports/resolveSSRValue";
9
+ export * from "../script";
10
+ export * from "../worker";
@@ -1,11 +1,10 @@
1
1
  import "./types/worker";
2
- export * from "../register/worker";
3
- export * from "../worker";
4
2
  export * from "../error";
5
- export * from "../script";
6
3
  export * from "../lib/utils";
4
+ export * from "../register/worker";
5
+ export * from "../render/renderToStream";
6
+ export * from "../render/renderToString";
7
7
  export * from "../requestInfo/types";
8
8
  export * from "../requestInfo/worker";
9
- export * from "../render/renderToString";
10
- export * from "../render/renderToStream";
11
- export * from "../imports/resolveSSRValue";
9
+ export * from "../script";
10
+ export * from "../worker";
@@ -1,6 +1,6 @@
1
- import { requestInfo } from "../requestInfo/worker";
2
1
  import { ssrWebpackRequire as baseSsrWebpackRequire } from "rwsdk/__ssr_bridge";
3
2
  import { memoizeOnId } from "../lib/memoizeOnId";
3
+ import { requestInfo } from "../requestInfo/worker";
4
4
  // @ts-ignore
5
5
  import { useServerLookup } from "virtual:use-server-lookup.js";
6
6
  export const loadServerModule = memoizeOnId(async (id) => {
@@ -35,10 +35,10 @@ export declare const defineSessionStore: <Session, SessionInputData>({ cookieNam
35
35
  unset: (sessionId: string) => Promise<void>;
36
36
  }) => {
37
37
  load: (request: Request) => Promise<Session | null>;
38
- save: (headers: Headers, sessionInputData: SessionInputData, { maxAge }?: {
38
+ save: (responseHeaders: Headers, sessionInputData: SessionInputData, { maxAge }?: {
39
39
  maxAge?: number | true;
40
40
  }) => Promise<void>;
41
- remove: (request: Request, headers: Headers) => Promise<void>;
41
+ remove: (request: Request, responseHeaders: Headers) => Promise<void>;
42
42
  };
43
43
  type SessionStoreFromDurableObject<SessionDurableObject> = SessionDurableObject extends DurableObjectMethods<infer Session, infer SessionInputData> ? SessionStore<Session, SessionInputData> : never;
44
44
  export declare const defineDurableSession: <SessionDurableObject extends DurableObjectMethods<any, any>>({ cookieName, createCookie, secretKey, sessionDurableObject, }: {
@@ -1,5 +1,5 @@
1
- import { ErrorResponse } from "../../error";
2
1
  import { env } from "cloudflare:workers";
2
+ import { ErrorResponse } from "../../error";
3
3
  const AUTH_SECRET_KEY = env.AUTH_SECRET_KEY ??
4
4
  (import.meta.env.VITE_IS_DEV_SERVER
5
5
  ? "development-secret-key-do-not-use-in-production"
@@ -89,17 +89,17 @@ export const defineSessionStore = ({ cookieName = "session_id", createCookie = c
89
89
  throw new ErrorResponse(401, "Invalid session id");
90
90
  }
91
91
  };
92
- const save = async (headers, sessionInputData, { maxAge } = {}) => {
92
+ const save = async (responseHeaders, sessionInputData, { maxAge } = {}) => {
93
93
  const sessionId = await generateSessionId({ secretKey });
94
94
  await set(sessionId, sessionInputData);
95
- headers.set("Set-Cookie", createCookie({ name: cookieName, sessionId, maxAge }));
95
+ responseHeaders.set("Set-Cookie", createCookie({ name: cookieName, sessionId, maxAge }));
96
96
  };
97
- const remove = async (request, headers) => {
97
+ const remove = async (request, responseHeaders) => {
98
98
  const sessionId = getSessionIdFromCookie(request);
99
99
  if (sessionId) {
100
100
  await unset(sessionId);
101
101
  }
102
- headers.set("Set-Cookie", createCookie({ name: cookieName, sessionId: "", maxAge: 0 }));
102
+ responseHeaders.set("Set-Cookie", createCookie({ name: cookieName, sessionId: "", maxAge: 0 }));
103
103
  };
104
104
  return {
105
105
  load,
@@ -1,4 +1,4 @@
1
- import { SqliteAdapter, SqliteIntrospector, SqliteQueryCompiler, Driver, DatabaseConnection, QueryResult } from "kysely";
1
+ import { DatabaseConnection, Driver, QueryResult, SqliteAdapter, SqliteIntrospector, SqliteQueryCompiler } from "kysely";
2
2
  type DOWorkerDialectConfig = {
3
3
  kyselyExecuteQuery: (compiledQuery: {
4
4
  sql: string;
@@ -1,5 +1,5 @@
1
- import debug from "../debug";
2
1
  import { SqliteAdapter, SqliteIntrospector, SqliteQueryCompiler, } from "kysely";
2
+ import debug from "../debug";
3
3
  const log = debug("sdk:db:do-worker-dialect");
4
4
  export class DOWorkerDialect {
5
5
  constructor(config) {
@@ -1,8 +1,8 @@
1
- import { DODialect } from "kysely-do";
2
1
  import { DurableObject } from "cloudflare:workers";
2
+ import { DODialect } from "kysely-do";
3
3
  import { Kysely, ParseJSONResultsPlugin, } from "kysely";
4
- import { createMigrator } from "./index.js";
5
4
  import debug from "../debug.js";
5
+ import { createMigrator } from "./index.js";
6
6
  const log = debug("sdk:do-db");
7
7
  // Base class for Durable Objects that need Kysely database access
8
8
  export class SqliteDurableObject extends DurableObject {
@@ -1,5 +1,5 @@
1
+ export { sql } from "kysely";
2
+ export * from "./createDb.js";
1
3
  export * from "./migrations.js";
2
4
  export * from "./SqliteDurableObject.js";
3
- export * from "./createDb.js";
4
5
  export type * from "./typeInference/database.js";
5
- export { sql } from "kysely";
@@ -1,4 +1,4 @@
1
+ export { sql } from "kysely";
2
+ export * from "./createDb.js";
1
3
  export * from "./migrations.js";
2
4
  export * from "./SqliteDurableObject.js";
3
- export * from "./createDb.js";
4
- export { sql } from "kysely";
@@ -1,4 +1,4 @@
1
- import { Kysely, Migration, Migrator, MigrationProvider } from "kysely";
1
+ import { Kysely, Migration, MigrationProvider, Migrator } from "kysely";
2
2
  /**
3
3
  * A custom MigrationProvider that works with in-memory migrations
4
4
  * rather than reading from files.
@@ -1,7 +1,7 @@
1
- import { SqlToTsType, ExecutedBuilder, AlterOperation, AddColumnOp, DropColumnOp, RenameColumnOp, AlterColumnOp, ModifyColumnOp } from "../utils";
2
- import { ColumnDefinitionBuilder } from "./columnDefinition";
1
+ import { CheckConstraintNode, Expression, ForeignKeyConstraintBuilder, PrimaryKeyConstraintNode, sql, UniqueConstraintNode } from "kysely";
2
+ import { AddColumnOp, AlterColumnOp, AlterOperation, DropColumnOp, ExecutedBuilder, ModifyColumnOp, RenameColumnOp, SqlToTsType } from "../utils";
3
3
  import { AlterColumnBuilderCallback } from "./alterColumn";
4
- import { ForeignKeyConstraintBuilder, Expression, CheckConstraintNode, UniqueConstraintNode, PrimaryKeyConstraintNode, sql } from "kysely";
4
+ import { ColumnDefinitionBuilder } from "./columnDefinition";
5
5
  type DataTypeExpression = string | typeof sql;
6
6
  interface CheckConstraintBuilder {
7
7
  $call<T>(func: (qb: this) => T): T;
@@ -1,4 +1,4 @@
1
- import { Expression, sql, ColumnDefinitionNode } from "kysely";
1
+ import { ColumnDefinitionNode, Expression, sql } from "kysely";
2
2
  type DefaultValueExpression = string | number | boolean | null | typeof sql;
3
3
  export interface ColumnDefinitionBuilder<TType> {
4
4
  autoIncrement(): ColumnDefinitionBuilder<TType>;
@@ -1,6 +1,6 @@
1
- import { SqlToTsType, ExecutedBuilder, Prettify } from "../utils";
1
+ import { CheckConstraintNode, CompiledQuery, CreateTableNode, Expression, ForeignKeyConstraintBuilder, PrimaryKeyConstraintNode, UniqueConstraintNode } from "kysely";
2
+ import { ExecutedBuilder, Prettify, SqlToTsType } from "../utils";
2
3
  import { ColumnDefinitionBuilder } from "./columnDefinition";
3
- import { CompiledQuery, CreateTableNode, Expression, ForeignKeyConstraintBuilder, CheckConstraintNode, UniqueConstraintNode, PrimaryKeyConstraintNode } from "kysely";
4
4
  interface CheckConstraintBuilder {
5
5
  $call<T>(func: (qb: this) => T): T;
6
6
  toOperationNode(): CheckConstraintNode;
@@ -1,5 +1,5 @@
1
+ import { CompiledQuery, CreateViewNode, RawBuilder, SelectQueryBuilder } from "kysely";
1
2
  import { ExecutedBuilder } from "../utils";
2
- import { CreateViewNode, CompiledQuery, SelectQueryBuilder, RawBuilder } from "kysely";
3
3
  export interface CreateViewBuilder<TName extends string, TSchema extends Record<string, any> = {}, TColumns extends string[] = []> {
4
4
  readonly __viewName: TName;
5
5
  readonly __schema: TSchema;
@@ -1,5 +1,5 @@
1
+ import { CompiledQuery, DropTableNode } from "kysely";
1
2
  import { ExecutedBuilder } from "../utils";
2
- import { DropTableNode, CompiledQuery } from "kysely";
3
3
  export interface DropTableBuilder<TName extends string> {
4
4
  readonly __tableName: TName;
5
5
  ifExists(): DropTableBuilder<TName>;
@@ -1,5 +1,5 @@
1
+ import { CompiledQuery, DropViewNode } from "kysely";
1
2
  import { ExecutedBuilder } from "../utils";
2
- import { DropViewNode, CompiledQuery } from "kysely";
3
3
  export interface DropViewBuilder<TName extends string> {
4
4
  readonly __viewName: TName;
5
5
  ifExists(): DropViewBuilder<TName>;
@@ -1,9 +1,9 @@
1
- import { CreateTableBuilder } from "./createTable";
1
+ import { CreateIndexBuilder, CreateSchemaBuilder, CreateTypeBuilder, DropIndexBuilder, DropSchemaBuilder, DropTypeBuilder, KyselyPlugin, RefreshMaterializedViewBuilder } from "kysely";
2
2
  import { AlterTableBuilder } from "./alterTable";
3
- import { DropTableBuilder } from "./dropTable";
3
+ import { CreateTableBuilder } from "./createTable";
4
4
  import { CreateViewBuilder } from "./createView";
5
+ import { DropTableBuilder } from "./dropTable";
5
6
  import { DropViewBuilder } from "./dropView";
6
- import { CreateIndexBuilder, DropIndexBuilder, CreateSchemaBuilder, DropSchemaBuilder, CreateTypeBuilder, DropTypeBuilder, KyselyPlugin, RefreshMaterializedViewBuilder } from "kysely";
7
7
  export interface SchemaBuilder {
8
8
  createTable<TName extends string>(name: TName): CreateTableBuilder<TName, {}>;
9
9
  alterTable<TName extends string>(name: TName): AlterTableBuilder<TName, []>;
@@ -1,9 +1,9 @@
1
1
  import { Kysely } from "kysely";
2
- import { ExecutedBuilder, Prettify, ProcessAlteredTable, UnionToTuple } from "./utils";
3
- import { CreateTableBuilder } from "./builders/createTable";
4
2
  import { AlterTableBuilder } from "./builders/alterTable";
3
+ import { CreateTableBuilder } from "./builders/createTable";
5
4
  import { DropTableBuilder } from "./builders/dropTable";
6
5
  import { SchemaBuilder } from "./builders/schema";
6
+ import { ExecutedBuilder, Prettify, ProcessAlteredTable, UnionToTuple } from "./utils";
7
7
  export interface InferenceBuilder {
8
8
  schema: SchemaBuilder;
9
9
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,49 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { memoizeOnId } from "./memoizeOnId";
3
+ describe("memoizeOnId", () => {
4
+ it("should call the function only once for the same id", () => {
5
+ const fn = vi.fn((id) => `result-${id}`);
6
+ const memoizedFn = memoizeOnId(fn);
7
+ const result1 = memoizedFn("a");
8
+ const result2 = memoizedFn("a");
9
+ expect(result1).toBe("result-a");
10
+ expect(result2).toBe("result-a");
11
+ expect(fn).toHaveBeenCalledTimes(1);
12
+ expect(fn).toHaveBeenCalledWith("a");
13
+ });
14
+ it("should call the function again for a different id", () => {
15
+ const fn = vi.fn((id) => `result-${id}`);
16
+ const memoizedFn = memoizeOnId(fn);
17
+ const result1 = memoizedFn("a");
18
+ const result2 = memoizedFn("b");
19
+ expect(result1).toBe("result-a");
20
+ expect(result2).toBe("result-b");
21
+ expect(fn).toHaveBeenCalledTimes(2);
22
+ expect(fn).toHaveBeenCalledWith("a");
23
+ expect(fn).toHaveBeenCalledWith("b");
24
+ });
25
+ it("should return the correct cached value for multiple calls", () => {
26
+ const fn = vi.fn((id) => ({ id }));
27
+ const memoizedFn = memoizeOnId(fn);
28
+ const resultA1 = memoizedFn("a");
29
+ const resultB1 = memoizedFn("b");
30
+ const resultA2 = memoizedFn("a");
31
+ expect(resultA1).toEqual({ id: "a" });
32
+ expect(resultB1).toEqual({ id: "b" });
33
+ expect(resultA2).toBe(resultA1); // Should be the same object reference
34
+ expect(fn).toHaveBeenCalledTimes(2);
35
+ });
36
+ it("should handle object properties that exist on Object.prototype", () => {
37
+ const fn = vi.fn((id) => `result-${id}`);
38
+ const memoizedFn = memoizeOnId(fn);
39
+ const result1 = memoizedFn("constructor");
40
+ const result2 = memoizedFn("toString");
41
+ const result3 = memoizedFn("constructor");
42
+ expect(result1).toBe("result-constructor");
43
+ expect(result2).toBe("result-toString");
44
+ expect(result3).toBe("result-constructor");
45
+ expect(fn).toHaveBeenCalledTimes(2);
46
+ expect(fn).toHaveBeenCalledWith("constructor");
47
+ expect(fn).toHaveBeenCalledWith("toString");
48
+ });
49
+ });
@@ -1,7 +1,7 @@
1
- import { initClient } from "../../client/client";
2
1
  import { createFromReadableStream } from "react-server-dom-webpack/client.browser";
3
- import { MESSAGE_TYPE } from "./shared";
2
+ import { initClient } from "../../client/client";
4
3
  import { packMessage, unpackMessage, } from "./protocol";
4
+ import { MESSAGE_TYPE } from "./shared";
5
5
  const DEFAULT_KEY = "default";
6
6
  export const initRealtimeClient = ({ key = DEFAULT_KEY, handleResponse, } = {}) => {
7
7
  const transport = realtimeTransport({ key, handleResponse });
@@ -1,7 +1,7 @@
1
1
  import { DurableObject } from "cloudflare:workers";
2
+ import { packMessage, unpackMessage, } from "./protocol";
2
3
  import { MESSAGE_TYPE } from "./shared";
3
4
  import { validateUpgradeRequest } from "./validateUpgradeRequest";
4
- import { packMessage, unpackMessage, } from "./protocol";
5
5
  export class RealtimeDurableObject extends DurableObject {
6
6
  constructor(state, env) {
7
7
  super(state, env);
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,107 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { packMessage, unpackMessage } from "./protocol";
3
+ import { MESSAGE_TYPE } from "./shared";
4
+ describe("Realtime Protocol pack/unpack", () => {
5
+ const textEncoder = new TextEncoder();
6
+ // Helper to generate a UUID string of the correct length
7
+ const generateId = () => "a".repeat(36);
8
+ const testMessages = [
9
+ {
10
+ type: MESSAGE_TYPE.ACTION_REQUEST,
11
+ id: "my-action",
12
+ args: { foo: "bar" },
13
+ requestId: generateId(),
14
+ clientUrl: "http://localhost:3000/",
15
+ },
16
+ {
17
+ type: MESSAGE_TYPE.ACTION_START,
18
+ id: generateId(),
19
+ status: 200,
20
+ },
21
+ {
22
+ type: MESSAGE_TYPE.ACTION_CHUNK,
23
+ id: generateId(),
24
+ payload: textEncoder.encode("chunk data"),
25
+ },
26
+ {
27
+ type: MESSAGE_TYPE.ACTION_END,
28
+ id: generateId(),
29
+ },
30
+ {
31
+ type: MESSAGE_TYPE.ACTION_ERROR,
32
+ id: generateId(),
33
+ error: "Something went wrong",
34
+ },
35
+ {
36
+ type: MESSAGE_TYPE.RSC_START,
37
+ id: generateId(),
38
+ status: 200,
39
+ },
40
+ {
41
+ type: MESSAGE_TYPE.RSC_CHUNK,
42
+ id: generateId(),
43
+ payload: textEncoder.encode("rsc chunk"),
44
+ },
45
+ {
46
+ type: MESSAGE_TYPE.RSC_END,
47
+ id: generateId(),
48
+ },
49
+ ];
50
+ testMessages.forEach((message) => {
51
+ it(`should correctly pack and unpack a ${Object.keys(MESSAGE_TYPE).find((key) => MESSAGE_TYPE[key] === message.type) || "UNKNOWN"} message`, () => {
52
+ const packed = packMessage(message);
53
+ const unpacked = unpackMessage(packed);
54
+ expect(unpacked).toEqual(message);
55
+ });
56
+ });
57
+ describe("Error Handling", () => {
58
+ it("should throw an error for an unknown message type on pack", () => {
59
+ const invalidMessage = { type: 999 };
60
+ expect(() => packMessage(invalidMessage)).toThrow("Unknown message type for packing");
61
+ });
62
+ it("should throw an error for an unknown message type on unpack", () => {
63
+ const invalidData = new Uint8Array([99, 1, 2, 3]);
64
+ expect(() => unpackMessage(invalidData)).toThrow("Unknown message type for unpacking: 99");
65
+ });
66
+ it("should throw an error for an empty message on unpack", () => {
67
+ const emptyData = new Uint8Array([]);
68
+ expect(() => unpackMessage(emptyData)).toThrow("Cannot unpack empty message");
69
+ });
70
+ const invalidLengthTests = [
71
+ { type: MESSAGE_TYPE.ACTION_START, name: "START" },
72
+ { type: MESSAGE_TYPE.RSC_START, name: "START" },
73
+ { type: MESSAGE_TYPE.ACTION_CHUNK, name: "CHUNK" },
74
+ { type: MESSAGE_TYPE.RSC_CHUNK, name: "CHUNK" },
75
+ { type: MESSAGE_TYPE.ACTION_END, name: "END" },
76
+ { type: MESSAGE_TYPE.RSC_END, name: "END" },
77
+ { type: MESSAGE_TYPE.ACTION_ERROR, name: "ERROR" },
78
+ ];
79
+ invalidLengthTests.forEach(({ type, name }) => {
80
+ it(`should throw for invalid ${name} message length on unpack`, () => {
81
+ const invalidData = new Uint8Array([type, 1, 2, 3]); // Too short
82
+ expect(() => unpackMessage(invalidData)).toThrow(`Invalid ${name} message length`);
83
+ });
84
+ });
85
+ const invalidIdTests = [
86
+ { type: MESSAGE_TYPE.ACTION_START, name: "START" },
87
+ { type: MESSAGE_TYPE.RSC_START, name: "START" },
88
+ { type: MESSAGE_TYPE.ACTION_CHUNK, name: "CHUNK" },
89
+ { type: MESSAGE_TYPE.RSC_CHUNK, name: "CHUNK" },
90
+ { type: MESSAGE_TYPE.ACTION_END, name: "END" },
91
+ { type: MESSAGE_TYPE.RSC_END, name: "END" },
92
+ { type: MESSAGE_TYPE.ACTION_ERROR, name: "ERROR" },
93
+ ];
94
+ invalidIdTests.forEach(({ type, name }) => {
95
+ it(`should throw for invalid ID length on ${name} message pack`, () => {
96
+ const message = {
97
+ type,
98
+ id: "short-id",
99
+ status: 200, // For START types
100
+ payload: new Uint8Array(), // For CHUNK types
101
+ error: "", // For ERROR type
102
+ };
103
+ expect(() => packMessage(message)).toThrow(`Invalid message ID length for ${name} message`);
104
+ });
105
+ });
106
+ });
107
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,18 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { MESSAGE_TYPE } from "./shared";
3
+ describe("Realtime Shared Constants", () => {
4
+ it("MESSAGE_TYPE should match snapshot", () => {
5
+ expect(MESSAGE_TYPE).toMatchInlineSnapshot(`
6
+ {
7
+ "ACTION_CHUNK": 5,
8
+ "ACTION_END": 6,
9
+ "ACTION_ERROR": 7,
10
+ "ACTION_REQUEST": 3,
11
+ "ACTION_START": 4,
12
+ "RSC_CHUNK": 1,
13
+ "RSC_END": 2,
14
+ "RSC_START": 0,
15
+ }
16
+ `);
17
+ });
18
+ });
@@ -0,0 +1,66 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { validateUpgradeRequest } from "./validateUpgradeRequest";
3
+ describe("validateUpgradeRequest", () => {
4
+ it("should return valid for a correct WebSocket upgrade request", () => {
5
+ const request = new Request("http://localhost:8787/ws", {
6
+ headers: {
7
+ Upgrade: "websocket",
8
+ Origin: "http://localhost:8787",
9
+ },
10
+ });
11
+ const result = validateUpgradeRequest(request);
12
+ expect(result.valid).toBe(true);
13
+ });
14
+ it("should return invalid if Upgrade header is not 'websocket'", async () => {
15
+ const request = new Request("http://localhost:8787/ws", {
16
+ headers: {
17
+ Upgrade: "not-websocket",
18
+ Origin: "http://localhost:8787",
19
+ },
20
+ });
21
+ const result = validateUpgradeRequest(request);
22
+ expect(result.valid).toBe(false);
23
+ if (!result.valid) {
24
+ expect(result.response?.status).toBe(400);
25
+ await expect(result.response?.text()).resolves.toBe("Expected WebSocket");
26
+ }
27
+ });
28
+ it("should return invalid if Upgrade header is missing", () => {
29
+ const request = new Request("http://localhost:8787/ws", {
30
+ headers: {
31
+ Origin: "http://localhost:8787",
32
+ },
33
+ });
34
+ const result = validateUpgradeRequest(request);
35
+ expect(result.valid).toBe(false);
36
+ if (!result.valid) {
37
+ expect(result.response?.status).toBe(400);
38
+ }
39
+ });
40
+ it("should return invalid if Origin header is missing", async () => {
41
+ const request = new Request("http://localhost:8787/ws", {
42
+ headers: {
43
+ Upgrade: "websocket",
44
+ },
45
+ });
46
+ const result = validateUpgradeRequest(request);
47
+ expect(result.valid).toBe(false);
48
+ if (!result.valid) {
49
+ expect(result.response?.status).toBe(403);
50
+ await expect(result.response?.text()).resolves.toBe("Invalid origin");
51
+ }
52
+ });
53
+ it("should return invalid if Origin does not match request URL", () => {
54
+ const request = new Request("http://localhost:8787/ws", {
55
+ headers: {
56
+ Upgrade: "websocket",
57
+ Origin: "http://another-domain.com",
58
+ },
59
+ });
60
+ const result = validateUpgradeRequest(request);
61
+ expect(result.valid).toBe(false);
62
+ if (!result.valid) {
63
+ expect(result.response?.status).toBe(403);
64
+ }
65
+ });
66
+ });
@@ -1,3 +1,3 @@
1
1
  import type { RealtimeDurableObject } from "./durableObject";
2
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>>;
3
+ export declare const realtimeRoute: (getDurableObjectNamespace: (env: Cloudflare.Env) => DurableObjectNamespace<RealtimeDurableObject>) => import("../router").RouteDefinition<import("../../worker").RequestInfo<any, import("../../worker").DefaultAppContext>>;
@@ -1,7 +1,7 @@
1
+ import { env } from "cloudflare:workers";
1
2
  import { route } from "../../entries/router";
2
- import { validateUpgradeRequest } from "./validateUpgradeRequest";
3
3
  import { DEFAULT_REALTIME_KEY } from "./constants";
4
- import { env } from "cloudflare:workers";
4
+ import { validateUpgradeRequest } from "./validateUpgradeRequest";
5
5
  export { renderRealtimeClients } from "./renderRealtimeClients";
6
6
  export const realtimeRoute = (getDurableObjectNamespace) => route("/__realtime", async function ({ request }) {
7
7
  const validation = validateUpgradeRequest(request);
@@ -1,6 +1,6 @@
1
+ import type { Kysely } from "kysely";
1
2
  import React from "react";
2
3
  import { RequestInfo } from "../requestInfo/types";
3
- import type { Kysely } from "kysely";
4
4
  export type DocumentProps<T extends RequestInfo = RequestInfo> = T & {
5
5
  children: React.ReactNode;
6
6
  };
@@ -97,30 +97,38 @@ export function defineRoutes(routes) {
97
97
  return undefined;
98
98
  }
99
99
  // --- Main flow ---
100
- const globalMiddlewares = flattenedRoutes.filter((route) => typeof route === "function");
101
- const routeDefinitions = flattenedRoutes.filter((route) => typeof route !== "function");
102
- // 1. Run global middlewares
103
- for (const middleware of globalMiddlewares) {
104
- const result = await middleware(getRequestInfo());
105
- const handled = await handleMiddlewareResult(result);
106
- if (handled) {
107
- return handled;
100
+ let firstRouteDefinitionEncountered = false;
101
+ let actionHandled = false;
102
+ const handleAction = async () => {
103
+ if (!actionHandled && url.searchParams.has("__rsc_action_id")) {
104
+ getRequestInfo().rw.actionResult = await rscActionHandler(request);
105
+ actionHandled = true;
106
+ }
107
+ };
108
+ for (const route of flattenedRoutes) {
109
+ if (typeof route === "function") {
110
+ // This is a global middleware.
111
+ const result = await route(getRequestInfo());
112
+ const handled = await handleMiddlewareResult(result);
113
+ if (handled) {
114
+ return handled; // Short-circuit
115
+ }
116
+ continue;
117
+ }
118
+ // This is a RouteDefinition.
119
+ // The first time we see one, we handle any RSC actions.
120
+ if (!firstRouteDefinitionEncountered) {
121
+ firstRouteDefinitionEncountered = true;
122
+ await handleAction();
108
123
  }
109
- }
110
- // 2. Handle RSC actions
111
- if (url.searchParams.has("__rsc_action_id")) {
112
- getRequestInfo().rw.actionResult = await rscActionHandler(request);
113
- }
114
- // 3. Match and handle routes
115
- for (const route of routeDefinitions) {
116
124
  const params = matchPath(route.path, path);
117
125
  if (!params) {
118
- continue;
126
+ continue; // Not a match, keep going.
119
127
  }
120
- // Found a match: run route-specific middlewares, then the final component
128
+ // Found a match: run route-specific middlewares, then the final component, then stop.
121
129
  return await runWithRequestInfoOverrides({ params }, async () => {
122
130
  const { routeMiddlewares, componentHandler } = parseHandlers(route.handler);
123
- // 3a. Route-specific middlewares
131
+ // Route-specific middlewares
124
132
  for (const mw of routeMiddlewares) {
125
133
  const result = await mw(getRequestInfo());
126
134
  const handled = await handleMiddlewareResult(result);
@@ -128,7 +136,7 @@ export function defineRoutes(routes) {
128
136
  return handled;
129
137
  }
130
138
  }
131
- // 3b. Final component/handler
139
+ // Final component/handler
132
140
  if (isRouteComponent(componentHandler)) {
133
141
  const requestInfo = getRequestInfo();
134
142
  const WrappedComponent = wrapWithLayouts(wrapHandlerToThrowResponses(componentHandler), route.layouts || [], requestInfo);
@@ -148,7 +156,11 @@ export function defineRoutes(routes) {
148
156
  });
149
157
  });
150
158
  }
151
- // No route matched
159
+ // If we've gotten this far, no route was matched.
160
+ // We still need to handle a possible action if the app has no route definitions at all.
161
+ if (!firstRouteDefinitionEncountered) {
162
+ await handleAction();
163
+ }
152
164
  return new Response("Not Found", { status: 404 });
153
165
  },
154
166
  };
@@ -168,8 +180,14 @@ export function index(handler) {
168
180
  export function prefix(prefixPath, routes) {
169
181
  return routes.map((r) => {
170
182
  if (typeof r === "function") {
171
- // Pass through middleware as-is
172
- return r;
183
+ const middleware = (requestInfo) => {
184
+ const url = new URL(requestInfo.request.url);
185
+ if (url.pathname.startsWith(prefixPath)) {
186
+ return r(requestInfo);
187
+ }
188
+ return;
189
+ };
190
+ return middleware;
173
191
  }
174
192
  if (Array.isArray(r)) {
175
193
  // Recursively process nested route arrays