@reckona/mreact-router 0.0.203 → 0.0.205

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 (140) hide show
  1. package/README.md +53 -9
  2. package/dist/actions.d.ts +6 -0
  3. package/dist/actions.d.ts.map +1 -1
  4. package/dist/actions.js +70 -10
  5. package/dist/actions.js.map +1 -1
  6. package/dist/adapters/aws-lambda.d.ts +15 -4
  7. package/dist/adapters/aws-lambda.d.ts.map +1 -1
  8. package/dist/adapters/aws-lambda.js +301 -63
  9. package/dist/adapters/aws-lambda.js.map +1 -1
  10. package/dist/adapters/cloudflare.d.ts +2 -1
  11. package/dist/adapters/cloudflare.d.ts.map +1 -1
  12. package/dist/adapters/cloudflare.js +18 -10
  13. package/dist/adapters/cloudflare.js.map +1 -1
  14. package/dist/adapters/edge.d.ts +1 -1
  15. package/dist/adapters/edge.d.ts.map +1 -1
  16. package/dist/adapters/edge.js.map +1 -1
  17. package/dist/adapters/node.d.ts +5 -3
  18. package/dist/adapters/node.d.ts.map +1 -1
  19. package/dist/adapters/node.js +2 -1
  20. package/dist/adapters/node.js.map +1 -1
  21. package/dist/adapters/static.d.ts.map +1 -1
  22. package/dist/adapters/static.js +24 -2
  23. package/dist/adapters/static.js.map +1 -1
  24. package/dist/build.d.ts +1 -0
  25. package/dist/build.d.ts.map +1 -1
  26. package/dist/build.js +91 -5
  27. package/dist/build.js.map +1 -1
  28. package/dist/built-runtime.d.ts +2 -0
  29. package/dist/built-runtime.d.ts.map +1 -1
  30. package/dist/built-runtime.js +16 -0
  31. package/dist/built-runtime.js.map +1 -1
  32. package/dist/cache.d.ts +3 -1
  33. package/dist/cache.d.ts.map +1 -1
  34. package/dist/cache.js +211 -13
  35. package/dist/cache.js.map +1 -1
  36. package/dist/cli.js +12 -1
  37. package/dist/cli.js.map +1 -1
  38. package/dist/client.d.ts.map +1 -1
  39. package/dist/client.js +32 -1
  40. package/dist/client.js.map +1 -1
  41. package/dist/config.d.ts +3 -0
  42. package/dist/config.d.ts.map +1 -1
  43. package/dist/config.js +21 -2
  44. package/dist/config.js.map +1 -1
  45. package/dist/csp.d.ts +1 -0
  46. package/dist/csp.d.ts.map +1 -1
  47. package/dist/csp.js +11 -6
  48. package/dist/csp.js.map +1 -1
  49. package/dist/dehydrate-policy.d.ts +3 -0
  50. package/dist/dehydrate-policy.d.ts.map +1 -0
  51. package/dist/dehydrate-policy.js +16 -0
  52. package/dist/dehydrate-policy.js.map +1 -0
  53. package/dist/dev-server.d.ts +7 -2
  54. package/dist/dev-server.d.ts.map +1 -1
  55. package/dist/dev-server.js +120 -11
  56. package/dist/dev-server.js.map +1 -1
  57. package/dist/http.d.ts +1 -1
  58. package/dist/http.d.ts.map +1 -1
  59. package/dist/http.js +147 -7
  60. package/dist/http.js.map +1 -1
  61. package/dist/index.d.ts +4 -3
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +1 -0
  64. package/dist/index.js.map +1 -1
  65. package/dist/logger.d.ts +22 -1
  66. package/dist/logger.d.ts.map +1 -1
  67. package/dist/logger.js +22 -8
  68. package/dist/logger.js.map +1 -1
  69. package/dist/metadata.d.ts +8 -0
  70. package/dist/metadata.d.ts.map +1 -1
  71. package/dist/metadata.js +60 -22
  72. package/dist/metadata.js.map +1 -1
  73. package/dist/navigation-marker.d.ts.map +1 -1
  74. package/dist/navigation-marker.js +72 -9
  75. package/dist/navigation-marker.js.map +1 -1
  76. package/dist/navigation.d.ts +1 -0
  77. package/dist/navigation.d.ts.map +1 -1
  78. package/dist/navigation.js +1 -1
  79. package/dist/navigation.js.map +1 -1
  80. package/dist/node-server.d.ts +5 -2
  81. package/dist/node-server.d.ts.map +1 -1
  82. package/dist/node-server.js +75 -6
  83. package/dist/node-server.js.map +1 -1
  84. package/dist/prerender-entry.d.ts +14 -0
  85. package/dist/prerender-entry.d.ts.map +1 -1
  86. package/dist/prerender-entry.js +40 -3
  87. package/dist/prerender-entry.js.map +1 -1
  88. package/dist/render.d.ts +9 -1
  89. package/dist/render.d.ts.map +1 -1
  90. package/dist/render.js +102 -123
  91. package/dist/render.js.map +1 -1
  92. package/dist/serve.d.ts +8 -2
  93. package/dist/serve.d.ts.map +1 -1
  94. package/dist/serve.js +22 -20
  95. package/dist/serve.js.map +1 -1
  96. package/dist/session.d.ts.map +1 -1
  97. package/dist/session.js +52 -19
  98. package/dist/session.js.map +1 -1
  99. package/dist/upgrade.d.ts +59 -2
  100. package/dist/upgrade.d.ts.map +1 -1
  101. package/dist/upgrade.js +282 -1
  102. package/dist/upgrade.js.map +1 -1
  103. package/dist/vite-config.d.ts +2 -0
  104. package/dist/vite-config.d.ts.map +1 -1
  105. package/dist/vite-config.js +2 -0
  106. package/dist/vite-config.js.map +1 -1
  107. package/dist/vite.d.ts +4 -1
  108. package/dist/vite.d.ts.map +1 -1
  109. package/dist/vite.js +117 -6
  110. package/dist/vite.js.map +1 -1
  111. package/package.json +11 -11
  112. package/src/actions.ts +81 -11
  113. package/src/adapters/aws-lambda.ts +426 -115
  114. package/src/adapters/cloudflare.ts +29 -13
  115. package/src/adapters/edge.ts +2 -0
  116. package/src/adapters/node.ts +8 -10
  117. package/src/adapters/static.ts +31 -2
  118. package/src/build.ts +117 -10
  119. package/src/built-runtime.ts +28 -0
  120. package/src/cache.ts +262 -15
  121. package/src/cli.ts +14 -1
  122. package/src/client.ts +32 -1
  123. package/src/config.ts +43 -6
  124. package/src/csp.ts +14 -11
  125. package/src/dehydrate-policy.ts +23 -0
  126. package/src/dev-server.ts +188 -15
  127. package/src/http.ts +172 -6
  128. package/src/index.ts +14 -1
  129. package/src/logger.ts +47 -10
  130. package/src/metadata.ts +125 -60
  131. package/src/navigation-marker.ts +79 -9
  132. package/src/navigation.ts +1 -1
  133. package/src/node-server.ts +128 -22
  134. package/src/prerender-entry.ts +52 -3
  135. package/src/render.ts +807 -753
  136. package/src/serve.ts +49 -56
  137. package/src/session.ts +56 -25
  138. package/src/upgrade.ts +402 -3
  139. package/src/vite-config.ts +6 -0
  140. package/src/vite.ts +157 -5
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAyC1E,MAAM,uBAAuB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AACjD,MAAM,kBAAkB,GAAG,gBAAgB,CAAC;AAC5C,MAAM,mBAAmB,GAAG,uBAAuB,CAAC;AAEpD,SAAS,YAAY;IACnB,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC;AAC/C,CAAC;AAED,SAAS,iBAAiB;IACxB,OAAO,YAAY,EAAE,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,kBAAkB,CAAC;AACnE,CAAC;AAED,SAAS,oBAAoB,CAAC,OAAO,GAAyB,EAAE;IAC9D,MAAM,UAAU,GAAG,YAAY,EAAE,CAAC;IAElC,OAAO;QACL,QAAQ,EAAE,IAAI;QACd,MAAM,EAAE,OAAO,CAAC,aAAa,IAAI,uBAAuB;QACxD,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,IAAI,GAAG;QAC5C,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,KAAK;QACnC,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,UAAU;KAC5B,CAAC;AACb,CAAC;AAED,SAAS,aAAa,CACpB,OAAgB,EAChB,OAAO,GAAyB,EAAE;IAElC,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;IAChE,OAAO,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,IAAI,iBAAiB,EAAE,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,eAAe;IACtB,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IAEjC,UAAU,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAEzC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IAED,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACjF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CACtC,OAAO,GAA8B,EAAE;IAEvC,MAAM,UAAU,GAAG,wBAAwB,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACzE,MAAM,eAAe,GAAG,2BAA2B,CAAC,OAAO,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IACrF,MAAM,OAAO,GAAG,IAAI,GAAG,EAAgC,CAAC;IACxD,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,SAAS,YAAY,CAAC,GAAW;QAC/B,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;YAClC,IAAI,KAAK,CAAC,SAAS,IAAI,GAAG,EAAE,CAAC;gBAC3B,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;QAED,WAAW,GAAG,GAAG,GAAG,eAAe,CAAC;IACtC,CAAC;IAED,SAAS,iBAAiB,CAAC,GAAW;QACpC,IAAI,eAAe,KAAK,CAAC,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC;YAChD,YAAY,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IAED,SAAS,kBAAkB;QACzB,OAAO,OAAO,CAAC,IAAI,GAAG,UAAU,EAAE,CAAC;YACjC,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;YAE7C,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC3B,OAAO;YACT,CAAC;YAED,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,OAAO;QACL,MAAM,CAAC,EAAE;YACP,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACrB,CAAC;QACD,GAAG,CAAC,EAAE;YACJ,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,iBAAiB,CAAC,GAAG,CAAC,CAAC;YACvB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAE/B,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,SAAS,IAAI,GAAG,EAAE,CAAC;gBACpD,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACnB,OAAO,SAAS,CAAC;YACnB,CAAC;YAED,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACnB,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;YAC1B,CAAC;YAED,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,GAAG,CAAC,MAAM;YACR,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,iBAAiB,CAAC,GAAG,CAAC,CAAC;YAEvB,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC1B,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;YAE/B,IAAI,OAAO,CAAC,IAAI,GAAG,UAAU,EAAE,CAAC;gBAC9B,YAAY,CAAC,GAAG,CAAC,CAAC;gBAClB,kBAAkB,EAAE,CAAC;YACvB,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,wBAAwB,CAAC,KAAyB,EAAE,QAAgB;IAC3E,OAAO,KAAK,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;AACzF,CAAC;AAED,SAAS,2BAA2B,CAAC,KAAyB,EAAE,QAAgB;IAC9E,OAAO,KAAK,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;AACzF,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,OAAgB,EAChB,KAA0B,EAC1B,OAAO,GAAyB,EAAE;IAElC,MAAM,EAAE,GAAG,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAE3C,IAAI,EAAE,KAAK,SAAS,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEnC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;QACnC,MAAM,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACvB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,QAAkB,EAClB,KAA0B,EAC1B,IAAW,EACX,OAAO,GAAyB,EAAE;IAElC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,uBAAuB,CAAC;IACvE,MAAM,MAAM,GAAyB;QACnC,SAAS,EAAE,GAAG;QACd,IAAI;QACJ,SAAS,EAAE,GAAG,GAAG,aAAa,GAAG,IAAI;QACrC,EAAE,EAAE,eAAe,EAAE;KACtB,CAAC;IAEF,MAAM,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACxB,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,UAAU,IAAI,iBAAiB,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE;QACxE,GAAG,oBAAoB,CAAC,EAAE,GAAG,OAAO,EAAE,aAAa,EAAE,CAAC;KACvD,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAgB,EAChB,QAAkB,EAClB,KAA0B,EAC1B,OAAO,GAAyB,EAAE;IAElC,MAAM,EAAE,GAAG,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAE3C,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;QACrB,MAAM,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACzB,CAAC;IAED,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,UAAU,IAAI,iBAAiB,EAAE,EAAE;QAChE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,IAAI,GAAG;QAChD,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,KAAK;QACnC,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,YAAY,EAAE;KACzC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAAgB,EAChB,QAAkB,EAClB,KAA0B,EAC1B,OAAO,GAAyB,EAAE;IAElC,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAE1D,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC/B,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAEzE,OAAO,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;AAC5C,CAAC","sourcesContent":["import { deleteCookie, parseCookieHeader, setCookie } from \"./cookies.js\";\n\n/**\n * Stores session data and expiration metadata for one session id.\n */\nexport interface SessionRecord<TData = unknown> {\n createdAt: number;\n data: TData;\n expiresAt: number;\n id: string;\n rotatedAt?: number;\n}\n\n/**\n * Defines the persistence API used by app-router session helpers.\n */\nexport interface SessionStore<TData = unknown> {\n delete(id: string): void | Promise<void>;\n get(id: string): SessionRecord<TData> | undefined | Promise<SessionRecord<TData> | undefined>;\n set(record: SessionRecord<TData>): void | Promise<void>;\n}\n\n/**\n * Configures the process-local memory session store.\n */\nexport interface MemorySessionStoreOptions {\n maxEntries?: number;\n sweepIntervalMs?: number;\n}\n\n/**\n * Configures the cookie used by app-router session helpers.\n */\nexport interface SessionCookieOptions {\n cookieName?: string;\n maxAgeSeconds?: number;\n path?: string;\n sameSite?: \"Strict\" | \"Lax\" | \"None\";\n secure?: boolean;\n}\n\nconst DEFAULT_MAX_AGE_SECONDS = 7 * 24 * 60 * 60;\nconst SESSION_COOKIE_DEV = \"mreact.session\";\nconst SESSION_COOKIE_PROD = \"__Host-mreact.session\";\n\nfunction isProduction(): boolean {\n return process.env.NODE_ENV === \"production\";\n}\n\nfunction defaultCookieName(): string {\n return isProduction() ? SESSION_COOKIE_PROD : SESSION_COOKIE_DEV;\n}\n\nfunction sessionCookieOptions(options: SessionCookieOptions = {}) {\n const production = isProduction();\n\n return {\n httpOnly: true,\n maxAge: options.maxAgeSeconds ?? DEFAULT_MAX_AGE_SECONDS,\n path: production ? \"/\" : options.path ?? \"/\",\n sameSite: options.sameSite ?? \"Lax\",\n secure: options.secure ?? production,\n } as const;\n}\n\nfunction readSessionId(\n request: Request,\n options: SessionCookieOptions = {},\n): string | undefined {\n const values = parseCookieHeader(request.headers.get(\"cookie\"));\n return values.get(options.cookieName ?? defaultCookieName());\n}\n\nfunction createSessionId(): string {\n const bytes = new Uint8Array(32);\n\n globalThis.crypto.getRandomValues(bytes);\n\n let binary = \"\";\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n\n return btoa(binary).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n/**\n * Creates a process-local session store backed by an in-memory LRU-like map.\n *\n * Use it for development, tests, or single-process deployments; production multi-instance deployments should provide a shared `SessionStore`.\n */\nexport function createMemorySessionStore<TData>(\n options: MemorySessionStoreOptions = {},\n): SessionStore<TData> {\n const maxEntries = positiveIntegerOrDefault(options.maxEntries, 100_000);\n const sweepIntervalMs = nonNegativeIntegerOrDefault(options.sweepIntervalMs, 60_000);\n const records = new Map<string, SessionRecord<TData>>();\n let nextSweepAt = 0;\n\n function sweepExpired(now: number): void {\n for (const [id, value] of records) {\n if (value.expiresAt <= now) {\n records.delete(id);\n }\n }\n\n nextSweepAt = now + sweepIntervalMs;\n }\n\n function maybeSweepExpired(now: number): void {\n if (sweepIntervalMs === 0 || now >= nextSweepAt) {\n sweepExpired(now);\n }\n }\n\n function evictOldestEntries(): void {\n while (records.size > maxEntries) {\n const oldestId = records.keys().next().value;\n\n if (oldestId === undefined) {\n return;\n }\n\n records.delete(oldestId);\n }\n }\n\n return {\n delete(id) {\n records.delete(id);\n },\n get(id) {\n const now = Date.now();\n maybeSweepExpired(now);\n const record = records.get(id);\n\n if (record !== undefined && record.expiresAt <= now) {\n records.delete(id);\n return undefined;\n }\n\n if (record !== undefined) {\n records.delete(id);\n records.set(id, record);\n }\n\n return record;\n },\n set(record) {\n const now = Date.now();\n maybeSweepExpired(now);\n\n records.delete(record.id);\n records.set(record.id, record);\n\n if (records.size > maxEntries) {\n sweepExpired(now);\n evictOldestEntries();\n }\n },\n };\n}\n\nfunction positiveIntegerOrDefault(value: number | undefined, fallback: number): number {\n return value === undefined || !Number.isInteger(value) || value < 1 ? fallback : value;\n}\n\nfunction nonNegativeIntegerOrDefault(value: number | undefined, fallback: number): number {\n return value === undefined || !Number.isInteger(value) || value < 0 ? fallback : value;\n}\n\n/**\n * Reads the current session cookie, loads the matching session record, and deletes expired records.\n */\nexport async function getSession<TData>(\n request: Request,\n store: SessionStore<TData>,\n options: SessionCookieOptions = {},\n): Promise<SessionRecord<TData> | undefined> {\n const id = readSessionId(request, options);\n\n if (id === undefined || id.length === 0) {\n return undefined;\n }\n\n const record = await store.get(id);\n\n if (record === undefined) {\n return undefined;\n }\n\n if (record.expiresAt <= Date.now()) {\n await store.delete(id);\n return undefined;\n }\n\n return record;\n}\n\n/**\n * Creates a new session record, stores it, and appends the session cookie to the response.\n */\nexport async function createSession<TData>(\n response: Response,\n store: SessionStore<TData>,\n data: TData,\n options: SessionCookieOptions = {},\n): Promise<SessionRecord<TData>> {\n const now = Date.now();\n const maxAgeSeconds = options.maxAgeSeconds ?? DEFAULT_MAX_AGE_SECONDS;\n const record: SessionRecord<TData> = {\n createdAt: now,\n data,\n expiresAt: now + maxAgeSeconds * 1000,\n id: createSessionId(),\n };\n\n await store.set(record);\n setCookie(response, options.cookieName ?? defaultCookieName(), record.id, {\n ...sessionCookieOptions({ ...options, maxAgeSeconds }),\n });\n\n return record;\n}\n\n/**\n * Deletes the current session record when present and appends an expiring session cookie to the response.\n */\nexport async function destroySession<TData>(\n request: Request,\n response: Response,\n store: SessionStore<TData>,\n options: SessionCookieOptions = {},\n): Promise<void> {\n const id = readSessionId(request, options);\n\n if (id !== undefined) {\n await store.delete(id);\n }\n\n deleteCookie(response, options.cookieName ?? defaultCookieName(), {\n path: isProduction() ? \"/\" : options.path ?? \"/\",\n sameSite: options.sameSite ?? \"Lax\",\n secure: options.secure ?? isProduction(),\n });\n}\n\n/**\n * Replaces the current session id while preserving the stored session data.\n *\n * Use this after authentication or privilege changes to reduce session fixation risk.\n */\nexport async function rotateSession<TData>(\n request: Request,\n response: Response,\n store: SessionStore<TData>,\n options: SessionCookieOptions = {},\n): Promise<SessionRecord<TData> | undefined> {\n const current = await getSession(request, store, options);\n\n if (current === undefined) {\n return undefined;\n }\n\n await store.delete(current.id);\n const next = await createSession(response, store, current.data, options);\n\n return { ...next, rotatedAt: Date.now() };\n}\n"]}
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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","sourcesContent":["import { deleteCookie, parseCookieHeader, serializeCookie, setCookie } from \"./cookies.js\";\n\n/**\n * Stores session data and expiration metadata for one session id.\n */\nexport interface SessionRecord<TData = unknown> {\n createdAt: number;\n data: TData;\n expiresAt: number;\n id: string;\n rotatedAt?: number;\n}\n\n/**\n * Defines the persistence API used by app-router session helpers.\n */\nexport interface SessionStore<TData = unknown> {\n delete(id: string): void | Promise<void>;\n get(id: string): SessionRecord<TData> | undefined | Promise<SessionRecord<TData> | undefined>;\n set(record: SessionRecord<TData>): void | Promise<void>;\n}\n\n/**\n * Configures the process-local memory session store.\n */\nexport interface MemorySessionStoreOptions {\n maxEntries?: number;\n sweepIntervalMs?: number;\n}\n\n/**\n * Configures the cookie used by app-router session helpers.\n */\nexport interface SessionCookieOptions {\n cookieName?: string;\n maxAgeSeconds?: number;\n path?: string;\n sameSite?: \"Strict\" | \"Lax\" | \"None\";\n secure?: boolean;\n}\n\nconst DEFAULT_MAX_AGE_SECONDS = 7 * 24 * 60 * 60;\nconst SESSION_COOKIE_DEV = \"mreact.session\";\nconst SESSION_COOKIE_PROD = \"__Host-mreact.session\";\n\nfunction usesHardenedCookieDefaults(): boolean {\n const nodeEnv = typeof process === \"undefined\" ? undefined : process[\"env\"]?.[\"NODE_ENV\"];\n return nodeEnv !== \"development\" && nodeEnv !== \"test\";\n}\n\nfunction resolveSessionCookie(options: SessionCookieOptions = {}) {\n const hardened = usesHardenedCookieDefaults();\n const cookieOptions = {\n httpOnly: true,\n maxAge: options.maxAgeSeconds ?? DEFAULT_MAX_AGE_SECONDS,\n path: options.path ?? \"/\",\n sameSite: options.sameSite ?? \"Lax\",\n secure: options.secure ?? hardened,\n } as const;\n const canUseHostPrefix = cookieOptions.secure && cookieOptions.path === \"/\";\n\n return {\n name:\n options.cookieName ??\n (hardened && canUseHostPrefix ? SESSION_COOKIE_PROD : SESSION_COOKIE_DEV),\n options: cookieOptions,\n };\n}\n\nfunction validateResolvedSessionCookie(cookie: ReturnType<typeof resolveSessionCookie>): void {\n serializeCookie(cookie.name, \"\", cookie.options);\n}\n\nfunction assertMutableResponseHeaders(response: Response): void {\n const probeName = \"x-mreact-session-header-probe\";\n const previous = response.headers.get(probeName);\n\n try {\n response.headers.set(probeName, \"1\");\n if (previous === null) {\n response.headers.delete(probeName);\n } else {\n response.headers.set(probeName, previous);\n }\n } catch (cause) {\n throw new TypeError(\"Session helpers require a Response with mutable headers.\", { cause });\n }\n}\n\nfunction readSessionId(request: Request, options: SessionCookieOptions = {}): string | undefined {\n const cookie = resolveSessionCookie(options);\n const values = parseCookieHeader(request.headers.get(\"cookie\"));\n return values.get(cookie.name);\n}\n\nfunction createSessionId(): string {\n const bytes = new Uint8Array(32);\n\n globalThis.crypto.getRandomValues(bytes);\n\n let binary = \"\";\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n\n return btoa(binary).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n/**\n * Creates a process-local session store backed by an in-memory LRU-like map.\n *\n * Use it for development, tests, or single-process deployments; production multi-instance deployments should provide a shared `SessionStore`.\n */\nexport function createMemorySessionStore<TData>(\n options: MemorySessionStoreOptions = {},\n): SessionStore<TData> {\n const maxEntries = positiveIntegerOrDefault(options.maxEntries, 100_000);\n const sweepIntervalMs = nonNegativeIntegerOrDefault(options.sweepIntervalMs, 60_000);\n const records = new Map<string, SessionRecord<TData>>();\n let nextSweepAt = 0;\n\n function sweepExpired(now: number): void {\n for (const [id, value] of records) {\n if (value.expiresAt <= now) {\n records.delete(id);\n }\n }\n\n nextSweepAt = now + sweepIntervalMs;\n }\n\n function maybeSweepExpired(now: number): void {\n if (sweepIntervalMs === 0 || now >= nextSweepAt) {\n sweepExpired(now);\n }\n }\n\n function evictOldestEntries(): void {\n while (records.size > maxEntries) {\n const oldestId = records.keys().next().value;\n\n if (oldestId === undefined) {\n return;\n }\n\n records.delete(oldestId);\n }\n }\n\n return {\n delete(id) {\n records.delete(id);\n },\n get(id) {\n const now = Date.now();\n maybeSweepExpired(now);\n const record = records.get(id);\n\n if (record !== undefined && record.expiresAt <= now) {\n records.delete(id);\n return undefined;\n }\n\n if (record !== undefined) {\n records.delete(id);\n records.set(id, record);\n }\n\n return record;\n },\n set(record) {\n const now = Date.now();\n maybeSweepExpired(now);\n\n records.delete(record.id);\n records.set(record.id, record);\n\n if (records.size > maxEntries) {\n sweepExpired(now);\n evictOldestEntries();\n }\n },\n };\n}\n\nfunction positiveIntegerOrDefault(value: number | undefined, fallback: number): number {\n return value === undefined || !Number.isInteger(value) || value < 1 ? fallback : value;\n}\n\nfunction nonNegativeIntegerOrDefault(value: number | undefined, fallback: number): number {\n return value === undefined || !Number.isInteger(value) || value < 0 ? fallback : value;\n}\n\n/**\n * Reads the current session cookie, loads the matching session record, and deletes expired records.\n */\nexport async function getSession<TData>(\n request: Request,\n store: SessionStore<TData>,\n options: SessionCookieOptions = {},\n): Promise<SessionRecord<TData> | undefined> {\n const id = readSessionId(request, options);\n\n if (id === undefined || id.length === 0) {\n return undefined;\n }\n\n const record = await store.get(id);\n\n if (record === undefined) {\n return undefined;\n }\n\n if (record.expiresAt <= Date.now()) {\n await store.delete(id);\n return undefined;\n }\n\n return record;\n}\n\n/**\n * Creates a new session record, stores it, and appends the session cookie to the response.\n */\nexport async function createSession<TData>(\n response: Response,\n store: SessionStore<TData>,\n data: TData,\n options: SessionCookieOptions = {},\n): Promise<SessionRecord<TData>> {\n const now = Date.now();\n const maxAgeSeconds = options.maxAgeSeconds ?? DEFAULT_MAX_AGE_SECONDS;\n const cookie = resolveSessionCookie({ ...options, maxAgeSeconds });\n validateResolvedSessionCookie(cookie);\n assertMutableResponseHeaders(response);\n const record: SessionRecord<TData> = {\n createdAt: now,\n data,\n expiresAt: now + maxAgeSeconds * 1000,\n id: createSessionId(),\n };\n\n await store.set(record);\n setCookie(response, cookie.name, record.id, cookie.options);\n\n return record;\n}\n\n/**\n * Deletes the current session record when present and appends an expiring session cookie to the response.\n */\nexport async function destroySession<TData>(\n request: Request,\n response: Response,\n store: SessionStore<TData>,\n options: SessionCookieOptions = {},\n): Promise<void> {\n const cookie = resolveSessionCookie(options);\n validateResolvedSessionCookie({\n name: cookie.name,\n options: { ...cookie.options, maxAge: 0 },\n });\n assertMutableResponseHeaders(response);\n const id = readSessionId(request, options);\n\n if (id !== undefined) {\n await store.delete(id);\n }\n\n deleteCookie(response, cookie.name, {\n path: cookie.options.path,\n sameSite: cookie.options.sameSite,\n secure: cookie.options.secure,\n });\n}\n\n/**\n * Replaces the current session id while preserving the stored session data.\n *\n * Use this after authentication or privilege changes to reduce session fixation risk.\n */\nexport async function rotateSession<TData>(\n request: Request,\n response: Response,\n store: SessionStore<TData>,\n options: SessionCookieOptions = {},\n): Promise<SessionRecord<TData> | undefined> {\n validateResolvedSessionCookie(resolveSessionCookie(options));\n assertMutableResponseHeaders(response);\n const current = await getSession(request, store, options);\n\n if (current === undefined) {\n return undefined;\n }\n\n await store.delete(current.id);\n const next = await createSession(response, store, current.data, options);\n\n return { ...next, rotatedAt: Date.now() };\n}\n"]}
package/dist/upgrade.d.ts CHANGED
@@ -1,7 +1,64 @@
1
- import type { IncomingMessage } from "node:http";
1
+ import type { IncomingMessage, Server } from "node:http";
2
2
  import type { Duplex } from "node:stream";
3
+ import { type AppRouterLogger } from "./logger.js";
4
+ export type HttpUpgradeDisposition = "declined" | "handled";
3
5
  /**
4
- * Handles an HTTP upgrade request on the app-router Node server.
6
+ * Explicitly claims or declines one HTTP upgrade before asynchronous verification begins.
5
7
  */
8
+ export interface HttpUpgradeContext {
9
+ accept(): HttpUpgradeDisposition;
10
+ decline(): HttpUpgradeDisposition;
11
+ }
12
+ /** Handles an HTTP upgrade using the legacy three-argument callback contract. */
6
13
  export type HttpUpgradeHandler = (request: IncomingMessage, socket: Duplex, head: Buffer) => void;
14
+ /**
15
+ * Handles a managed HTTP upgrade on the app-router Node server.
16
+ *
17
+ * Existing `HttpUpgradeHandler` callbacks remain assignable. Handlers that defer verification must
18
+ * call `context.accept()` synchronously; returning without writing a handshake is treated as a
19
+ * decline.
20
+ */
21
+ export type ManagedHttpUpgradeHandler = (request: IncomingMessage, socket: Duplex, head: Buffer, context: HttpUpgradeContext) => void;
22
+ export type HttpUpgradeOriginFailureReason = "disallowed-origin" | "malformed-origin" | "missing-origin" | "opaque-origin";
23
+ export type HttpUpgradeOriginValidation = {
24
+ ok: true;
25
+ origin: string | undefined;
26
+ } | {
27
+ ok: false;
28
+ reason: HttpUpgradeOriginFailureReason;
29
+ };
30
+ export interface ValidateHttpUpgradeOriginOptions {
31
+ allowedOrigins: readonly string[];
32
+ allowMissingOrigin?: boolean | undefined;
33
+ }
34
+ export type HttpUpgradeOriginPolicy = "same-origin" | "unchecked" | {
35
+ allowedOrigins: readonly string[];
36
+ allowMissingOrigin?: boolean | undefined;
37
+ };
38
+ export declare function assertValidHttpUpgradeOriginPolicy(policy: HttpUpgradeOriginPolicy | undefined): void;
39
+ /**
40
+ * Validates a WebSocket/HTTP upgrade Origin against exact serialized origins.
41
+ *
42
+ * Missing origins are rejected by default. Configured origins must contain only an HTTP(S)
43
+ * scheme, host, and optional port; paths, credentials, queries, and fragments are invalid.
44
+ */
45
+ export declare function validateHttpUpgradeOrigin(request: IncomingMessage, options: ValidateHttpUpgradeOriginOptions): HttpUpgradeOriginValidation;
46
+ export interface ManagedHttpUpgradeOptions {
47
+ decisionTimeoutMs: number;
48
+ handler: ManagedHttpUpgradeHandler;
49
+ isOriginAllowed(request: IncomingMessage): HttpUpgradeOriginValidation;
50
+ logger?: AppRouterLogger | undefined;
51
+ shouldBypass?: ((request: IncomingMessage) => boolean) | undefined;
52
+ }
53
+ export interface ManagedHttpUpgradeLifecycle {
54
+ beginClose(): void;
55
+ handle(request: IncomingMessage, socket: Duplex, head: Buffer): void;
56
+ waitForSockets(timeoutMs: number): Promise<void>;
57
+ }
58
+ export declare function createManagedHttpUpgradeLifecycle(options: ManagedHttpUpgradeOptions): ManagedHttpUpgradeLifecycle;
59
+ export declare function closeServerWithUpgrades(options: {
60
+ lifecycle: ManagedHttpUpgradeLifecycle;
61
+ server: Server;
62
+ timeoutMs: number;
63
+ }): Promise<void>;
7
64
  //# sourceMappingURL=upgrade.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"upgrade.d.ts","sourceRoot":"","sources":["../src/upgrade.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAC/B,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,KACT,IAAI,CAAC"}
1
+ {"version":3,"file":"upgrade.d.ts","sourceRoot":"","sources":["../src/upgrade.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAML,KAAK,eAAe,EACrB,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,sBAAsB,GAAG,UAAU,GAAG,SAAS,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,IAAI,sBAAsB,CAAC;IACjC,OAAO,IAAI,sBAAsB,CAAC;CACnC;AAED,iFAAiF;AACjF,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;AAElG;;;;;;GAMG;AACH,MAAM,MAAM,yBAAyB,GAAG,CACtC,OAAO,EAAE,eAAe,EACxB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,kBAAkB,KACxB,IAAI,CAAC;AAEV,MAAM,MAAM,8BAA8B,GACtC,mBAAmB,GACnB,kBAAkB,GAClB,gBAAgB,GAChB,eAAe,CAAC;AAEpB,MAAM,MAAM,2BAA2B,GACnC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GACxC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,8BAA8B,CAAA;CAAE,CAAC;AAE1D,MAAM,WAAW,gCAAgC;IAC/C,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,kBAAkB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC1C;AAED,MAAM,MAAM,uBAAuB,GAC/B,aAAa,GACb,WAAW,GACX;IACE,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,kBAAkB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC1C,CAAC;AAEN,wBAAgB,kCAAkC,CAChD,MAAM,EAAE,uBAAuB,GAAG,SAAS,GAC1C,IAAI,CAMN;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,gCAAgC,GACxC,2BAA2B,CAwB7B;AAqCD,MAAM,WAAW,yBAAyB;IACxC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,yBAAyB,CAAC;IACnC,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,2BAA2B,CAAC;IACvE,MAAM,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC;IACrC,YAAY,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,eAAe,KAAK,OAAO,CAAC,GAAG,SAAS,CAAC;CACpE;AAED,MAAM,WAAW,2BAA2B;IAC1C,UAAU,IAAI,IAAI,CAAC;IACnB,MAAM,CAAC,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACrE,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClD;AAED,wBAAgB,iCAAiC,CAC/C,OAAO,EAAE,yBAAyB,GACjC,2BAA2B,CA8N7B;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE;IAC/C,SAAS,EAAE,2BAA2B,CAAC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAShB"}
package/dist/upgrade.js CHANGED
@@ -1,2 +1,283 @@
1
- export {};
1
+ import { emitRouterLog, logDurationMs, logError, logNow, nodeRequestPath, } from "./logger.js";
2
+ export function assertValidHttpUpgradeOriginPolicy(policy) {
3
+ if (typeof policy === "object") {
4
+ for (const origin of policy.allowedOrigins) {
5
+ normalizeConfiguredOrigin(origin);
6
+ }
7
+ }
8
+ }
9
+ /**
10
+ * Validates a WebSocket/HTTP upgrade Origin against exact serialized origins.
11
+ *
12
+ * Missing origins are rejected by default. Configured origins must contain only an HTTP(S)
13
+ * scheme, host, and optional port; paths, credentials, queries, and fragments are invalid.
14
+ */
15
+ export function validateHttpUpgradeOrigin(request, options) {
16
+ const allowedOrigins = options.allowedOrigins.map(normalizeConfiguredOrigin);
17
+ const value = request.headers.origin;
18
+ if (value === undefined) {
19
+ return options.allowMissingOrigin === true
20
+ ? { ok: true, origin: undefined }
21
+ : { ok: false, reason: "missing-origin" };
22
+ }
23
+ if (Array.isArray(value) || value.includes(",")) {
24
+ return { ok: false, reason: "malformed-origin" };
25
+ }
26
+ if (value === "null") {
27
+ return { ok: false, reason: "opaque-origin" };
28
+ }
29
+ const origin = normalizeRequestOrigin(value);
30
+ if (origin === undefined) {
31
+ return { ok: false, reason: "malformed-origin" };
32
+ }
33
+ return allowedOrigins.includes(origin)
34
+ ? { ok: true, origin }
35
+ : { ok: false, reason: "disallowed-origin" };
36
+ }
37
+ function normalizeConfiguredOrigin(value) {
38
+ const origin = normalizeOrigin(value);
39
+ if (origin === undefined) {
40
+ throw new TypeError(`Invalid HTTP upgrade allowed origin: ${value}`);
41
+ }
42
+ return origin;
43
+ }
44
+ function normalizeRequestOrigin(value) {
45
+ return normalizeOrigin(value);
46
+ }
47
+ function normalizeOrigin(value) {
48
+ let url;
49
+ try {
50
+ url = new URL(value);
51
+ }
52
+ catch {
53
+ return undefined;
54
+ }
55
+ if ((url.protocol !== "http:" && url.protocol !== "https:") ||
56
+ url.username !== "" ||
57
+ url.password !== "" ||
58
+ url.pathname !== "/" ||
59
+ url.search !== "" ||
60
+ url.hash !== "" ||
61
+ url.origin === "null") {
62
+ return undefined;
63
+ }
64
+ return url.origin;
65
+ }
66
+ export function createManagedHttpUpgradeLifecycle(options) {
67
+ const sockets = new Set();
68
+ const emptyWaiters = new Set();
69
+ const pendingDecisionCancels = new Set();
70
+ let closing = false;
71
+ function track(socket) {
72
+ sockets.add(socket);
73
+ socket.once("close", () => {
74
+ sockets.delete(socket);
75
+ if (sockets.size === 0) {
76
+ for (const resolve of emptyWaiters) {
77
+ resolve();
78
+ }
79
+ emptyWaiters.clear();
80
+ }
81
+ });
82
+ }
83
+ function destroy(socket) {
84
+ if (!socket.destroyed) {
85
+ socket.destroy();
86
+ }
87
+ }
88
+ function emitError(request, startedAt, error) {
89
+ emitRouterLog(options.logger, "error", {
90
+ durationMs: logDurationMs(startedAt),
91
+ error: logError(error),
92
+ method: request.method ?? "GET",
93
+ path: nodeRequestPath(request.url),
94
+ runtime: "node",
95
+ type: "router:upgrade:error",
96
+ });
97
+ if (options.logger === undefined) {
98
+ try {
99
+ console.error("[mreact] HTTP upgrade handler failed:", error);
100
+ }
101
+ catch {
102
+ // Failure reporting must never escape the HTTP upgrade listener.
103
+ }
104
+ }
105
+ }
106
+ function handle(request, socket, head) {
107
+ const startedAt = logNow();
108
+ if (closing) {
109
+ destroy(socket);
110
+ return;
111
+ }
112
+ let bypass = false;
113
+ try {
114
+ bypass = options.shouldBypass?.(request) === true;
115
+ }
116
+ catch (error) {
117
+ emitError(request, startedAt, error);
118
+ destroy(socket);
119
+ return;
120
+ }
121
+ if (bypass) {
122
+ return;
123
+ }
124
+ track(socket);
125
+ let origin;
126
+ try {
127
+ origin = options.isOriginAllowed(request);
128
+ }
129
+ catch (error) {
130
+ emitError(request, startedAt, error);
131
+ destroy(socket);
132
+ return;
133
+ }
134
+ if (!origin.ok) {
135
+ emitRouterLog(options.logger, "warn", {
136
+ method: request.method ?? "GET",
137
+ path: nodeRequestPath(request.url),
138
+ reason: origin.reason,
139
+ runtime: "node",
140
+ type: "router:upgrade:rejected",
141
+ });
142
+ destroy(socket);
143
+ return;
144
+ }
145
+ let disposition;
146
+ let decisionTimer;
147
+ let failureReported = false;
148
+ let socketClosed = false;
149
+ const clearDecisionTimer = () => {
150
+ if (decisionTimer !== undefined) {
151
+ clearTimeout(decisionTimer);
152
+ decisionTimer = undefined;
153
+ }
154
+ pendingDecisionCancels.delete(clearDecisionTimer);
155
+ };
156
+ socket.once("close", () => {
157
+ socketClosed = true;
158
+ clearDecisionTimer();
159
+ });
160
+ const before = {
161
+ bytesWritten: socketBytesWritten(socket),
162
+ destroyed: socket.destroyed,
163
+ writableEnded: socket.writableEnded,
164
+ };
165
+ const decide = (next) => {
166
+ if (disposition !== undefined) {
167
+ return disposition;
168
+ }
169
+ disposition = next;
170
+ clearDecisionTimer();
171
+ if (next === "declined") {
172
+ destroy(socket);
173
+ }
174
+ return next;
175
+ };
176
+ const context = {
177
+ accept: () => decide("handled"),
178
+ decline: () => decide("declined"),
179
+ };
180
+ const fail = (error) => {
181
+ if (failureReported) {
182
+ return;
183
+ }
184
+ failureReported = true;
185
+ clearDecisionTimer();
186
+ emitError(request, startedAt, error);
187
+ disposition ??= "declined";
188
+ destroy(socket);
189
+ };
190
+ let result;
191
+ try {
192
+ result = options.handler(request, socket, head, context);
193
+ }
194
+ catch (error) {
195
+ fail(error);
196
+ return;
197
+ }
198
+ if ((typeof result === "object" || typeof result === "function") && result !== null) {
199
+ if (disposition === undefined && !closing && !socketClosed) {
200
+ decisionTimer = setTimeout(() => {
201
+ if (disposition === undefined) {
202
+ fail(new Error(`HTTP upgrade decision timed out after ${options.decisionTimeoutMs}ms.`));
203
+ }
204
+ }, options.decisionTimeoutMs);
205
+ decisionTimer.unref?.();
206
+ pendingDecisionCancels.add(clearDecisionTimer);
207
+ }
208
+ void Promise.resolve(result).then((value) => {
209
+ if (socketClosed) {
210
+ return;
211
+ }
212
+ if (value === "declined" || value === "handled") {
213
+ decide(value);
214
+ }
215
+ else if (disposition === undefined) {
216
+ decide(legacySocketAction(socket, before) ? "handled" : "declined");
217
+ }
218
+ }, (error) => {
219
+ fail(error);
220
+ });
221
+ return;
222
+ }
223
+ if (result === "declined" || result === "handled") {
224
+ decide(result);
225
+ }
226
+ else if (disposition === undefined) {
227
+ decide(legacySocketAction(socket, before) ? "handled" : "declined");
228
+ }
229
+ }
230
+ return {
231
+ beginClose() {
232
+ if (closing) {
233
+ return;
234
+ }
235
+ closing = true;
236
+ for (const cancel of pendingDecisionCancels) {
237
+ cancel();
238
+ }
239
+ },
240
+ handle,
241
+ async waitForSockets(timeoutMs) {
242
+ if (sockets.size === 0) {
243
+ return;
244
+ }
245
+ await new Promise((resolve) => {
246
+ let settled = false;
247
+ const finish = () => {
248
+ if (settled) {
249
+ return;
250
+ }
251
+ settled = true;
252
+ clearTimeout(timer);
253
+ emptyWaiters.delete(finish);
254
+ resolve();
255
+ };
256
+ const timer = setTimeout(() => {
257
+ for (const socket of sockets) {
258
+ destroy(socket);
259
+ }
260
+ finish();
261
+ }, timeoutMs);
262
+ timer.unref?.();
263
+ emptyWaiters.add(finish);
264
+ });
265
+ },
266
+ };
267
+ }
268
+ export function closeServerWithUpgrades(options) {
269
+ options.lifecycle.beginClose();
270
+ const serverClosed = new Promise((resolve, reject) => {
271
+ options.server.close((error) => (error ? reject(error) : resolve()));
272
+ });
273
+ return Promise.all([serverClosed, options.lifecycle.waitForSockets(options.timeoutMs)]).then(() => undefined);
274
+ }
275
+ function legacySocketAction(socket, before) {
276
+ return (socketBytesWritten(socket) !== before.bytesWritten ||
277
+ socket.destroyed !== before.destroyed ||
278
+ socket.writableEnded !== before.writableEnded);
279
+ }
280
+ function socketBytesWritten(socket) {
281
+ return socket.bytesWritten;
282
+ }
2
283
  //# sourceMappingURL=upgrade.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"upgrade.js","sourceRoot":"","sources":["../src/upgrade.ts"],"names":[],"mappings":"","sourcesContent":["import type { IncomingMessage } from \"node:http\";\nimport type { Duplex } from \"node:stream\";\n\n/**\n * Handles an HTTP upgrade request on the app-router Node server.\n */\nexport type HttpUpgradeHandler = (\n request: IncomingMessage,\n socket: Duplex,\n head: Buffer,\n) => void;\n"]}
1
+ {"version":3,"file":"upgrade.js","sourceRoot":"","sources":["../src/upgrade.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IncomingMessage, Server } from \"node:http\";\nimport type { Duplex } from \"node:stream\";\nimport {\n emitRouterLog,\n logDurationMs,\n logError,\n logNow,\n nodeRequestPath,\n type AppRouterLogger,\n} from \"./logger.js\";\n\nexport type HttpUpgradeDisposition = \"declined\" | \"handled\";\n\n/**\n * Explicitly claims or declines one HTTP upgrade before asynchronous verification begins.\n */\nexport interface HttpUpgradeContext {\n accept(): HttpUpgradeDisposition;\n decline(): HttpUpgradeDisposition;\n}\n\n/** Handles an HTTP upgrade using the legacy three-argument callback contract. */\nexport type HttpUpgradeHandler = (request: IncomingMessage, socket: Duplex, head: Buffer) => void;\n\n/**\n * Handles a managed HTTP upgrade on the app-router Node server.\n *\n * Existing `HttpUpgradeHandler` callbacks remain assignable. Handlers that defer verification must\n * call `context.accept()` synchronously; returning without writing a handshake is treated as a\n * decline.\n */\nexport type ManagedHttpUpgradeHandler = (\n request: IncomingMessage,\n socket: Duplex,\n head: Buffer,\n context: HttpUpgradeContext,\n) => void;\n\nexport type HttpUpgradeOriginFailureReason =\n | \"disallowed-origin\"\n | \"malformed-origin\"\n | \"missing-origin\"\n | \"opaque-origin\";\n\nexport type HttpUpgradeOriginValidation =\n | { ok: true; origin: string | undefined }\n | { ok: false; reason: HttpUpgradeOriginFailureReason };\n\nexport interface ValidateHttpUpgradeOriginOptions {\n allowedOrigins: readonly string[];\n allowMissingOrigin?: boolean | undefined;\n}\n\nexport type HttpUpgradeOriginPolicy =\n | \"same-origin\"\n | \"unchecked\"\n | {\n allowedOrigins: readonly string[];\n allowMissingOrigin?: boolean | undefined;\n };\n\nexport function assertValidHttpUpgradeOriginPolicy(\n policy: HttpUpgradeOriginPolicy | undefined,\n): void {\n if (typeof policy === \"object\") {\n for (const origin of policy.allowedOrigins) {\n normalizeConfiguredOrigin(origin);\n }\n }\n}\n\n/**\n * Validates a WebSocket/HTTP upgrade Origin against exact serialized origins.\n *\n * Missing origins are rejected by default. Configured origins must contain only an HTTP(S)\n * scheme, host, and optional port; paths, credentials, queries, and fragments are invalid.\n */\nexport function validateHttpUpgradeOrigin(\n request: IncomingMessage,\n options: ValidateHttpUpgradeOriginOptions,\n): HttpUpgradeOriginValidation {\n const allowedOrigins = options.allowedOrigins.map(normalizeConfiguredOrigin);\n const value = request.headers.origin;\n\n if (value === undefined) {\n return options.allowMissingOrigin === true\n ? { ok: true, origin: undefined }\n : { ok: false, reason: \"missing-origin\" };\n }\n if (Array.isArray(value) || value.includes(\",\")) {\n return { ok: false, reason: \"malformed-origin\" };\n }\n if (value === \"null\") {\n return { ok: false, reason: \"opaque-origin\" };\n }\n\n const origin = normalizeRequestOrigin(value);\n if (origin === undefined) {\n return { ok: false, reason: \"malformed-origin\" };\n }\n\n return allowedOrigins.includes(origin)\n ? { ok: true, origin }\n : { ok: false, reason: \"disallowed-origin\" };\n}\n\nfunction normalizeConfiguredOrigin(value: string): string {\n const origin = normalizeOrigin(value);\n if (origin === undefined) {\n throw new TypeError(`Invalid HTTP upgrade allowed origin: ${value}`);\n }\n return origin;\n}\n\nfunction normalizeRequestOrigin(value: string): string | undefined {\n return normalizeOrigin(value);\n}\n\nfunction normalizeOrigin(value: string): string | undefined {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n return undefined;\n }\n\n if (\n (url.protocol !== \"http:\" && url.protocol !== \"https:\") ||\n url.username !== \"\" ||\n url.password !== \"\" ||\n url.pathname !== \"/\" ||\n url.search !== \"\" ||\n url.hash !== \"\" ||\n url.origin === \"null\"\n ) {\n return undefined;\n }\n\n return url.origin;\n}\n\nexport interface ManagedHttpUpgradeOptions {\n decisionTimeoutMs: number;\n handler: ManagedHttpUpgradeHandler;\n isOriginAllowed(request: IncomingMessage): HttpUpgradeOriginValidation;\n logger?: AppRouterLogger | undefined;\n shouldBypass?: ((request: IncomingMessage) => boolean) | undefined;\n}\n\nexport interface ManagedHttpUpgradeLifecycle {\n beginClose(): void;\n handle(request: IncomingMessage, socket: Duplex, head: Buffer): void;\n waitForSockets(timeoutMs: number): Promise<void>;\n}\n\nexport function createManagedHttpUpgradeLifecycle(\n options: ManagedHttpUpgradeOptions,\n): ManagedHttpUpgradeLifecycle {\n const sockets = new Set<Duplex>();\n const emptyWaiters = new Set<() => void>();\n const pendingDecisionCancels = new Set<() => void>();\n let closing = false;\n\n function track(socket: Duplex): void {\n sockets.add(socket);\n socket.once(\"close\", () => {\n sockets.delete(socket);\n if (sockets.size === 0) {\n for (const resolve of emptyWaiters) {\n resolve();\n }\n emptyWaiters.clear();\n }\n });\n }\n\n function destroy(socket: Duplex): void {\n if (!socket.destroyed) {\n socket.destroy();\n }\n }\n\n function emitError(request: IncomingMessage, startedAt: number, error: unknown): void {\n emitRouterLog(options.logger, \"error\", {\n durationMs: logDurationMs(startedAt),\n error: logError(error),\n method: request.method ?? \"GET\",\n path: nodeRequestPath(request.url),\n runtime: \"node\",\n type: \"router:upgrade:error\",\n });\n if (options.logger === undefined) {\n try {\n console.error(\"[mreact] HTTP upgrade handler failed:\", error);\n } catch {\n // Failure reporting must never escape the HTTP upgrade listener.\n }\n }\n }\n\n function handle(request: IncomingMessage, socket: Duplex, head: Buffer): void {\n const startedAt = logNow();\n if (closing) {\n destroy(socket);\n return;\n }\n let bypass = false;\n try {\n bypass = options.shouldBypass?.(request) === true;\n } catch (error) {\n emitError(request, startedAt, error);\n destroy(socket);\n return;\n }\n if (bypass) {\n return;\n }\n\n track(socket);\n\n let origin: HttpUpgradeOriginValidation;\n try {\n origin = options.isOriginAllowed(request);\n } catch (error) {\n emitError(request, startedAt, error);\n destroy(socket);\n return;\n }\n if (!origin.ok) {\n emitRouterLog(options.logger, \"warn\", {\n method: request.method ?? \"GET\",\n path: nodeRequestPath(request.url),\n reason: origin.reason,\n runtime: \"node\",\n type: \"router:upgrade:rejected\",\n });\n destroy(socket);\n return;\n }\n\n let disposition: HttpUpgradeDisposition | undefined;\n let decisionTimer: ReturnType<typeof setTimeout> | undefined;\n let failureReported = false;\n let socketClosed = false;\n const clearDecisionTimer = (): void => {\n if (decisionTimer !== undefined) {\n clearTimeout(decisionTimer);\n decisionTimer = undefined;\n }\n pendingDecisionCancels.delete(clearDecisionTimer);\n };\n socket.once(\"close\", () => {\n socketClosed = true;\n clearDecisionTimer();\n });\n const before = {\n bytesWritten: socketBytesWritten(socket),\n destroyed: socket.destroyed,\n writableEnded: socket.writableEnded,\n };\n\n const decide = (next: HttpUpgradeDisposition): HttpUpgradeDisposition => {\n if (disposition !== undefined) {\n return disposition;\n }\n disposition = next;\n clearDecisionTimer();\n if (next === \"declined\") {\n destroy(socket);\n }\n return next;\n };\n const context: HttpUpgradeContext = {\n accept: () => decide(\"handled\"),\n decline: () => decide(\"declined\"),\n };\n\n const fail = (error: unknown): void => {\n if (failureReported) {\n return;\n }\n failureReported = true;\n clearDecisionTimer();\n emitError(request, startedAt, error);\n disposition ??= \"declined\";\n destroy(socket);\n };\n\n let result: unknown;\n try {\n result = (\n options.handler as (\n request: IncomingMessage,\n socket: Duplex,\n head: Buffer,\n context: HttpUpgradeContext,\n ) => unknown\n )(request, socket, head, context);\n } catch (error) {\n fail(error);\n return;\n }\n\n if ((typeof result === \"object\" || typeof result === \"function\") && result !== null) {\n if (disposition === undefined && !closing && !socketClosed) {\n decisionTimer = setTimeout(() => {\n if (disposition === undefined) {\n fail(\n new Error(`HTTP upgrade decision timed out after ${options.decisionTimeoutMs}ms.`),\n );\n }\n }, options.decisionTimeoutMs);\n decisionTimer.unref?.();\n pendingDecisionCancels.add(clearDecisionTimer);\n }\n\n void Promise.resolve(result as PromiseLike<HttpUpgradeDisposition | void>).then(\n (value) => {\n if (socketClosed) {\n return;\n }\n if (value === \"declined\" || value === \"handled\") {\n decide(value);\n } else if (disposition === undefined) {\n decide(legacySocketAction(socket, before) ? \"handled\" : \"declined\");\n }\n },\n (error) => {\n fail(error);\n },\n );\n return;\n }\n\n if (result === \"declined\" || result === \"handled\") {\n decide(result);\n } else if (disposition === undefined) {\n decide(legacySocketAction(socket, before) ? \"handled\" : \"declined\");\n }\n }\n\n return {\n beginClose() {\n if (closing) {\n return;\n }\n closing = true;\n for (const cancel of pendingDecisionCancels) {\n cancel();\n }\n },\n handle,\n async waitForSockets(timeoutMs) {\n if (sockets.size === 0) {\n return;\n }\n\n await new Promise<void>((resolve) => {\n let settled = false;\n const finish = () => {\n if (settled) {\n return;\n }\n settled = true;\n clearTimeout(timer);\n emptyWaiters.delete(finish);\n resolve();\n };\n const timer = setTimeout(() => {\n for (const socket of sockets) {\n destroy(socket);\n }\n finish();\n }, timeoutMs);\n timer.unref?.();\n emptyWaiters.add(finish);\n });\n },\n };\n}\n\nexport function closeServerWithUpgrades(options: {\n lifecycle: ManagedHttpUpgradeLifecycle;\n server: Server;\n timeoutMs: number;\n}): Promise<void> {\n options.lifecycle.beginClose();\n const serverClosed = new Promise<void>((resolve, reject) => {\n options.server.close((error) => (error ? reject(error) : resolve()));\n });\n\n return Promise.all([serverClosed, options.lifecycle.waitForSockets(options.timeoutMs)]).then(\n () => undefined,\n );\n}\n\nfunction legacySocketAction(\n socket: Duplex,\n before: { bytesWritten: number | undefined; destroyed: boolean; writableEnded: boolean },\n): boolean {\n return (\n socketBytesWritten(socket) !== before.bytesWritten ||\n socket.destroyed !== before.destroyed ||\n socket.writableEnded !== before.writableEnded\n );\n}\n\nfunction socketBytesWritten(socket: Duplex): number | undefined {\n return (socket as Duplex & { bytesWritten?: number }).bytesWritten;\n}\n"]}
@@ -1,7 +1,9 @@
1
1
  import { type ConfigEnv, type UserConfig } from "vite";
2
+ import type { DehydrateOptions } from "@reckona/mreact-query";
2
3
  import type { ResolvedAppRouterProject } from "./config.js";
3
4
  import type { AppRouterImportPolicy } from "./import-policy.js";
4
5
  export interface LoadedMreactRouterViteConfig {
6
+ dehydrateOptions?: DehydrateOptions | undefined;
5
7
  importPolicy?: AppRouterImportPolicy | undefined;
6
8
  project: ResolvedAppRouterProject;
7
9
  serverPort?: number | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"vite-config.d.ts","sourceRoot":"","sources":["../src/vite-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,SAAS,EAAqB,KAAK,UAAU,EAAE,MAAM,MAAM,CAAC;AAC9F,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAGhE,MAAM,WAAW,4BAA4B;IAC3C,YAAY,CAAC,EAAE,qBAAqB,GAAG,SAAS,CAAC;IACjD,OAAO,EAAE,wBAAwB,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,UAAU,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CACrC;AAED,wBAAsB,0BAA0B,CAAC,OAAO,EAAE;IACxD,OAAO,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAEpC;AAED,wBAAsB,iCAAiC,CAAC,OAAO,EAAE;IAC/D,OAAO,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAkCxC"}
1
+ {"version":3,"file":"vite-config.d.ts","sourceRoot":"","sources":["../src/vite-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,SAAS,EAAqB,KAAK,UAAU,EAAE,MAAM,MAAM,CAAC;AAC9F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAGhE,MAAM,WAAW,4BAA4B;IAC3C,gBAAgB,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAChD,YAAY,CAAC,EAAE,qBAAqB,GAAG,SAAS,CAAC;IACjD,OAAO,EAAE,wBAAwB,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,UAAU,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CACrC;AAED,wBAAsB,0BAA0B,CAAC,OAAO,EAAE;IACxD,OAAO,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAEpC;AAED,wBAAsB,iCAAiC,CAAC,OAAO,EAAE;IAC/D,OAAO,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAsCxC"}
@@ -17,7 +17,9 @@ export async function loadMreactRouterViteConfigDetails(options) {
17
17
  }
18
18
  const serverPort = loaded.config.server?.port;
19
19
  const importPolicy = config.importPolicy;
20
+ const dehydrateOptions = config.dehydrateOptions;
20
21
  return {
22
+ ...(dehydrateOptions === undefined ? {} : { dehydrateOptions }),
21
23
  ...(importPolicy === undefined ? {} : { importPolicy }),
22
24
  project: config,
23
25
  ...(typeof serverPort === "number" ? { serverPort } : {}),
@@ -1 +1 @@
1
- {"version":3,"file":"vite-config.js","sourceRoot":"","sources":["../src/vite-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAsD,MAAM,MAAM,CAAC;AAG9F,OAAO,EAAE,6BAA6B,EAAE,MAAM,WAAW,CAAC;AAS1D,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAC,OAIhD;IACC,OAAO,CAAC,MAAM,iCAAiC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;AACpE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iCAAiC,CAAC,OAIvD;IACC,MAAM,MAAM,GAAG,MAAM,kBAAkB,CACrC;QACE,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC;KACnF,EACD,SAAS,EACT,OAAO,CAAC,GAAG,CACZ,CAAC;IAEF,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;IAChF,CAAC;IAED,MAAM,MAAM,GAAG,6BAA6B,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IAE1E,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,8EAA8E,CAAC,CAAC;IAClG,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC;IAC9C,MAAM,YAAY,GAAI,MAEpB,CAAC,YAAY,CAAC;IAEhB,OAAO;QACL,GAAG,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC;QACvD,OAAO,EAAE,MAAM;QACf,GAAG,CAAC,OAAO,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,UAAU,EAAE;YACV,GAAG,MAAM,CAAC,MAAM;YAChB,OAAO,EAAE,wBAAwB,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;SAC/D;KACF,CAAC;AACJ,CAAC;AAED,SAAS,wBAAwB,CAAC,OAA2B;IAC3D,OAAO,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,EAA0B,EAAE;QACtE,IAAI,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YAChE,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,6BAA6B,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,SAAS,CAAC;IAC/D,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { loadConfigFromFile, type ConfigEnv, type PluginOption, type UserConfig } from \"vite\";\nimport type { ResolvedAppRouterProject } from \"./config.js\";\nimport type { AppRouterImportPolicy } from \"./import-policy.js\";\nimport { mreactRouterConfigFromPlugins } from \"./vite.js\";\n\nexport interface LoadedMreactRouterViteConfig {\n importPolicy?: AppRouterImportPolicy | undefined;\n project: ResolvedAppRouterProject;\n serverPort?: number | undefined;\n viteConfig?: UserConfig | undefined;\n}\n\nexport async function loadMreactRouterViteConfig(options: {\n command: ConfigEnv[\"command\"];\n cwd: string;\n mode?: string | undefined;\n}): Promise<ResolvedAppRouterProject> {\n return (await loadMreactRouterViteConfigDetails(options)).project;\n}\n\nexport async function loadMreactRouterViteConfigDetails(options: {\n command: ConfigEnv[\"command\"];\n cwd: string;\n mode?: string | undefined;\n}): Promise<LoadedMreactRouterViteConfig> {\n const loaded = await loadConfigFromFile(\n {\n command: options.command,\n mode: options.mode ?? (options.command === \"serve\" ? \"development\" : \"production\"),\n },\n undefined,\n options.cwd,\n );\n\n if (loaded === null) {\n throw new Error(\"vite.config.ts is required for mreact-router CLI commands.\");\n }\n\n const config = mreactRouterConfigFromPlugins(loaded.config.plugins ?? []);\n\n if (config === undefined) {\n throw new Error(\"vite.config.ts must include mreactRouter() from @reckona/mreact-router/vite.\");\n }\n\n const serverPort = loaded.config.server?.port;\n const importPolicy = (config as ResolvedAppRouterProject & {\n importPolicy?: AppRouterImportPolicy | undefined;\n }).importPolicy;\n\n return {\n ...(importPolicy === undefined ? {} : { importPolicy }),\n project: config,\n ...(typeof serverPort === \"number\" ? { serverPort } : {}),\n viteConfig: {\n ...loaded.config,\n plugins: routeAgnosticVitePlugins(loaded.config.plugins ?? []),\n },\n };\n}\n\nfunction routeAgnosticVitePlugins(plugins: readonly unknown[]): PluginOption[] {\n return plugins.flat(Infinity).filter((plugin): plugin is PluginOption => {\n if (plugin === false || plugin === null || plugin === undefined) {\n return false;\n }\n\n return mreactRouterConfigFromPlugins([plugin]) === undefined;\n });\n}\n"]}
1
+ {"version":3,"file":"vite-config.js","sourceRoot":"","sources":["../src/vite-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAsD,MAAM,MAAM,CAAC;AAI9F,OAAO,EAAE,6BAA6B,EAAE,MAAM,WAAW,CAAC;AAU1D,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAC,OAIhD;IACC,OAAO,CAAC,MAAM,iCAAiC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;AACpE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iCAAiC,CAAC,OAIvD;IACC,MAAM,MAAM,GAAG,MAAM,kBAAkB,CACrC;QACE,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC;KACnF,EACD,SAAS,EACT,OAAO,CAAC,GAAG,CACZ,CAAC;IAEF,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;IAChF,CAAC;IAED,MAAM,MAAM,GAAG,6BAA6B,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IAE1E,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,8EAA8E,CAAC,CAAC;IAClG,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC;IAC9C,MAAM,YAAY,GAAI,MAEpB,CAAC,YAAY,CAAC;IAChB,MAAM,gBAAgB,GAAI,MAExB,CAAC,gBAAgB,CAAC;IAEpB,OAAO;QACL,GAAG,CAAC,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,CAAC;QAC/D,GAAG,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC;QACvD,OAAO,EAAE,MAAM;QACf,GAAG,CAAC,OAAO,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,UAAU,EAAE;YACV,GAAG,MAAM,CAAC,MAAM;YAChB,OAAO,EAAE,wBAAwB,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;SAC/D;KACF,CAAC;AACJ,CAAC;AAED,SAAS,wBAAwB,CAAC,OAA2B;IAC3D,OAAO,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,EAA0B,EAAE;QACtE,IAAI,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YAChE,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,6BAA6B,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,SAAS,CAAC;IAC/D,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { loadConfigFromFile, type ConfigEnv, type PluginOption, type UserConfig } from \"vite\";\nimport type { DehydrateOptions } from \"@reckona/mreact-query\";\nimport type { ResolvedAppRouterProject } from \"./config.js\";\nimport type { AppRouterImportPolicy } from \"./import-policy.js\";\nimport { mreactRouterConfigFromPlugins } from \"./vite.js\";\n\nexport interface LoadedMreactRouterViteConfig {\n dehydrateOptions?: DehydrateOptions | undefined;\n importPolicy?: AppRouterImportPolicy | undefined;\n project: ResolvedAppRouterProject;\n serverPort?: number | undefined;\n viteConfig?: UserConfig | undefined;\n}\n\nexport async function loadMreactRouterViteConfig(options: {\n command: ConfigEnv[\"command\"];\n cwd: string;\n mode?: string | undefined;\n}): Promise<ResolvedAppRouterProject> {\n return (await loadMreactRouterViteConfigDetails(options)).project;\n}\n\nexport async function loadMreactRouterViteConfigDetails(options: {\n command: ConfigEnv[\"command\"];\n cwd: string;\n mode?: string | undefined;\n}): Promise<LoadedMreactRouterViteConfig> {\n const loaded = await loadConfigFromFile(\n {\n command: options.command,\n mode: options.mode ?? (options.command === \"serve\" ? \"development\" : \"production\"),\n },\n undefined,\n options.cwd,\n );\n\n if (loaded === null) {\n throw new Error(\"vite.config.ts is required for mreact-router CLI commands.\");\n }\n\n const config = mreactRouterConfigFromPlugins(loaded.config.plugins ?? []);\n\n if (config === undefined) {\n throw new Error(\"vite.config.ts must include mreactRouter() from @reckona/mreact-router/vite.\");\n }\n\n const serverPort = loaded.config.server?.port;\n const importPolicy = (config as ResolvedAppRouterProject & {\n importPolicy?: AppRouterImportPolicy | undefined;\n }).importPolicy;\n const dehydrateOptions = (config as ResolvedAppRouterProject & {\n dehydrateOptions?: DehydrateOptions | undefined;\n }).dehydrateOptions;\n\n return {\n ...(dehydrateOptions === undefined ? {} : { dehydrateOptions }),\n ...(importPolicy === undefined ? {} : { importPolicy }),\n project: config,\n ...(typeof serverPort === \"number\" ? { serverPort } : {}),\n viteConfig: {\n ...loaded.config,\n plugins: routeAgnosticVitePlugins(loaded.config.plugins ?? []),\n },\n };\n}\n\nfunction routeAgnosticVitePlugins(plugins: readonly unknown[]): PluginOption[] {\n return plugins.flat(Infinity).filter((plugin): plugin is PluginOption => {\n if (plugin === false || plugin === null || plugin === undefined) {\n return false;\n }\n\n return mreactRouterConfigFromPlugins([plugin]) === undefined;\n });\n}\n"]}
package/dist/vite.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { DehydrateOptions } from "@reckona/mreact-query";
1
2
  import { type Connect, type Plugin, type PluginOption, type UserConfig } from "vite";
2
3
  import type { AppRouterServerActionOptions } from "./actions.js";
3
4
  import type { AppRouterCache } from "./cache.js";
@@ -9,13 +10,14 @@ export type { AppRouterAllowedServerAction, AppRouterServerActionOptions } from
9
10
  export type { AppRouterCache, AppRouterCacheEntry } from "./cache.js";
10
11
  export type { AppRouterBuildTarget, AppRouterClientConsoleMethod, AppRouterClientSourceMapMode, AppRouterClientSourceMapOption, AppRouterProductionOptions, AppRouterProjectOptions, ResolvedAppRouterProject, } from "./config.js";
11
12
  export type { AppRouterImportPolicy } from "./import-policy.js";
12
- export type { AppRouterCspInlineNonceWarningLogEvent, AppRouterLogError, AppRouterLogEvent, AppRouterLogger, AppRouterRuntime, AppRouterRenderTimingLogEvent, AppRouterRequestEndLogEvent, AppRouterRequestErrorLogEvent, AppRouterRequestStartLogEvent, AppRouterRequestTimingLogEvent, } from "./logger.js";
13
+ export type { AppRouterCspInlineNonceWarningLogEvent, AppRouterLogError, AppRouterLogEvent, AppRouterLogger, AppRouterRuntime, AppRouterRenderTimingLogEvent, AppRouterRequestEndLogEvent, AppRouterRequestErrorLogEvent, AppRouterRequestStartLogEvent, AppRouterRequestTimingLogEvent, AppRouterUpgradeErrorLogEvent, AppRouterUpgradeRejectedLogEvent, } from "./logger.js";
13
14
  export type { RequestHostPolicy } from "./serve.js";
14
15
  /**
15
16
  * Configures the app-router Vite middleware used by development servers.
16
17
  */
17
18
  export interface AppRouterViteMiddlewareOptions extends AppRouterProjectOptions {
18
19
  allowedHosts?: readonly string[] | undefined;
20
+ dehydrateOptions?: DehydrateOptions | undefined;
19
21
  define?: UserConfig["define"] | undefined;
20
22
  hostPolicy?: RequestHostPolicy | undefined;
21
23
  importPolicy?: AppRouterImportPolicy | undefined;
@@ -29,6 +31,7 @@ export interface AppRouterViteMiddlewareOptions extends AppRouterProjectOptions
29
31
  */
30
32
  export interface AppRouterVitePluginOptions extends AppRouterProjectOptions {
31
33
  allowedHosts?: readonly string[] | undefined;
34
+ dehydrateOptions?: DehydrateOptions | undefined;
32
35
  hostPolicy?: RequestHostPolicy | undefined;
33
36
  importPolicy?: AppRouterImportPolicy | undefined;
34
37
  logger?: AppRouterLogger | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"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"}