typeferry 0.6.0

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 (392) hide show
  1. package/README.md +88 -0
  2. package/dist/auth/client/cross-tab-sync.d.ts +21 -0
  3. package/dist/auth/client/cross-tab-sync.js +56 -0
  4. package/dist/auth/client/cross-tab-sync.js.map +1 -0
  5. package/dist/auth/client/index.d.ts +2 -0
  6. package/dist/auth/client/index.js +3 -0
  7. package/dist/auth/client/index.js.map +1 -0
  8. package/dist/auth/client/oauth/google-provider.d.ts +11 -0
  9. package/dist/auth/client/oauth/google-provider.js +11 -0
  10. package/dist/auth/client/oauth/google-provider.js.map +1 -0
  11. package/dist/auth/client/oauth/index.d.ts +4 -0
  12. package/dist/auth/client/oauth/index.js +3 -0
  13. package/dist/auth/client/oauth/index.js.map +1 -0
  14. package/dist/auth/client/oauth/use-google-login.d.ts +39 -0
  15. package/dist/auth/client/oauth/use-google-login.js +55 -0
  16. package/dist/auth/client/oauth/use-google-login.js.map +1 -0
  17. package/dist/auth/client/token-refresh.d.ts +21 -0
  18. package/dist/auth/client/token-refresh.js +212 -0
  19. package/dist/auth/client/token-refresh.js.map +1 -0
  20. package/dist/auth/index.d.ts +7 -0
  21. package/dist/auth/index.js +9 -0
  22. package/dist/auth/index.js.map +1 -0
  23. package/dist/auth/server/cookie-utils.d.ts +42 -0
  24. package/dist/auth/server/cookie-utils.js +91 -0
  25. package/dist/auth/server/cookie-utils.js.map +1 -0
  26. package/dist/auth/server/device-info.d.ts +23 -0
  27. package/dist/auth/server/device-info.js +52 -0
  28. package/dist/auth/server/device-info.js.map +1 -0
  29. package/dist/auth/server/index.d.ts +4 -0
  30. package/dist/auth/server/index.js +5 -0
  31. package/dist/auth/server/index.js.map +1 -0
  32. package/dist/auth/server/jwt-utils.d.ts +29 -0
  33. package/dist/auth/server/jwt-utils.js +53 -0
  34. package/dist/auth/server/jwt-utils.js.map +1 -0
  35. package/dist/auth/server/oauth/google.d.ts +31 -0
  36. package/dist/auth/server/oauth/google.js +40 -0
  37. package/dist/auth/server/oauth/google.js.map +1 -0
  38. package/dist/auth/server/oauth/index.d.ts +3 -0
  39. package/dist/auth/server/oauth/index.js +2 -0
  40. package/dist/auth/server/oauth/index.js.map +1 -0
  41. package/dist/auth/server/oauth/types.d.ts +37 -0
  42. package/dist/auth/server/oauth/types.js +2 -0
  43. package/dist/auth/server/oauth/types.js.map +1 -0
  44. package/dist/auth/server/session-manager.d.ts +46 -0
  45. package/dist/auth/server/session-manager.js +167 -0
  46. package/dist/auth/server/session-manager.js.map +1 -0
  47. package/dist/auth/types.d.ts +197 -0
  48. package/dist/auth/types.js +2 -0
  49. package/dist/auth/types.js.map +1 -0
  50. package/dist/client/call-method-proxy.d.ts +2 -0
  51. package/dist/client/call-method-proxy.js +22 -0
  52. package/dist/client/call-method-proxy.js.map +1 -0
  53. package/dist/client/client-channel.d.ts +43 -0
  54. package/dist/client/client-channel.js +148 -0
  55. package/dist/client/client-channel.js.map +1 -0
  56. package/dist/client/client-http.d.ts +27 -0
  57. package/dist/client/client-http.js +106 -0
  58. package/dist/client/client-http.js.map +1 -0
  59. package/dist/client/client-socket.d.ts +85 -0
  60. package/dist/client/client-socket.js +317 -0
  61. package/dist/client/client-socket.js.map +1 -0
  62. package/dist/client/client.d.ts +149 -0
  63. package/dist/client/client.js +401 -0
  64. package/dist/client/client.js.map +1 -0
  65. package/dist/client/context-manager.d.ts +54 -0
  66. package/dist/client/context-manager.js +89 -0
  67. package/dist/client/context-manager.js.map +1 -0
  68. package/dist/client/idle-timer.d.ts +35 -0
  69. package/dist/client/idle-timer.js +101 -0
  70. package/dist/client/idle-timer.js.map +1 -0
  71. package/dist/client/index.d.ts +6 -0
  72. package/dist/client/index.js +7 -0
  73. package/dist/client/index.js.map +1 -0
  74. package/dist/client/logger.d.ts +76 -0
  75. package/dist/client/logger.js +129 -0
  76. package/dist/client/logger.js.map +1 -0
  77. package/dist/client/visibility-manager.d.ts +62 -0
  78. package/dist/client/visibility-manager.js +177 -0
  79. package/dist/client/visibility-manager.js.map +1 -0
  80. package/dist/ejson/adjust-types-from-json-value.d.ts +1 -0
  81. package/dist/ejson/adjust-types-from-json-value.js +35 -0
  82. package/dist/ejson/adjust-types-from-json-value.js.map +1 -0
  83. package/dist/ejson/base64.d.ts +11 -0
  84. package/dist/ejson/base64.js +87 -0
  85. package/dist/ejson/base64.js.map +1 -0
  86. package/dist/ejson/built-in-converters.d.ts +1 -0
  87. package/dist/ejson/built-in-converters.js +137 -0
  88. package/dist/ejson/built-in-converters.js.map +1 -0
  89. package/dist/ejson/clone.d.ts +1 -0
  90. package/dist/ejson/clone.js +80 -0
  91. package/dist/ejson/clone.js.map +1 -0
  92. package/dist/ejson/custom-models.d.ts +38 -0
  93. package/dist/ejson/custom-models.js +76 -0
  94. package/dist/ejson/custom-models.js.map +1 -0
  95. package/dist/ejson/custom-types.d.ts +1 -0
  96. package/dist/ejson/custom-types.js +2 -0
  97. package/dist/ejson/custom-types.js.map +1 -0
  98. package/dist/ejson/equals.d.ts +1 -0
  99. package/dist/ejson/equals.js +117 -0
  100. package/dist/ejson/equals.js.map +1 -0
  101. package/dist/ejson/from-json-value.d.ts +1 -0
  102. package/dist/ejson/from-json-value.js +13 -0
  103. package/dist/ejson/from-json-value.js.map +1 -0
  104. package/dist/ejson/helpers/adjust-types-to-json-value.d.ts +1 -0
  105. package/dist/ejson/helpers/adjust-types-to-json-value.js +36 -0
  106. package/dist/ejson/helpers/adjust-types-to-json-value.js.map +1 -0
  107. package/dist/ejson/helpers/from-json-value-helper.d.ts +1 -0
  108. package/dist/ejson/helpers/from-json-value-helper.js +24 -0
  109. package/dist/ejson/helpers/from-json-value-helper.js.map +1 -0
  110. package/dist/ejson/helpers/to-json-value-helper.d.ts +1 -0
  111. package/dist/ejson/helpers/to-json-value-helper.js +15 -0
  112. package/dist/ejson/helpers/to-json-value-helper.js.map +1 -0
  113. package/dist/ejson/index.d.ts +27 -0
  114. package/dist/ejson/index.js +54 -0
  115. package/dist/ejson/index.js.map +1 -0
  116. package/dist/ejson/is-binary.d.ts +2 -0
  117. package/dist/ejson/is-binary.js +5 -0
  118. package/dist/ejson/is-binary.js.map +1 -0
  119. package/dist/ejson/parse.d.ts +6 -0
  120. package/dist/ejson/parse.js +12 -0
  121. package/dist/ejson/parse.js.map +1 -0
  122. package/dist/ejson/stable-stringify.d.ts +10 -0
  123. package/dist/ejson/stable-stringify.js +25 -0
  124. package/dist/ejson/stable-stringify.js.map +1 -0
  125. package/dist/ejson/stringify.d.ts +5 -0
  126. package/dist/ejson/stringify.js +15 -0
  127. package/dist/ejson/stringify.js.map +1 -0
  128. package/dist/ejson/to-json-value.d.ts +1 -0
  129. package/dist/ejson/to-json-value.js +17 -0
  130. package/dist/ejson/to-json-value.js.map +1 -0
  131. package/dist/ejson/utils.d.ts +18 -0
  132. package/dist/ejson/utils.js +43 -0
  133. package/dist/ejson/utils.js.map +1 -0
  134. package/dist/mongodb/change-streams.d.ts +31 -0
  135. package/dist/mongodb/change-streams.js +142 -0
  136. package/dist/mongodb/change-streams.js.map +1 -0
  137. package/dist/mongodb/client.d.ts +13 -0
  138. package/dist/mongodb/client.js +30 -0
  139. package/dist/mongodb/client.js.map +1 -0
  140. package/dist/mongodb/decorators/collection.d.ts +9 -0
  141. package/dist/mongodb/decorators/collection.js +26 -0
  142. package/dist/mongodb/decorators/collection.js.map +1 -0
  143. package/dist/mongodb/decorators/index.d.ts +4 -0
  144. package/dist/mongodb/decorators/index.js +5 -0
  145. package/dist/mongodb/decorators/index.js.map +1 -0
  146. package/dist/mongodb/decorators/metadata.d.ts +21 -0
  147. package/dist/mongodb/decorators/metadata.js +29 -0
  148. package/dist/mongodb/decorators/metadata.js.map +1 -0
  149. package/dist/mongodb/decorators/register.d.ts +3 -0
  150. package/dist/mongodb/decorators/register.js +10 -0
  151. package/dist/mongodb/decorators/register.js.map +1 -0
  152. package/dist/mongodb/decorators/watch.d.ts +4 -0
  153. package/dist/mongodb/decorators/watch.js +10 -0
  154. package/dist/mongodb/decorators/watch.js.map +1 -0
  155. package/dist/mongodb/filters.d.ts +20 -0
  156. package/dist/mongodb/filters.js +40 -0
  157. package/dist/mongodb/filters.js.map +1 -0
  158. package/dist/mongodb/find-one-or-create.d.ts +4 -0
  159. package/dist/mongodb/find-one-or-create.js +16 -0
  160. package/dist/mongodb/find-one-or-create.js.map +1 -0
  161. package/dist/mongodb/index.d.ts +10 -0
  162. package/dist/mongodb/index.js +11 -0
  163. package/dist/mongodb/index.js.map +1 -0
  164. package/dist/mongodb/live/client.d.ts +52 -0
  165. package/dist/mongodb/live/client.js +266 -0
  166. package/dist/mongodb/live/client.js.map +1 -0
  167. package/dist/mongodb/live/engine.d.ts +55 -0
  168. package/dist/mongodb/live/engine.js +440 -0
  169. package/dist/mongodb/live/engine.js.map +1 -0
  170. package/dist/mongodb/live/index.d.ts +5 -0
  171. package/dist/mongodb/live/index.js +6 -0
  172. package/dist/mongodb/live/index.js.map +1 -0
  173. package/dist/mongodb/live/observer.d.ts +58 -0
  174. package/dist/mongodb/live/observer.js +246 -0
  175. package/dist/mongodb/live/observer.js.map +1 -0
  176. package/dist/mongodb/live/publication.d.ts +4 -0
  177. package/dist/mongodb/live/publication.js +30 -0
  178. package/dist/mongodb/live/publication.js.map +1 -0
  179. package/dist/mongodb/live/source.d.ts +55 -0
  180. package/dist/mongodb/live/source.js +197 -0
  181. package/dist/mongodb/live/source.js.map +1 -0
  182. package/dist/mongodb/live/types.d.ts +266 -0
  183. package/dist/mongodb/live/types.js +29 -0
  184. package/dist/mongodb/live/types.js.map +1 -0
  185. package/dist/mongodb/live/window.d.ts +7 -0
  186. package/dist/mongodb/live/window.js +93 -0
  187. package/dist/mongodb/live/window.js.map +1 -0
  188. package/dist/mongodb/registry.d.ts +35 -0
  189. package/dist/mongodb/registry.js +129 -0
  190. package/dist/mongodb/registry.js.map +1 -0
  191. package/dist/mongodb/schema.d.ts +16 -0
  192. package/dist/mongodb/schema.js +43 -0
  193. package/dist/mongodb/schema.js.map +1 -0
  194. package/dist/mongodb/timestamps.d.ts +17 -0
  195. package/dist/mongodb/timestamps.js +27 -0
  196. package/dist/mongodb/timestamps.js.map +1 -0
  197. package/dist/mongodb/types.d.ts +120 -0
  198. package/dist/mongodb/types.js +10 -0
  199. package/dist/mongodb/types.js.map +1 -0
  200. package/dist/react/components/client-provider.d.ts +8 -0
  201. package/dist/react/components/client-provider.js +23 -0
  202. package/dist/react/components/client-provider.js.map +1 -0
  203. package/dist/react/components/index.d.ts +1 -0
  204. package/dist/react/components/index.js +2 -0
  205. package/dist/react/components/index.js.map +1 -0
  206. package/dist/react/hooks/index.d.ts +13 -0
  207. package/dist/react/hooks/index.js +14 -0
  208. package/dist/react/hooks/index.js.map +1 -0
  209. package/dist/react/hooks/use-auth.d.ts +4 -0
  210. package/dist/react/hooks/use-auth.js +35 -0
  211. package/dist/react/hooks/use-auth.js.map +1 -0
  212. package/dist/react/hooks/use-caller.d.ts +5 -0
  213. package/dist/react/hooks/use-caller.js +13 -0
  214. package/dist/react/hooks/use-caller.js.map +1 -0
  215. package/dist/react/hooks/use-channel.d.ts +1 -0
  216. package/dist/react/hooks/use-channel.js +7 -0
  217. package/dist/react/hooks/use-channel.js.map +1 -0
  218. package/dist/react/hooks/use-circuit-breaker.d.ts +6 -0
  219. package/dist/react/hooks/use-circuit-breaker.js +16 -0
  220. package/dist/react/hooks/use-circuit-breaker.js.map +1 -0
  221. package/dist/react/hooks/use-client.d.ts +3 -0
  222. package/dist/react/hooks/use-client.js +13 -0
  223. package/dist/react/hooks/use-client.js.map +1 -0
  224. package/dist/react/hooks/use-connection-state.d.ts +13 -0
  225. package/dist/react/hooks/use-connection-state.js +55 -0
  226. package/dist/react/hooks/use-connection-state.js.map +1 -0
  227. package/dist/react/hooks/use-creation.d.ts +5 -0
  228. package/dist/react/hooks/use-creation.js +17 -0
  229. package/dist/react/hooks/use-creation.js.map +1 -0
  230. package/dist/react/hooks/use-deps-change.d.ts +1 -0
  231. package/dist/react/hooks/use-deps-change.js +11 -0
  232. package/dist/react/hooks/use-deps-change.js.map +1 -0
  233. package/dist/react/hooks/use-local-event.d.ts +13 -0
  234. package/dist/react/hooks/use-local-event.js +32 -0
  235. package/dist/react/hooks/use-local-event.js.map +1 -0
  236. package/dist/react/hooks/use-method-refresh.d.ts +15 -0
  237. package/dist/react/hooks/use-method-refresh.js +48 -0
  238. package/dist/react/hooks/use-method-refresh.js.map +1 -0
  239. package/dist/react/hooks/use-method.d.ts +26 -0
  240. package/dist/react/hooks/use-method.js +161 -0
  241. package/dist/react/hooks/use-method.js.map +1 -0
  242. package/dist/react/hooks/use-mongodb-live-publication.d.ts +13 -0
  243. package/dist/react/hooks/use-mongodb-live-publication.js +26 -0
  244. package/dist/react/hooks/use-mongodb-live-publication.js.map +1 -0
  245. package/dist/react/hooks/use-object.d.ts +2 -0
  246. package/dist/react/hooks/use-object.js +22 -0
  247. package/dist/react/hooks/use-object.js.map +1 -0
  248. package/dist/react/hooks/use-subscribe.d.ts +8 -0
  249. package/dist/react/hooks/use-subscribe.js +49 -0
  250. package/dist/react/hooks/use-subscribe.js.map +1 -0
  251. package/dist/react/hooks/use-throttled-events.d.ts +7 -0
  252. package/dist/react/hooks/use-throttled-events.js +11 -0
  253. package/dist/react/hooks/use-throttled-events.js.map +1 -0
  254. package/dist/react/hooks/use-token-refresh.d.ts +13 -0
  255. package/dist/react/hooks/use-token-refresh.js +40 -0
  256. package/dist/react/hooks/use-token-refresh.js.map +1 -0
  257. package/dist/react/index.d.ts +2 -0
  258. package/dist/react/index.js +3 -0
  259. package/dist/react/index.js.map +1 -0
  260. package/dist/server/client-node.d.ts +76 -0
  261. package/dist/server/client-node.js +159 -0
  262. package/dist/server/client-node.js.map +1 -0
  263. package/dist/server/create-method-proxy.d.ts +2 -0
  264. package/dist/server/create-method-proxy.js +16 -0
  265. package/dist/server/create-method-proxy.js.map +1 -0
  266. package/dist/server/decorators/cached.d.ts +37 -0
  267. package/dist/server/decorators/cached.js +65 -0
  268. package/dist/server/decorators/cached.js.map +1 -0
  269. package/dist/server/decorators/index.d.ts +14 -0
  270. package/dist/server/decorators/index.js +13 -0
  271. package/dist/server/decorators/index.js.map +1 -0
  272. package/dist/server/decorators/infer.d.ts +78 -0
  273. package/dist/server/decorators/infer.js +11 -0
  274. package/dist/server/decorators/infer.js.map +1 -0
  275. package/dist/server/decorators/metadata.d.ts +60 -0
  276. package/dist/server/decorators/metadata.js +77 -0
  277. package/dist/server/decorators/metadata.js.map +1 -0
  278. package/dist/server/decorators/method.d.ts +14 -0
  279. package/dist/server/decorators/method.js +25 -0
  280. package/dist/server/decorators/method.js.map +1 -0
  281. package/dist/server/decorators/namespace.d.ts +25 -0
  282. package/dist/server/decorators/namespace.js +34 -0
  283. package/dist/server/decorators/namespace.js.map +1 -0
  284. package/dist/server/decorators/protected.d.ts +36 -0
  285. package/dist/server/decorators/protected.js +61 -0
  286. package/dist/server/decorators/protected.js.map +1 -0
  287. package/dist/server/decorators/register.d.ts +25 -0
  288. package/dist/server/decorators/register.js +72 -0
  289. package/dist/server/decorators/register.js.map +1 -0
  290. package/dist/server/decorators/schema.d.ts +17 -0
  291. package/dist/server/decorators/schema.js +27 -0
  292. package/dist/server/decorators/schema.js.map +1 -0
  293. package/dist/server/decorators/use.d.ts +22 -0
  294. package/dist/server/decorators/use.js +32 -0
  295. package/dist/server/decorators/use.js.map +1 -0
  296. package/dist/server/default-methods.d.ts +8 -0
  297. package/dist/server/default-methods.js +8 -0
  298. package/dist/server/default-methods.js.map +1 -0
  299. package/dist/server/event.d.ts +42 -0
  300. package/dist/server/event.js +53 -0
  301. package/dist/server/event.js.map +1 -0
  302. package/dist/server/index.d.ts +10 -0
  303. package/dist/server/index.js +11 -0
  304. package/dist/server/index.js.map +1 -0
  305. package/dist/server/method.d.ts +95 -0
  306. package/dist/server/method.js +113 -0
  307. package/dist/server/method.js.map +1 -0
  308. package/dist/server/methods.d.ts +11 -0
  309. package/dist/server/methods.js +74 -0
  310. package/dist/server/methods.js.map +1 -0
  311. package/dist/server/request-types.d.ts +20 -0
  312. package/dist/server/request-types.js +8 -0
  313. package/dist/server/request-types.js.map +1 -0
  314. package/dist/server/room-registry.d.ts +28 -0
  315. package/dist/server/room-registry.js +83 -0
  316. package/dist/server/room-registry.js.map +1 -0
  317. package/dist/server/server-channel.d.ts +32 -0
  318. package/dist/server/server-channel.js +104 -0
  319. package/dist/server/server-channel.js.map +1 -0
  320. package/dist/server/server.d.ts +124 -0
  321. package/dist/server/server.js +243 -0
  322. package/dist/server/server.js.map +1 -0
  323. package/dist/server/transports/hono-rate-limit.d.ts +15 -0
  324. package/dist/server/transports/hono-rate-limit.js +36 -0
  325. package/dist/server/transports/hono-rate-limit.js.map +1 -0
  326. package/dist/server/transports/index.d.ts +4 -0
  327. package/dist/server/transports/index.js +5 -0
  328. package/dist/server/transports/index.js.map +1 -0
  329. package/dist/server/transports/node-hono-transport-contract.d.ts +16 -0
  330. package/dist/server/transports/node-hono-transport-contract.js +18 -0
  331. package/dist/server/transports/node-hono-transport-contract.js.map +1 -0
  332. package/dist/server/transports/node-hono-transport.d.ts +47 -0
  333. package/dist/server/transports/node-hono-transport.js +327 -0
  334. package/dist/server/transports/node-hono-transport.js.map +1 -0
  335. package/dist/server/transports/redis-transport.d.ts +34 -0
  336. package/dist/server/transports/redis-transport.js +84 -0
  337. package/dist/server/transports/redis-transport.js.map +1 -0
  338. package/dist/server/transports/websocket-transport.d.ts +42 -0
  339. package/dist/server/transports/websocket-transport.js +174 -0
  340. package/dist/server/transports/websocket-transport.js.map +1 -0
  341. package/dist/server/transports/ws-shared.d.ts +37 -0
  342. package/dist/server/transports/ws-shared.js +188 -0
  343. package/dist/server/transports/ws-shared.js.map +1 -0
  344. package/dist/server/typeferry-async-local-storage.d.ts +5 -0
  345. package/dist/server/typeferry-async-local-storage.js +6 -0
  346. package/dist/server/typeferry-async-local-storage.js.map +1 -0
  347. package/dist/server/types.d.ts +27 -0
  348. package/dist/server/types.js +11 -0
  349. package/dist/server/types.js.map +1 -0
  350. package/dist/utils/constants.d.ts +72 -0
  351. package/dist/utils/constants.js +79 -0
  352. package/dist/utils/constants.js.map +1 -0
  353. package/dist/utils/environment.d.ts +8 -0
  354. package/dist/utils/environment.js +17 -0
  355. package/dist/utils/environment.js.map +1 -0
  356. package/dist/utils/errors.d.ts +26 -0
  357. package/dist/utils/errors.js +35 -0
  358. package/dist/utils/errors.js.map +1 -0
  359. package/dist/utils/event-emitter.d.ts +37 -0
  360. package/dist/utils/event-emitter.js +104 -0
  361. package/dist/utils/event-emitter.js.map +1 -0
  362. package/dist/utils/events.d.ts +7 -0
  363. package/dist/utils/events.js +23 -0
  364. package/dist/utils/events.js.map +1 -0
  365. package/dist/utils/helpers.d.ts +14 -0
  366. package/dist/utils/helpers.js +40 -0
  367. package/dist/utils/helpers.js.map +1 -0
  368. package/dist/utils/index.d.ts +11 -0
  369. package/dist/utils/index.js +12 -0
  370. package/dist/utils/index.js.map +1 -0
  371. package/dist/utils/intercept.d.ts +7 -0
  372. package/dist/utils/intercept.js +21 -0
  373. package/dist/utils/intercept.js.map +1 -0
  374. package/dist/utils/iterator.d.ts +9 -0
  375. package/dist/utils/iterator.js +28 -0
  376. package/dist/utils/iterator.js.map +1 -0
  377. package/dist/utils/lodash.d.ts +33 -0
  378. package/dist/utils/lodash.js +123 -0
  379. package/dist/utils/lodash.js.map +1 -0
  380. package/dist/utils/presentation.d.ts +19 -0
  381. package/dist/utils/presentation.js +25 -0
  382. package/dist/utils/presentation.js.map +1 -0
  383. package/dist/utils/promise.d.ts +6 -0
  384. package/dist/utils/promise.js +17 -0
  385. package/dist/utils/promise.js.map +1 -0
  386. package/dist/utils/protocol.d.ts +110 -0
  387. package/dist/utils/protocol.js +59 -0
  388. package/dist/utils/protocol.js.map +1 -0
  389. package/dist/utils/types.d.ts +23 -0
  390. package/dist/utils/types.js +2 -0
  391. package/dist/utils/types.js.map +1 -0
  392. package/package.json +187 -0
package/README.md ADDED
@@ -0,0 +1,88 @@
1
+ # typeferry
2
+
3
+ The TypeScript implementation of TypeFerry provides the reference Node.js server, browser/Node client, React hooks, authentication helpers, EJSON, and an optional MongoDB extension.
4
+
5
+ Install the public TypeScript package with `npm install typeferry`. Repository contributors can use the local [`template/`](../template/) workflow described in the [quickstart](../docs/getting-started.md).
6
+
7
+ ## Runtime requirements
8
+
9
+ - Node.js `24.19.0`
10
+ - npm `11.17.0`
11
+ - Node.js for the server runtime
12
+ - A browser or WebSocket-capable JavaScript runtime for clients
13
+
14
+ ## Public entry points
15
+
16
+ | Import | Purpose |
17
+ |---|---|
18
+ | `typeferry/server` | Server, methods, events, channels, and runtime types |
19
+ | `typeferry/server/decorators` | Namespace and method decorators |
20
+ | `typeferry/server/transports` | Node HTTP, WebSocket, and Redis transports |
21
+ | `typeferry/client` | Core client and connection APIs |
22
+ | `typeferry/react` | React provider and hooks |
23
+ | `typeferry/auth` | Shared auth, token, session, and cookie helpers |
24
+ | `typeferry/auth/server/oauth` | Server OAuth providers |
25
+ | `typeferry/auth/client/oauth` | Client OAuth helpers |
26
+ | `typeferry/ejson` | Extended JSON namespace |
27
+ | `typeferry/mongodb` | Native-driver MongoDB extension |
28
+ | `typeferry/mongodb/decorators` | MongoDB collection decorators |
29
+
30
+ Applications should import these compiled package exports. Do not alias or import TypeFerry source files from application code.
31
+
32
+ ## Define and serve a typed method
33
+
34
+ ```ts
35
+ import { Server } from 'typeferry/server'
36
+ import type { ClientNode } from 'typeferry/server'
37
+ import {
38
+ type InferNamespace,
39
+ Method,
40
+ Namespace,
41
+ registerNamespace,
42
+ Schema,
43
+ } from 'typeferry/server/decorators'
44
+ import { z } from 'zod'
45
+
46
+ const greetingSchema = z.object({
47
+ name: z.string().trim().min(1),
48
+ })
49
+
50
+ type GreetingInput = z.infer<typeof greetingSchema>
51
+
52
+ @Namespace('greeting')
53
+ export class GreetingMethods {
54
+ @Method()
55
+ @Schema(greetingSchema)
56
+ async hello(
57
+ _client: ClientNode,
58
+ input: GreetingInput,
59
+ ): Promise<string> {
60
+ return `Hello, ${input.name}!`
61
+ }
62
+ }
63
+
64
+ export type GreetingApi = InferNamespace<GreetingMethods, 'greeting'>
65
+
66
+ const server = new Server({ host: '127.0.0.1', port: 8002 })
67
+ registerNamespace(GreetingMethods)
68
+ await server.isReady()
69
+ ```
70
+
71
+ Clients can call the method as `client.m.greeting.hello({ name: 'Ada' })` when parameterized with `GreetingApi`. The decorators turn the class method into an HTTP and WebSocket RPC endpoint, while `@Schema()` validates network input at runtime. The `Server` constructor installs both transports; call `server.close()` during graceful shutdown.
72
+
73
+ ## Development
74
+
75
+ Run commands from `typeferry-ts/`:
76
+
77
+ ```sh
78
+ npm ci
79
+ npm run lint
80
+ npm run typecheck
81
+ npm test
82
+ npm run build
83
+ npm pack --dry-run
84
+ ```
85
+
86
+ ## Guides
87
+
88
+ Start at the [documentation home](../docs/README.md) or jump to [server and RPC](../docs/typescript/server-rpc.md), [client](../docs/typescript/client.md), [React](../docs/typescript/react.md), [authentication](../docs/typescript/authentication.md), [events and channels](../docs/typescript/events-and-channels.md), [MongoDB](../docs/typescript/mongodb.md), [EJSON](../docs/typescript/ejson.md), or [deployment](../docs/typescript/deployment.md).
@@ -0,0 +1,21 @@
1
+ import type { Client } from '../../client/index.js';
2
+ import type { CrossTabSyncConfig } from '../types.js';
3
+ /**
4
+ * Set up cross-tab token synchronization using BroadcastChannel.
5
+ * When one tab refreshes the token, all other tabs receive the update.
6
+ *
7
+ * @param client - TypeFerry client instance
8
+ * @param config - Sync configuration
9
+ * @returns Cleanup function
10
+ */
11
+ export declare function setupCrossTabSync(client: Client, config: CrossTabSyncConfig): () => void;
12
+ /**
13
+ * Broadcast a token refresh to all other tabs.
14
+ * Call this after successfully refreshing the token.
15
+ *
16
+ * @param channelName - BroadcastChannel name
17
+ * @param token - New access token
18
+ * @param exp - Token expiration (Unix timestamp in seconds)
19
+ * @param iat - Token issued-at time (Unix timestamp in seconds) for clock-skew compensation
20
+ */
21
+ export declare function broadcastTokenRefresh(channelName: string, token: string, exp: number, iat?: number): void;
@@ -0,0 +1,56 @@
1
+ const TOKEN_REFRESHED = 'TOKEN_REFRESHED';
2
+ /**
3
+ * Set up cross-tab token synchronization using BroadcastChannel.
4
+ * When one tab refreshes the token, all other tabs receive the update.
5
+ *
6
+ * @param client - TypeFerry client instance
7
+ * @param config - Sync configuration
8
+ * @returns Cleanup function
9
+ */
10
+ export function setupCrossTabSync(client, config) {
11
+ // BroadcastChannel not available in SSR or older browsers
12
+ if (typeof BroadcastChannel === 'undefined') {
13
+ return () => { };
14
+ }
15
+ const channel = new BroadcastChannel(config.channelName);
16
+ const handleMessage = (event) => {
17
+ // Validate message structure before trusting data from other tabs
18
+ if (event.data?.type === TOKEN_REFRESHED &&
19
+ typeof event.data.token === 'string' &&
20
+ typeof event.data.exp === 'number') {
21
+ const { token, exp, iat } = event.data;
22
+ const context = { token, exp };
23
+ if (typeof iat === 'number') {
24
+ context.iat = iat;
25
+ context._tokenReceivedAt = Date.now();
26
+ }
27
+ client.updateContext(context);
28
+ if (config.tokenRefreshedEvent) {
29
+ client.emit(config.tokenRefreshedEvent, { token, exp });
30
+ }
31
+ }
32
+ };
33
+ channel.addEventListener('message', handleMessage);
34
+ return () => {
35
+ channel.removeEventListener('message', handleMessage);
36
+ channel.close();
37
+ };
38
+ }
39
+ /**
40
+ * Broadcast a token refresh to all other tabs.
41
+ * Call this after successfully refreshing the token.
42
+ *
43
+ * @param channelName - BroadcastChannel name
44
+ * @param token - New access token
45
+ * @param exp - Token expiration (Unix timestamp in seconds)
46
+ * @param iat - Token issued-at time (Unix timestamp in seconds) for clock-skew compensation
47
+ */
48
+ export function broadcastTokenRefresh(channelName, token, exp, iat) {
49
+ if (typeof BroadcastChannel === 'undefined') {
50
+ return;
51
+ }
52
+ const channel = new BroadcastChannel(channelName);
53
+ channel.postMessage({ type: TOKEN_REFRESHED, token, exp, iat });
54
+ channel.close();
55
+ }
56
+ //# sourceMappingURL=cross-tab-sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross-tab-sync.js","sourceRoot":"","sources":["../../../src/auth/client/cross-tab-sync.ts"],"names":[],"mappings":"AAGA,MAAM,eAAe,GAAG,iBAAiB,CAAA;AAEzC;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAc,EACd,MAA0B;IAE1B,0DAA0D;IAC1D,IAAI,OAAO,gBAAgB,KAAK,WAAW,EAAE,CAAC;QAC5C,OAAO,GAAG,EAAE,GAAE,CAAC,CAAA;IACjB,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;IAExD,MAAM,aAAa,GAAG,CAAC,KAAmB,EAAE,EAAE;QAC5C,kEAAkE;QAClE,IACE,KAAK,CAAC,IAAI,EAAE,IAAI,KAAK,eAAe;YACpC,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,QAAQ;YACpC,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,QAAQ,EAClC,CAAC;YACD,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC,IAAI,CAAA;YAEtC,MAAM,OAAO,GAA4B,EAAE,KAAK,EAAE,GAAG,EAAE,CAAA;YACvD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;gBAC5B,OAAO,CAAC,GAAG,GAAG,GAAG,CAAA;gBACjB,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;YACvC,CAAC;YAED,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAA;YAE7B,IAAI,MAAM,CAAC,mBAAmB,EAAE,CAAC;gBAC/B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAA;YACzD,CAAC;QACH,CAAC;IACH,CAAC,CAAA;IAED,OAAO,CAAC,gBAAgB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;IAElD,OAAO,GAAG,EAAE;QACV,OAAO,CAAC,mBAAmB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;QACrD,OAAO,CAAC,KAAK,EAAE,CAAA;IACjB,CAAC,CAAA;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CACnC,WAAmB,EACnB,KAAa,EACb,GAAW,EACX,GAAY;IAEZ,IAAI,OAAO,gBAAgB,KAAK,WAAW,EAAE,CAAC;QAC5C,OAAM;IACR,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC,WAAW,CAAC,CAAA;IACjD,OAAO,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAA;IAC/D,OAAO,CAAC,KAAK,EAAE,CAAA;AACjB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { broadcastTokenRefresh, setupCrossTabSync } from './cross-tab-sync.js';
2
+ export { refreshAccessToken, setupTokenRefreshOnExpiry } from './token-refresh.js';
@@ -0,0 +1,3 @@
1
+ export { broadcastTokenRefresh, setupCrossTabSync } from './cross-tab-sync.js';
2
+ export { refreshAccessToken, setupTokenRefreshOnExpiry } from './token-refresh.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/auth/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAC3E,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAA"}
@@ -0,0 +1,11 @@
1
+ import type { ReactNode } from 'react';
2
+ export interface GoogleOAuthProviderProps {
3
+ clientId: string;
4
+ children: ReactNode;
5
+ }
6
+ /**
7
+ * Wraps the application tree with Google OAuth context.
8
+ * Thin re-export of `@react-oauth/google`'s provider for
9
+ * consistency with the typeferry auth module surface.
10
+ */
11
+ export declare function GoogleOAuthProvider({ clientId, children, }: GoogleOAuthProviderProps): ReactNode;
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { GoogleOAuthProvider as ReactGoogleOAuthProvider } from '@react-oauth/google';
3
+ /**
4
+ * Wraps the application tree with Google OAuth context.
5
+ * Thin re-export of `@react-oauth/google`'s provider for
6
+ * consistency with the typeferry auth module surface.
7
+ */
8
+ export function GoogleOAuthProvider({ clientId, children, }) {
9
+ return (_jsx(ReactGoogleOAuthProvider, { clientId: clientId, children: children }));
10
+ }
11
+ //# sourceMappingURL=google-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google-provider.js","sourceRoot":"","sources":["../../../../src/auth/client/oauth/google-provider.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,mBAAmB,IAAI,wBAAwB,EAAE,MAAM,qBAAqB,CAAA;AAQrF;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAClC,QAAQ,EACR,QAAQ,GACiB;IACzB,OAAO,CACL,KAAC,wBAAwB,IAAC,QAAQ,EAAE,QAAQ,YACzC,QAAQ,GACgB,CAC5B,CAAA;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ export type { GoogleOAuthProviderProps } from './google-provider.js';
2
+ export { GoogleOAuthProvider } from './google-provider.js';
3
+ export type { UseGoogleLoginOptions } from './use-google-login.js';
4
+ export { useTypeFerryGoogleLogin } from './use-google-login.js';
@@ -0,0 +1,3 @@
1
+ export { GoogleOAuthProvider } from './google-provider.js';
2
+ export { useTypeFerryGoogleLogin } from './use-google-login.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/auth/client/oauth/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAEvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAA"}
@@ -0,0 +1,39 @@
1
+ export interface UseGoogleLoginOptions {
2
+ /**
3
+ * Server method to call with the authorization code.
4
+ * @default 'auth.google'
5
+ */
6
+ method?: string;
7
+ /**
8
+ * Async hook that runs after Google returns the auth code but
9
+ * before the server call. Return additional params to merge
10
+ * with `{ code }`, or return `false` to abort the flow.
11
+ *
12
+ * Useful for reCAPTCHA, analytics, or pre-flight checks.
13
+ */
14
+ beforeServerCall?: (code: string) => Promise<Record<string, unknown> | false>;
15
+ /** Called after successful authentication and context update. */
16
+ onSuccess?: () => void;
17
+ /** Called when any step of the flow fails. */
18
+ onError?: (error: unknown) => void;
19
+ }
20
+ /**
21
+ * Hook that returns a trigger function for the Google OAuth popup flow.
22
+ *
23
+ * On user consent it exchanges the authorization code with the server,
24
+ * updates the typeferry client context, and reconnects the socket with
25
+ * the new credentials.
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * const login = useTypeFerryGoogleLogin({
30
+ * beforeServerCall: async () => {
31
+ * const token = await executeRecaptcha('google_signup')
32
+ * return token ? { recaptchaToken: token } : false
33
+ * },
34
+ * })
35
+ *
36
+ * <button onClick={() => login()}>Sign in with Google</button>
37
+ * ```
38
+ */
39
+ export declare function useTypeFerryGoogleLogin(options?: UseGoogleLoginOptions): () => void;
@@ -0,0 +1,55 @@
1
+ import { useGoogleLogin } from '@react-oauth/google';
2
+ import { useCallback } from 'react';
3
+ import { useClient } from '../../../react/hooks/use-client.js';
4
+ /**
5
+ * Hook that returns a trigger function for the Google OAuth popup flow.
6
+ *
7
+ * On user consent it exchanges the authorization code with the server,
8
+ * updates the typeferry client context, and reconnects the socket with
9
+ * the new credentials.
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * const login = useTypeFerryGoogleLogin({
14
+ * beforeServerCall: async () => {
15
+ * const token = await executeRecaptcha('google_signup')
16
+ * return token ? { recaptchaToken: token } : false
17
+ * },
18
+ * })
19
+ *
20
+ * <button onClick={() => login()}>Sign in with Google</button>
21
+ * ```
22
+ */
23
+ export function useTypeFerryGoogleLogin(options = {}) {
24
+ const { method = 'auth.google', beforeServerCall, onSuccess, onError, } = options;
25
+ const client = useClient();
26
+ const login = useGoogleLogin({
27
+ onSuccess: async ({ code }) => {
28
+ try {
29
+ let extraParams = {};
30
+ if (beforeServerCall) {
31
+ const result = await beforeServerCall(code);
32
+ if (result === false)
33
+ return;
34
+ extraParams = result;
35
+ }
36
+ const { token, exp, iat } = await client.call(method, { code, ...extraParams }, { http: true });
37
+ await client.setContextAndReInit({
38
+ isGoogleAuth: true,
39
+ token,
40
+ exp,
41
+ iat,
42
+ _tokenReceivedAt: Date.now(),
43
+ });
44
+ onSuccess?.();
45
+ }
46
+ catch (error) {
47
+ onError?.(error);
48
+ }
49
+ },
50
+ flow: 'auth-code',
51
+ select_account: true,
52
+ });
53
+ return useCallback(() => login(), [login]);
54
+ }
55
+ //# sourceMappingURL=use-google-login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-google-login.js","sourceRoot":"","sources":["../../../../src/auth/client/oauth/use-google-login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAEnC,OAAO,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAA;AA2B3D;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,uBAAuB,CACrC,UAAiC,EAAE;IAEnC,MAAM,EACJ,MAAM,GAAG,aAAa,EACtB,gBAAgB,EAChB,SAAS,EACT,OAAO,GACR,GAAG,OAAO,CAAA;IAEX,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAE1B,MAAM,KAAK,GAAG,cAAc,CAAC;QAC3B,SAAS,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;YAC5B,IAAI,CAAC;gBACH,IAAI,WAAW,GAA4B,EAAE,CAAA;gBAE7C,IAAI,gBAAgB,EAAE,CAAC;oBACrB,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAA;oBAC3C,IAAI,MAAM,KAAK,KAAK;wBAAE,OAAM;oBAC5B,WAAW,GAAG,MAAM,CAAA;gBACtB,CAAC;gBAED,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAC3C,MAAM,EACN,EAAE,IAAI,EAAE,GAAG,WAAW,EAAE,EACxB,EAAE,IAAI,EAAE,IAAI,EAAE,CACf,CAAA;gBAED,MAAM,MAAM,CAAC,mBAAmB,CAAC;oBAC/B,YAAY,EAAE,IAAI;oBAClB,KAAK;oBACL,GAAG;oBACH,GAAG;oBACH,gBAAgB,EAAE,IAAI,CAAC,GAAG,EAAE;iBAC7B,CAAC,CAAA;gBAEF,SAAS,EAAE,EAAE,CAAA;YACf,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,EAAE,CAAC,KAAK,CAAC,CAAA;YAClB,CAAC;QACH,CAAC;QACD,IAAI,EAAE,WAAW;QACjB,cAAc,EAAE,IAAI;KACrB,CAAC,CAAA;IAEF,OAAO,WAAW,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAA;AAC5C,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { Client } from '../../client/index.js';
2
+ import type { TokenRefreshConfig } from '../types.js';
3
+ export type { TokenRefreshConfig };
4
+ /**
5
+ * Refresh the access token using the configured refresh method.
6
+ * Handles concurrent refresh requests by queueing them per-client.
7
+ *
8
+ * @param client - TypeFerry client instance
9
+ * @param config - Optional configuration overrides
10
+ * @returns New access token, or null if refresh failed
11
+ */
12
+ export declare function refreshAccessToken(client: Client, config?: Partial<TokenRefreshConfig>): Promise<string | null>;
13
+ /**
14
+ * Set up automatic token refresh before expiry.
15
+ * Returns a cleanup function to stop the refresh timer.
16
+ *
17
+ * @param client - TypeFerry client instance
18
+ * @param config - Optional configuration overrides
19
+ * @returns Cleanup function
20
+ */
21
+ export declare function setupTokenRefreshOnExpiry(client: Client, config?: Partial<TokenRefreshConfig>): () => void;
@@ -0,0 +1,212 @@
1
+ import { LogLevel } from '../../client/logger.js';
2
+ import { broadcastTokenRefresh, setupCrossTabSync } from './cross-tab-sync.js';
3
+ const defaultConfig = {
4
+ refreshMethod: 'auth.refresh',
5
+ refreshBeforeExpirySec: 60,
6
+ broadcastChannelName: 'typeferry-token-sync',
7
+ };
8
+ /** Delay before retrying a failed refresh on transient (network) errors. */
9
+ const RETRY_DELAY_MS = 5_000;
10
+ const refreshStateMap = new WeakMap();
11
+ function getRefreshState(client) {
12
+ let state = refreshStateMap.get(client);
13
+ if (!state) {
14
+ state = { isRefreshing: false, failedQueue: [] };
15
+ refreshStateMap.set(client, state);
16
+ }
17
+ return state;
18
+ }
19
+ function processQueue(state, error, token) {
20
+ state.failedQueue.forEach(({ resolve, reject }) => {
21
+ if (error) {
22
+ reject(error);
23
+ }
24
+ else {
25
+ resolve(token);
26
+ }
27
+ });
28
+ state.failedQueue = [];
29
+ }
30
+ /**
31
+ * Check if error is a terminal auth failure vs a transient network error.
32
+ * Terminal failures clear the context and redirect to login. Transient
33
+ * failures schedule a retry.
34
+ */
35
+ function isAuthFailureError(err) {
36
+ if (err.status === 401 || err.status === 403)
37
+ return true;
38
+ if (err.code === 'AUTHENTICATION_FAILED')
39
+ return true;
40
+ const msg = err.message;
41
+ if (msg === 'Token refresh failed')
42
+ return true;
43
+ if (msg.includes('missingRefreshToken'))
44
+ return true;
45
+ if (msg.includes('invalidOrExpiredRefreshToken'))
46
+ return true;
47
+ return false;
48
+ }
49
+ /**
50
+ * Refresh the access token using the configured refresh method.
51
+ * Handles concurrent refresh requests by queueing them per-client.
52
+ *
53
+ * @param client - TypeFerry client instance
54
+ * @param config - Optional configuration overrides
55
+ * @returns New access token, or null if refresh failed
56
+ */
57
+ export async function refreshAccessToken(client, config = {}) {
58
+ const opts = { ...defaultConfig, ...config };
59
+ const state = getRefreshState(client);
60
+ // Queue concurrent requests for the same client
61
+ if (state.isRefreshing) {
62
+ return new Promise((resolve, reject) => {
63
+ state.failedQueue.push({ resolve, reject });
64
+ });
65
+ }
66
+ state.isRefreshing = true;
67
+ try {
68
+ /**
69
+ * Refresh token is sent exclusively via the HttpOnly cookie
70
+ * (credentials: 'include' on fetch). No body param needed — the
71
+ * server reads from the cookie header directly.
72
+ */
73
+ client.logger.auth(LogLevel.INFO, 'Attempting token refresh', {
74
+ method: opts.refreshMethod,
75
+ hasToken: !!client.context.token,
76
+ exp: client.context.exp,
77
+ });
78
+ const result = await client.call(opts.refreshMethod, {}, {
79
+ ignoreInit: true,
80
+ http: true,
81
+ });
82
+ if (!result) {
83
+ throw new Error('Token refresh failed');
84
+ }
85
+ client.logger.auth(LogLevel.INFO, 'Token refresh succeeded', {
86
+ newExp: result.exp,
87
+ });
88
+ client.updateContext({
89
+ token: result.accessToken,
90
+ exp: result.exp,
91
+ iat: result.iat,
92
+ _tokenReceivedAt: Date.now(),
93
+ });
94
+ if (opts.broadcastChannelName) {
95
+ broadcastTokenRefresh(opts.broadcastChannelName, result.accessToken, result.exp, result.iat);
96
+ }
97
+ processQueue(state, null, result.accessToken);
98
+ return result.accessToken;
99
+ }
100
+ catch (error) {
101
+ const err = error;
102
+ const isAuthFailure = isAuthFailureError(err);
103
+ client.logger.auth(isAuthFailure ? LogLevel.WARN : LogLevel.ERROR, 'Token refresh failed', {
104
+ isAuthFailure,
105
+ status: err.status,
106
+ code: err.code,
107
+ hasToken: !!client.context.token,
108
+ }, err);
109
+ if (isAuthFailure)
110
+ client.clearContext();
111
+ processQueue(state, err, null);
112
+ throw error;
113
+ }
114
+ finally {
115
+ state.isRefreshing = false;
116
+ }
117
+ }
118
+ /**
119
+ * Set up automatic token refresh before expiry.
120
+ * Returns a cleanup function to stop the refresh timer.
121
+ *
122
+ * @param client - TypeFerry client instance
123
+ * @param config - Optional configuration overrides
124
+ * @returns Cleanup function
125
+ */
126
+ export function setupTokenRefreshOnExpiry(client, config = {}) {
127
+ const opts = { ...defaultConfig, ...config };
128
+ let refreshTimeout = null;
129
+ const cleanupCrossTab = opts.broadcastChannelName
130
+ ? setupCrossTabSync(client, { channelName: opts.broadcastChannelName })
131
+ : () => { };
132
+ const scheduleRefresh = () => {
133
+ if (refreshTimeout) {
134
+ clearTimeout(refreshTimeout);
135
+ refreshTimeout = null;
136
+ }
137
+ const { exp, iat, _tokenReceivedAt } = client.context;
138
+ if (!exp)
139
+ return;
140
+ /**
141
+ * Clock-skew-safe scheduling: when server-issued `iat` and local
142
+ * `_tokenReceivedAt` are available, compute remaining lifetime using
143
+ * only server-side TTL and client-side elapsed time — both immune
144
+ * to absolute clock differences between client and server.
145
+ *
146
+ * Falls back to the classic `exp - now` calculation for tokens
147
+ * issued before the iat migration.
148
+ */
149
+ let timeUntilRefresh;
150
+ if (iat && _tokenReceivedAt) {
151
+ const tokenTtlMs = (exp - iat) * 1000;
152
+ const elapsedMs = Date.now() - _tokenReceivedAt;
153
+ timeUntilRefresh =
154
+ tokenTtlMs - elapsedMs - opts.refreshBeforeExpirySec * 1000;
155
+ }
156
+ else {
157
+ const now = Math.floor(Date.now() / 1000);
158
+ timeUntilRefresh = (exp - now - opts.refreshBeforeExpirySec) * 1000;
159
+ }
160
+ /**
161
+ * Attempt a refresh and retry once on transient (non-auth) failures.
162
+ *
163
+ * Auth failures (401/403) are terminal — the session is invalid and
164
+ * clearContext already ran inside refreshAccessToken. Network errors
165
+ * are transient, so we schedule a single retry after a short delay
166
+ * to avoid the token expiring silently.
167
+ */
168
+ const attemptRefresh = (meta) => {
169
+ refreshAccessToken(client, opts).catch(error => {
170
+ const err = error;
171
+ client.logger.auth(LogLevel.ERROR, 'Scheduled token refresh failed', meta, err);
172
+ if (!isAuthFailureError(err)) {
173
+ refreshTimeout = setTimeout(scheduleRefresh, RETRY_DELAY_MS);
174
+ }
175
+ });
176
+ };
177
+ // If already expired or about to expire, refresh immediately
178
+ if (timeUntilRefresh <= 0) {
179
+ /**
180
+ * If a refresh is already in progress (e.g. this handler was called
181
+ * from the CONTEXT_CHANGED event emitted inside refreshAccessToken),
182
+ * defer rescheduling instead of queueing a redundant refresh call.
183
+ * The queued path would resolve but never reschedule, leaving the
184
+ * next automatic refresh unscheduled.
185
+ */
186
+ const state = getRefreshState(client);
187
+ if (state.isRefreshing) {
188
+ refreshTimeout = setTimeout(scheduleRefresh, 1000);
189
+ return;
190
+ }
191
+ attemptRefresh({ immediate: true });
192
+ return;
193
+ }
194
+ refreshTimeout = setTimeout(() => {
195
+ attemptRefresh({ scheduledDelayMs: timeUntilRefresh });
196
+ }, timeUntilRefresh);
197
+ };
198
+ // Schedule initial refresh
199
+ scheduleRefresh();
200
+ // Reschedule when context changes (e.g., after refresh)
201
+ const handleContextChange = () => scheduleRefresh();
202
+ client.on('context:changed', handleContextChange);
203
+ // Cleanup function
204
+ return () => {
205
+ if (refreshTimeout) {
206
+ clearTimeout(refreshTimeout);
207
+ }
208
+ client.off('context:changed', handleContextChange);
209
+ cleanupCrossTab();
210
+ };
211
+ }
212
+ //# sourceMappingURL=token-refresh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-refresh.js","sourceRoot":"","sources":["../../../src/auth/client/token-refresh.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export type { AccessTokenPayload, AuthConfig, AuthContext, CookieOptions, CrossTabSyncConfig, DeviceInfo, Session, SessionManager, TokenPair, TokenRefreshConfig, } from './types.js';
2
+ export { clearRefreshTokenCookie, getRefreshTokenFromRequest, setRefreshTokenCookie, } from './server/cookie-utils.js';
3
+ export { parseDeviceInfo } from './server/device-info.js';
4
+ export { decodeToken, signAccessToken, verifyAccessToken, } from './server/jwt-utils.js';
5
+ export { InMemorySessionManager } from './server/session-manager.js';
6
+ export { broadcastTokenRefresh, setupCrossTabSync, } from './client/cross-tab-sync.js';
7
+ export { refreshAccessToken, setupTokenRefreshOnExpiry, } from './client/token-refresh.js';
@@ -0,0 +1,9 @@
1
+ // Server utilities
2
+ export { clearRefreshTokenCookie, getRefreshTokenFromRequest, setRefreshTokenCookie, } from './server/cookie-utils.js';
3
+ export { parseDeviceInfo } from './server/device-info.js';
4
+ export { decodeToken, signAccessToken, verifyAccessToken, } from './server/jwt-utils.js';
5
+ export { InMemorySessionManager } from './server/session-manager.js';
6
+ // Client utilities
7
+ export { broadcastTokenRefresh, setupCrossTabSync, } from './client/cross-tab-sync.js';
8
+ export { refreshAccessToken, setupTokenRefreshOnExpiry, } from './client/token-refresh.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAcA,mBAAmB;AACnB,OAAO,EACL,uBAAuB,EACvB,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EACL,WAAW,EACX,eAAe,EACf,iBAAiB,GAClB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAA;AAEjE,mBAAmB;AACnB,OAAO,EACL,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,wBAAwB,CAAA"}
@@ -0,0 +1,42 @@
1
+ import type { CookieOptions } from '../types.js';
2
+ /**
3
+ * Response-like object that can set headers.
4
+ */
5
+ interface ResponseLike {
6
+ setHeader: (name: string, value: string) => void;
7
+ }
8
+ /**
9
+ * Request-like object that may contain cookies.
10
+ */
11
+ interface RequestLike {
12
+ cookies?: Record<string, string>;
13
+ headers?: {
14
+ cookie?: string;
15
+ };
16
+ }
17
+ /**
18
+ * Set an HttpOnly refresh token cookie.
19
+ *
20
+ * @param res - Response object with setHeader method
21
+ * @param token - Refresh token value
22
+ * @param options - Cookie configuration
23
+ */
24
+ export declare function setRefreshTokenCookie(res: ResponseLike, token: string, options: CookieOptions): void;
25
+ /**
26
+ * Clear a refresh token cookie by setting it to expire immediately.
27
+ *
28
+ * @param res - Response object with setHeader method
29
+ * @param options - Cookie configuration (name, secure, path)
30
+ */
31
+ export declare function clearRefreshTokenCookie(res: ResponseLike, options: Pick<CookieOptions, 'name' | 'secure' | 'sameSite' | 'path'>): void;
32
+ /**
33
+ * Extract refresh token from a request.
34
+ * Checks parsed cookies first, then falls back to manual cookie header parsing.
35
+ * Automatically URL-decodes the cookie value.
36
+ *
37
+ * @param req - Request object with optional cookies or cookie header
38
+ * @param cookieName - Name of the cookie to extract
39
+ * @returns Cookie value if found, undefined otherwise
40
+ */
41
+ export declare function getRefreshTokenFromRequest(req: RequestLike, cookieName: string): string | undefined;
42
+ export {};