orpc-fn 0.1.0 → 0.3.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 (156) hide show
  1. package/README.md +70 -33
  2. package/dist/assemble-procedure.d.ts +13 -0
  3. package/dist/assemble-procedure.d.ts.map +1 -0
  4. package/dist/assemble-procedure.js +29 -0
  5. package/dist/assemble-procedure.js.map +1 -0
  6. package/dist/bound-call.d.ts +1 -1
  7. package/dist/bound-call.d.ts.map +1 -1
  8. package/dist/bound-call.js.map +1 -1
  9. package/dist/cli.d.ts +3 -0
  10. package/dist/cli.d.ts.map +1 -0
  11. package/dist/cli.js +56 -0
  12. package/dist/cli.js.map +1 -0
  13. package/dist/client.d.ts +4 -2
  14. package/dist/client.d.ts.map +1 -1
  15. package/dist/client.js +4 -2
  16. package/dist/client.js.map +1 -1
  17. package/dist/compatibility.d.ts +16 -0
  18. package/dist/compatibility.d.ts.map +1 -0
  19. package/dist/compatibility.js +4 -0
  20. package/dist/compatibility.js.map +1 -0
  21. package/dist/create-fn.d.ts +30 -34
  22. package/dist/create-fn.d.ts.map +1 -1
  23. package/dist/create-fn.js +177 -121
  24. package/dist/create-fn.js.map +1 -1
  25. package/dist/expo.d.ts +11 -25
  26. package/dist/expo.d.ts.map +1 -1
  27. package/dist/expo.js +25 -30
  28. package/dist/expo.js.map +1 -1
  29. package/dist/hono.d.ts +12 -4
  30. package/dist/hono.d.ts.map +1 -1
  31. package/dist/hono.js +29 -12
  32. package/dist/hono.js.map +1 -1
  33. package/dist/index.d.ts +2 -2
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +2 -2
  36. package/dist/index.js.map +1 -1
  37. package/dist/json-schema.d.ts +2 -0
  38. package/dist/json-schema.d.ts.map +1 -1
  39. package/dist/json-schema.js +11 -0
  40. package/dist/json-schema.js.map +1 -1
  41. package/dist/live/codec.d.ts +6 -1
  42. package/dist/live/codec.d.ts.map +1 -1
  43. package/dist/live/codec.js +14 -3
  44. package/dist/live/codec.js.map +1 -1
  45. package/dist/live/fn-live.d.ts +67 -22
  46. package/dist/live/fn-live.d.ts.map +1 -1
  47. package/dist/live/fn-live.js +98 -16
  48. package/dist/live/fn-live.js.map +1 -1
  49. package/dist/live/index.d.ts +1 -1
  50. package/dist/live/index.d.ts.map +1 -1
  51. package/dist/live/index.js.map +1 -1
  52. package/dist/live/ioredis.d.ts +4 -1
  53. package/dist/live/ioredis.d.ts.map +1 -1
  54. package/dist/live/ioredis.js +21 -2
  55. package/dist/live/ioredis.js.map +1 -1
  56. package/dist/live/lifecycle.d.ts +7 -0
  57. package/dist/live/lifecycle.d.ts.map +1 -0
  58. package/dist/live/lifecycle.js +36 -0
  59. package/dist/live/lifecycle.js.map +1 -0
  60. package/dist/live/memory.d.ts.map +1 -1
  61. package/dist/live/memory.js +4 -0
  62. package/dist/live/memory.js.map +1 -1
  63. package/dist/live/pub-sub.d.ts +81 -13
  64. package/dist/live/pub-sub.d.ts.map +1 -1
  65. package/dist/live/pub-sub.js +437 -126
  66. package/dist/live/pub-sub.js.map +1 -1
  67. package/dist/live/redis-bun.d.ts +1 -1
  68. package/dist/live/redis-bun.d.ts.map +1 -1
  69. package/dist/live/redis-bun.js +3 -5
  70. package/dist/live/redis-bun.js.map +1 -1
  71. package/dist/live/redis.d.ts +2 -2
  72. package/dist/live/redis.d.ts.map +1 -1
  73. package/dist/live/redis.js +36 -9
  74. package/dist/live/redis.js.map +1 -1
  75. package/dist/live/transport.d.ts +5 -1
  76. package/dist/live/transport.d.ts.map +1 -1
  77. package/dist/live/transport.js.map +1 -1
  78. package/dist/logger.d.ts +2 -0
  79. package/dist/logger.d.ts.map +1 -1
  80. package/dist/logger.js +21 -0
  81. package/dist/logger.js.map +1 -1
  82. package/dist/mastra.d.ts.map +1 -1
  83. package/dist/mastra.js +16 -7
  84. package/dist/mastra.js.map +1 -1
  85. package/dist/mcp/core.d.ts +41 -0
  86. package/dist/mcp/core.d.ts.map +1 -0
  87. package/dist/mcp/core.js +61 -0
  88. package/dist/mcp/core.js.map +1 -0
  89. package/dist/mcp/sdk.d.ts +12 -0
  90. package/dist/mcp/sdk.d.ts.map +1 -0
  91. package/dist/mcp/sdk.js +14 -0
  92. package/dist/mcp/sdk.js.map +1 -0
  93. package/dist/mcp/server.d.ts +11 -0
  94. package/dist/mcp/server.d.ts.map +1 -0
  95. package/dist/mcp/server.js +13 -0
  96. package/dist/mcp/server.js.map +1 -0
  97. package/dist/mcp.d.ts +3 -2
  98. package/dist/mcp.d.ts.map +1 -1
  99. package/dist/mcp.js +22 -7
  100. package/dist/mcp.js.map +1 -1
  101. package/dist/meta.d.ts +15 -7
  102. package/dist/meta.d.ts.map +1 -1
  103. package/dist/meta.js +9 -2
  104. package/dist/meta.js.map +1 -1
  105. package/dist/otel.d.ts.map +1 -1
  106. package/dist/otel.js +77 -6
  107. package/dist/otel.js.map +1 -1
  108. package/dist/route-options.d.ts +22 -0
  109. package/dist/route-options.d.ts.map +1 -0
  110. package/dist/route-options.js +67 -0
  111. package/dist/route-options.js.map +1 -0
  112. package/dist/router.d.ts +13 -1
  113. package/dist/router.d.ts.map +1 -1
  114. package/dist/router.js +35 -0
  115. package/dist/router.js.map +1 -1
  116. package/dist/timing.d.ts +8 -0
  117. package/dist/timing.d.ts.map +1 -0
  118. package/dist/timing.js +4 -0
  119. package/dist/timing.js.map +1 -0
  120. package/dist/types.d.ts +96 -41
  121. package/dist/types.d.ts.map +1 -1
  122. package/dist/types.js +6 -2
  123. package/dist/types.js.map +1 -1
  124. package/package.json +28 -3
  125. package/src/assemble-procedure.ts +42 -0
  126. package/src/bound-call.ts +4 -3
  127. package/src/cli.ts +68 -0
  128. package/src/client.ts +9 -2
  129. package/src/compatibility.ts +39 -0
  130. package/src/create-fn.ts +295 -182
  131. package/src/expo.ts +49 -44
  132. package/src/hono.ts +36 -17
  133. package/src/index.ts +7 -2
  134. package/src/json-schema.ts +16 -0
  135. package/src/live/codec.ts +22 -3
  136. package/src/live/fn-live.ts +248 -69
  137. package/src/live/index.ts +2 -0
  138. package/src/live/ioredis.ts +22 -2
  139. package/src/live/lifecycle.ts +44 -0
  140. package/src/live/memory.ts +4 -0
  141. package/src/live/pub-sub.ts +619 -168
  142. package/src/live/redis-bun.ts +7 -5
  143. package/src/live/redis.ts +37 -11
  144. package/src/live/transport.ts +4 -1
  145. package/src/logger.ts +20 -0
  146. package/src/mastra.ts +15 -7
  147. package/src/mcp/core.ts +102 -0
  148. package/src/mcp/sdk.ts +36 -0
  149. package/src/mcp/server.ts +35 -0
  150. package/src/mcp.ts +48 -20
  151. package/src/meta.ts +40 -24
  152. package/src/otel.ts +77 -10
  153. package/src/route-options.ts +100 -0
  154. package/src/router.ts +58 -1
  155. package/src/timing.ts +5 -0
  156. package/src/types.ts +186 -62
@@ -1 +1 @@
1
- {"version":3,"file":"fn-live.js","sourceRoot":"","sources":["../../src/live/fn-live.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,SAAS,EAAE,MAAM,cAAc,CAAA;AAG3D,OAAO,EAAE,cAAc,EAAiB,MAAM,YAAY,CAAA;AAmB1D,wEAAwE;AACxE,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,CAAA;AAEjC,MAAM,iBAAiB,GAAG,MAAM,CAAC,cAAc,CAAC,CAAA;AAchD,MAAM,UAAU,WAAW,CAC1B,KAAc,EACd,IAAW;IAEX,OAAO,EAAE,CAAC,iBAAiB,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAA;AAClD,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACpC,OAAO,CACN,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,iBAAiB,IAAI,KAAK,CACzE,CAAA;AACF,CAAC;AAkJD;;;;;;;;GAQG;AACH,MAAM,UAAU,yBAAyB,CACxC,GAAY,EACZ,QAAgB,EAChB,MAA+B;AAC/B,kEAAkE;AAClE,UAAU,GAAgC,CAAC,KAAK,EAAE,EAAE,CACnD,KAAK,YAAY,SAAS,IAAI,KAAK,CAAC,MAAM,GAAG,GAAG;IAEjD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,CAAC,KAAK,CAAC,gCAAgC,EAAE;YAC9C,IAAI,EAAE,QAAQ;YACd,GAAG,EAAE,cAAc,CAAC,GAAG,CAAC;SACxB,CAAC,CAAA;IACH,CAAC;IACD,MAAM,eAAe,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;AACrC,CAAC;AAED,kFAAkF;AAClF,SAAS,eAAe,CACvB,GAAY,EACZ,QAAgB;IAEhB,IAAI,GAAG,YAAY,SAAS;QAAE,OAAO,GAAG,CAAA;IACxC,OAAO,IAAI,SAAS,CAAC,uBAAuB,EAAE;QAC7C,OAAO,EAAE,uCAAuC,QAAQ,EAAE;QAC1D,KAAK,EAAE,GAAG;KACV,CAAC,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,mBAAmB,CAIxC,IAQD;IACA,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,IAAI,CAAA;IAEnD,IAAI,OAAO,GAA2C,IAAI,CAAA;IAC1D,MAAM,QAAQ,GAAG,GAAG,EAAE;QACrB,MAAM,IAAI,GAAG,OAAO,IAAI,MAAM,CAAC,IAAI,EAAE,CAAA;QACrC,OAAO,GAAG,IAAI,CAAA;QACd,OAAO,IAAI,CAAA;IACZ,CAAC,CAAA;IAED,IAAI,QAAQ,GAAG,OAAO,CAAA;IACtB,MAAM,QAAQ,CAAA;IAEd,OAAO,IAAI,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,MAAM,QAAQ,EAAE,CAAA;QAChC,IAAI,OAAO,CAAC,IAAI;YAAE,MAAK;QAEvB,MAAM,KAAK,GAAa,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QAEvC,IAAI,UAAU,EAAE,CAAC;YAChB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,CAAA;YACrC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC;gBAC3B,MAAM,WAAW,GAAG,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;gBACtC,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAA;gBACvB,IAAI,KAAgD,CAAA;gBACpD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;oBACjC,IAAI;oBACJ,IAAI,OAAO,CAAiB,CAAC,OAAO,EAAE,EAAE;wBACvC,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,CAAC,CAAA;oBAClD,CAAC,CAAC;iBACF,CAAC,CAAA;gBACF,YAAY,CAAC,KAAK,CAAC,CAAA;gBAEnB,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;oBACxB,mEAAmE;oBACnE,gEAAgE;oBAChE,OAAO,GAAG,IAAI,CAAA;oBACd,MAAK;gBACN,CAAC;gBAED,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;oBACjB,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;oBACjC,MAAK;gBACN,CAAC;gBACD,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YACzB,CAAC;QACF,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;YAC3B,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;YACzC,IAAI,IAAI,KAAK,SAAS;gBAAE,SAAQ;YAChC,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzB,QAAQ,GAAG,IAAI,CAAC,KAAgB,CAAA;gBAChC,MAAM,IAAI,CAAC,IAAa,CAAA;gBACxB,SAAQ;YACT,CAAC;YACD,QAAQ,GAAG,IAAI,CAAA;YACf,MAAM,QAAQ,CAAA;QACf,CAAC;IACF,CAAC;AACF,CAAC;AAoBD;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,OAM5B;IACA,MAAM,EAAE,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,GAAG,OAAO,CAAA;IAC9C,MAAM,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;IAE7D,OAAO,CACN,OAU2B,EAC1B,EAAE;QACH,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,WAAW,EAAE,GAAG,OAAO,CAAA;QACtE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,IAAI,GAAG,IAAI,OAAO,CAAA;QAC5C,MAAM,WAAW,GAChB,IAAI,CAAC,OAAO,IAAI,mBAAmB,WAAW,CAAC,OAAO,IAAI,IAAI,EAAE,CAAA;QACjE,MAAM,eAAe,GAAG,IAAI,CAAC,WAAW,IAAI,WAAW,CAAC,WAAW,CAAA;QAEnE,kEAAkE;QAClE,MAAM,OAAO,GAAG,aAAa,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAA;QAE1D,MAAM,OAAO,GAAG,KAAK,EAAE,KAAc,EAAE,EAAE;YACxC,IAAI,CAAC,IAAI,CAAC,WAAW;gBAAE,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;YACpD,IAAI,CAAC;gBACJ,MAAM,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;YAC7B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACd,uEAAuE;gBACvE,4CAA4C;gBAC5C,UAAU,CAAC,KAAK,CAAC,uBAAuB,EAAE;oBACzC,IAAI,EAAE,QAAQ;oBACd,GAAG,EAAE,cAAc,CAAC,GAAG,CAAC;iBACxB,CAAC,CAAA;YACH,CAAC;QACF,CAAC,CAAA;QAED,MAAM,UAAU,GAAG,CAAC,MAAqB,EAAE,EAAE,CAC5C,OAAO,CAAC,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,CAAC,CAAA;QAChC,sEAAsE;QACtE,MAAM,WAAW,GAAG,KAAK,EAAE,MAAqB,EAAE,EAAE;YACnD,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,CAAA;YACvC,OAAO,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAA;QACnD,CAAC,CAAA;QAED,MAAM,SAAS,GAAG,EAAE,CAAC;YACpB,GAAG,WAAW;YACd,IAAI;YACJ,KAAK;YACL,MAAM;YACN,OAAO,EAAE,UAAU;SACnB,CAAC,CAAA;QAEF,0EAA0E;QAC1E,MAAM,YAAY,GAAG,MAAM,CAAC,WAAW,CACtC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CACjE,CAAA;QACD,MAAM,SAAS,GAAG,EAAE,CAAC;YACpB,GAAG,YAAY;YACf,SAAS,EAAE,WAAW,CAAC,SAAS;YAChC,IAAI,EAAE,WAAW,CAAC,IAAI;YACtB,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,KAAK;YACb,KAAK;YACL,OAAO,EAAE,WAAW;YACpB,WAAW,EAAE,eAAe;YAC5B,OAAO,EAAE,KAAK,SAAS,CAAC,EAAE,MAAqB;gBAC9C,oEAAoE;gBACpE,gEAAgE;gBAChE,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;oBACvC,KAAK,EAAE,MAAM,CAAC,KAAK;oBACnB,OAAO,EAAE,MAAM,CAAC,OAAO;oBACvB,MAAM,EAAE,MAAM,CAAC,MAAM;iBACrB,CAAC,CAAA;gBACF,IAAI,CAAC;oBACJ,IAAI,OAAgB,CAAA;oBACpB,IAAI,CAAC;wBACJ,OAAO,GAAG,MAAM,WAAW,CAAC,MAAM,CAAC,CAAA;oBACpC,CAAC;oBAAC,OAAO,GAAG,EAAE,CAAC;wBACd,gEAAgE;wBAChE,MAAM,eAAe,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;oBACrC,CAAC;oBAED,MAAM,KAAK,GAAG,CAAC,SAAmC,EAAE,EAAE,CACrD,WAAW,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,SAAS,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC,CAAA;oBAC7D,MAAM,KAAK,GAAG,KAAK,EAAE,KAAc,EAAE,QAAiB,EAAE,EAAE;wBACzD,IACC,IAAI,CAAC,YAAY;4BACjB,CAAC,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,EACzD,CAAC;4BACF,OAAO,SAAS,CAAA;wBACjB,CAAC;wBACD,IAAI,CAAC,IAAI,CAAC,aAAa;4BAAE,OAAO,WAAW,CAAC,MAAM,CAAC,CAAA;wBACnD,OAAO,IAAI,CAAC,aAAa,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAA;oBACjE,CAAC,CAAA;oBAED,KAAK,CAAC,CAAC,mBAAmB,CAAC;wBAC1B,MAAM,EAAE,YAAY,CAAC,MAAM;wBAC3B,OAAO;wBACP,UAAU,EAAE,IAAI,CAAC,UAAU;wBAC3B,KAAK;qBACL,CAAC,CAAA;gBACH,CAAC;wBAAS,CAAC;oBACV,YAAY,CAAC,KAAK,EAAE,CAAA;gBACrB,CAAC;YACF,CAAC;SACD,CAAC,CAAA;QAEF,OAAO;YACN,SAAS;YACT,SAAS;YACT,OAAO;YACP,cAAc,EAAE,OAAO,CAAC,cAAc;SACtC,CAAA;IACF,CAAC,CAAA;AACF,CAAC","sourcesContent":["import type { Schema } from '@orpc/contract'\nimport { type AnyProcedure, ORPCError } from '@orpc/server'\nimport type { ZodType, z } from 'zod'\nimport type { FnLogger } from '../logger.js'\nimport { errorMessageOf, type SpanLike } from '../otel.js'\nimport type {\n\tFnContext,\n\tFnDefinition,\n\tFnProcedure,\n\tFnRouteOptions,\n\tHandlerParams,\n\tMaybePromise,\n\tProcedureKey\n} from '../types.js'\nimport type {\n\tAuthFn,\n\tChannel,\n\tChannelDefinition,\n\tChannelOptions,\n\tObjectSchema,\n\tPublisherConfig\n} from './pub-sub.js'\n\n/** Marks a coalesce window that ended before the next event arrived. */\nconst TIMEOUT = Symbol('timeout')\n\nconst fnLivePatchMarker = Symbol('fnLive.patch')\n\n/**\n * Transformer result that splits the internal accumulator from the wire\n * payload: `state` becomes the `previous` snapshot for later events while only\n * `emit` is sent to the subscriber. Lets high-frequency streams avoid\n * re-serializing the full snapshot per event.\n */\nexport type FnLivePatch<TOutput, TEmit> = {\n\t[fnLivePatchMarker]: true\n\tstate: TOutput\n\temit: TEmit\n}\n\nexport function fnLivePatch<TOutput, TEmit>(\n\tstate: TOutput,\n\temit: TEmit\n): FnLivePatch<TOutput, TEmit> {\n\treturn { [fnLivePatchMarker]: true, state, emit }\n}\n\nfunction isFnLivePatch(value: unknown): value is FnLivePatch<unknown, unknown> {\n\treturn (\n\t\ttypeof value === 'object' && value !== null && fnLivePatchMarker in value\n\t)\n}\n\nexport type FnLiveConfig<\n\tTDef extends FnDefinition,\n\tTInput,\n\tTEventSchema extends ZodType,\n\tTOutput,\n\tTKey extends ProcedureKey<TDef>,\n\tTEmit = never\n> = Omit<PublisherConfig, 'name'> & {\n\t/** Subscribe route name; default `${name}.live`. */\n\tname?: string\n\teventSchema: TEventSchema\n\tchannel: ChannelDefinition<\n\t\tTInput,\n\t\tz.output<TEventSchema>,\n\t\tFnContext<TDef, TKey>\n\t>\n\t/** Fold an event into the snapshot; without it every event re-runs the handler. */\n\ttransformerFn?: (\n\t\tparams: HandlerParams<TDef, TInput, TKey> & {\n\t\t\tevent: z.output<TEventSchema>\n\t\t\tprevious: TOutput | undefined\n\t\t\trerun: (input?: TInput) => Promise<TOutput>\n\t\t}\n\t) => MaybePromise<TOutput | FnLivePatch<TOutput, TEmit> | undefined>\n\t/** Return false to skip an event. */\n\tshouldUpdate?: (\n\t\tparams: HandlerParams<TDef, TInput, TKey> & {\n\t\t\tevent: z.output<TEventSchema>\n\t\t\tprevious: TOutput | undefined\n\t\t}\n\t) => MaybePromise<boolean>\n\tauthFn?: AuthFn<TInput, FnContext<TDef, TKey>>\n\t/** Log publish failures instead of throwing them into the publishing route. */\n\tsafePublish?: boolean\n\t/** Batch events arriving within this window into one snapshot update. */\n\tcoalesceMs?: number\n\t/**\n\t * When a slow subscriber's queue overflows (drop-oldest), this marker is\n\t * enqueued INSTEAD of the dropped event so the client resyncs. Return\n\t * `null` to skip.\n\t */\n\toverflowMarker?: (input: TInput) => z.output<TEventSchema> | null\n\tsummary?: string\n\tdescription?: string\n}\n\nexport type FnLiveReturn<\n\tTDef extends FnDefinition,\n\tTKey extends ProcedureKey<TDef>,\n\tTInput extends ObjectSchema,\n\tTOutputSchema extends Schema<unknown, unknown>,\n\tTOutput,\n\tTEventSchema extends ZodType,\n\tTEmit = never\n> = {\n\tprocedure: FnProcedure<TDef, TKey, TInput, TOutputSchema>\n\tsubscribe: FnProcedure<\n\t\tTDef,\n\t\tTKey,\n\t\tTInput,\n\t\tSchema<AsyncGenerator<TOutput | TEmit>, AsyncGenerator<TOutput | TEmit>>\n\t>\n\tpublish: (event: z.input<TEventSchema>) => Promise<void>\n\tgetChannelName: (\n\t\tparams: Partial<z.output<TInput>> | Partial<z.output<TEventSchema>>,\n\t\tcontext?: FnContext<TDef, TKey>\n\t) => string\n}\n\n/**\n * A route plus a subscribe route that streams its result: the initial\n * snapshot, then an update for every event published on the channel.\n */\nexport interface FnLive<TDef extends FnDefinition> {\n\t<\n\t\tTInput extends ObjectSchema,\n\t\tTOutputSchema extends ZodType,\n\t\tTEventSchema extends ZodType,\n\t\tTKey extends ProcedureKey<TDef> = TDef['default'],\n\t\tTEmit = never\n\t>(\n\t\toptions: {\n\t\t\tinput: TInput\n\t\t\toutput: TOutputSchema\n\t\t\thandler: (\n\t\t\t\tparams: HandlerParams<TDef, z.output<TInput>, NoInfer<TKey>> & {\n\t\t\t\t\tpublish: (event: z.input<TEventSchema>) => Promise<void>\n\t\t\t\t}\n\t\t\t\t// The output schema parses what the handler returns: its input type.\n\t\t\t) => MaybePromise<z.input<TOutputSchema>>\n\t\t\tlive: FnLiveConfig<\n\t\t\t\tTDef,\n\t\t\t\tz.output<TInput>,\n\t\t\t\tTEventSchema,\n\t\t\t\tz.output<TOutputSchema>,\n\t\t\t\tNoInfer<TKey>,\n\t\t\t\tTEmit\n\t\t\t>\n\t\t} & FnRouteOptions<TDef, TKey>\n\t): FnLiveReturn<\n\t\tTDef,\n\t\tTKey,\n\t\tTInput,\n\t\tTOutputSchema,\n\t\tz.output<TOutputSchema>,\n\t\tTEventSchema,\n\t\tTEmit\n\t>\n\n\t<\n\t\tTInput extends ObjectSchema,\n\t\tTOutput,\n\t\tTEventSchema extends ZodType,\n\t\tTKey extends ProcedureKey<TDef> = TDef['default'],\n\t\tTEmit = never\n\t>(\n\t\toptions: {\n\t\t\tinput: TInput\n\t\t\toutput?: undefined\n\t\t\thandler: (\n\t\t\t\tparams: HandlerParams<TDef, z.output<TInput>, NoInfer<TKey>> & {\n\t\t\t\t\tpublish: (event: z.input<TEventSchema>) => Promise<void>\n\t\t\t\t}\n\t\t\t) => MaybePromise<TOutput>\n\t\t\tlive: FnLiveConfig<\n\t\t\t\tTDef,\n\t\t\t\tz.output<TInput>,\n\t\t\t\tTEventSchema,\n\t\t\t\tTOutput,\n\t\t\t\tNoInfer<TKey>,\n\t\t\t\tTEmit\n\t\t\t>\n\t\t} & FnRouteOptions<TDef, TKey>\n\t): FnLiveReturn<\n\t\tTDef,\n\t\tTKey,\n\t\tTInput,\n\t\tSchema<TOutput, TOutput>,\n\t\tTOutput,\n\t\tTEventSchema,\n\t\tTEmit\n\t>\n}\n\n/**\n * Fail a live subscription whose initial snapshot could not be built.\n *\n * An expected client failure - an `ORPCError` with a 4xx status, e.g. the\n * subscribed resource was not found or access was refused - reaches the\n * subscriber unchanged and is NOT logged as a server fault. Only 5xx and\n * unknown failures are logged. Unknown errors are wrapped as\n * `INTERNAL_SERVER_ERROR`.\n */\nexport function throwInitialSnapshotError(\n\terr: unknown,\n\tliveName: string,\n\tlogger: Pick<FnLogger, 'error'>,\n\t/** `createFn`'s `isExpectedError`; default: a 4xx `ORPCError`. */\n\tisExpected: (error: unknown) => boolean = (error) =>\n\t\terror instanceof ORPCError && error.status < 500\n): never {\n\tif (!isExpected(err)) {\n\t\tlogger.error('fnLive initial snapshot failed', {\n\t\t\tname: liveName,\n\t\t\terr: errorMessageOf(err)\n\t\t})\n\t}\n\tthrow toSnapshotError(err, liveName)\n}\n\n/** An `ORPCError` passes through; anything else becomes INTERNAL_SERVER_ERROR. */\nfunction toSnapshotError(\n\terr: unknown,\n\tliveName: string\n): ORPCError<string, unknown> {\n\tif (err instanceof ORPCError) return err\n\treturn new ORPCError('INTERNAL_SERVER_ERROR', {\n\t\tmessage: `Failed to load initial snapshot for ${liveName}`,\n\t\tcause: err\n\t})\n}\n\n/**\n * Drives a live subscription: yields the initial snapshot, then folds each\n * inbound event into the running snapshot via `apply`, yielding after every\n * change. With `coalesceMs`, events arriving within that window are batched so\n * bursty streams apply together.\n *\n * `apply` may return an {@link FnLivePatch} to keep the full snapshot as the\n * internal accumulator while yielding only the lighter `emit` payload.\n *\n * Invariant: there is never more than one outstanding `source.next()` read. On\n * a coalesce-window timeout the still-pending read is stashed in `pending` and\n * reused by the next `readNext()` - issuing a second concurrent read would\n * strand the in-flight event behind the next one (delivering it \"one behind\").\n */\nexport async function* streamLiveSnapshots<\n\tTEvent,\n\tTOutput,\n\tTEmit = never\n>(opts: {\n\tsource: AsyncIterator<TEvent>\n\tinitial: TOutput\n\tcoalesceMs?: number | undefined\n\tapply: (\n\t\tevent: TEvent,\n\t\tprevious: TOutput\n\t) => MaybePromise<TOutput | FnLivePatch<TOutput, TEmit> | undefined>\n}): AsyncGenerator<TOutput | TEmit> {\n\tconst { source, initial, coalesceMs, apply } = opts\n\n\tlet pending: Promise<IteratorResult<TEvent>> | null = null\n\tconst readNext = () => {\n\t\tconst read = pending ?? source.next()\n\t\tpending = null\n\t\treturn read\n\t}\n\n\tlet previous = initial\n\tyield previous\n\n\twhile (true) {\n\t\tconst current = await readNext()\n\t\tif (current.done) break\n\n\t\tconst batch: TEvent[] = [current.value]\n\n\t\tif (coalesceMs) {\n\t\t\tconst endAt = Date.now() + coalesceMs\n\t\t\twhile (Date.now() < endAt) {\n\t\t\t\tconst remainingMs = endAt - Date.now()\n\t\t\t\tconst read = readNext()\n\t\t\t\tlet timer: ReturnType<typeof setTimeout> | undefined\n\t\t\t\tconst result = await Promise.race([\n\t\t\t\t\tread,\n\t\t\t\t\tnew Promise<typeof TIMEOUT>((resolve) => {\n\t\t\t\t\t\ttimer = setTimeout(resolve, remainingMs, TIMEOUT)\n\t\t\t\t\t})\n\t\t\t\t])\n\t\t\t\tclearTimeout(timer)\n\n\t\t\t\tif (result === TIMEOUT) {\n\t\t\t\t\t// Reuse the SAME in-flight read next iteration instead of starting\n\t\t\t\t\t// a new one - this is what prevents the \"one behind\" stranding.\n\t\t\t\t\tpending = read\n\t\t\t\t\tbreak\n\t\t\t\t}\n\n\t\t\t\tif (result.done) {\n\t\t\t\t\tpending = Promise.resolve(result)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tbatch.push(result.value)\n\t\t\t}\n\t\t}\n\n\t\tfor (const event of batch) {\n\t\t\tconst next = await apply(event, previous)\n\t\t\tif (next === undefined) continue\n\t\t\tif (isFnLivePatch(next)) {\n\t\t\t\tprevious = next.state as TOutput\n\t\t\t\tyield next.emit as TEmit\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tprevious = next\n\t\t\tyield previous\n\t\t}\n\t}\n}\n\ntype RuntimeParams = Record<string, unknown> & {\n\tinput: Record<string, unknown>\n\tcontext: unknown\n\tsignal: AbortSignal | undefined\n\tlogger: FnLogger\n}\n\n/** `FnLiveConfig` with the generics erased: what the implementation reads. */\ntype RuntimeLiveConfig = Omit<ChannelOptions, 'name'> & {\n\tname?: string\n\ttransformerFn?: (params: RuntimeParams & Record<string, unknown>) => unknown\n\tshouldUpdate?: (params: RuntimeParams & Record<string, unknown>) => unknown\n\tsafePublish?: boolean\n\tcoalesceMs?: number\n\tsummary?: string\n\tdescription?: string\n}\n\n/**\n * @internal Wires `fnLive` onto an `fn` and channel runtime of the same\n * instance. `createFn` returns it typed as {@link FnLive}.\n */\nexport function createFnLive(runtime: {\n\t// biome-ignore lint/suspicious/noExplicitAny: runtime half of the typed `Fn`\n\tfn: (options: any) => AnyProcedure\n\tcreateChannel: (options: ChannelOptions) => Channel\n\tcreateLogger: (scope: string, span: SpanLike | undefined) => FnLogger\n\tisGuard: (option: string) => boolean\n}) {\n\tconst { fn, createChannel, isGuard } = runtime\n\tconst liveLogger = runtime.createLogger('fn-live', undefined)\n\n\treturn (\n\t\toptions: {\n\t\t\tlive: RuntimeLiveConfig\n\t\t\thandler: (params: RuntimeParams) => unknown\n\t\t\tinput: ZodType\n\t\t\toutput?: ZodType\n\t\t\tname: string\n\t\t\tprocedure?: string\n\t\t\tsummary?: string\n\t\t\tdescription?: string\n\t\t\ttags?: string[]\n\t\t} & Record<string, unknown>\n\t) => {\n\t\tconst { live, handler, input, output, name, ...routeConfig } = options\n\t\tconst liveName = live.name ?? `${name}.live`\n\t\tconst liveSummary =\n\t\t\tlive.summary ?? `Live updates of ${routeConfig.summary ?? name}`\n\t\tconst liveDescription = live.description ?? routeConfig.description\n\n\t\t// `createChannel` reads only the channel keys of the live config.\n\t\tconst channel = createChannel({ ...live, name: liveName })\n\n\t\tconst publish = async (event: unknown) => {\n\t\t\tif (!live.safePublish) return channel.publish(event)\n\t\t\ttry {\n\t\t\t\tawait channel.publish(event)\n\t\t\t} catch (err) {\n\t\t\t\t// Live update failures must not roll back the route that emitted them,\n\t\t\t\t// but they should still be visible in logs.\n\t\t\t\tliveLogger.error('fnLive publish failed', {\n\t\t\t\t\tname: liveName,\n\t\t\t\t\terr: errorMessageOf(err)\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tconst runHandler = (params: RuntimeParams) =>\n\t\t\thandler({ ...params, publish })\n\t\t// Snapshots go through the output schema like the route's own result.\n\t\tconst runSnapshot = async (params: RuntimeParams) => {\n\t\t\tconst result = await runHandler(params)\n\t\t\treturn output ? output.parseAsync(result) : result\n\t\t}\n\n\t\tconst procedure = fn({\n\t\t\t...routeConfig,\n\t\t\tname,\n\t\t\tinput,\n\t\t\toutput,\n\t\t\thandler: runHandler\n\t\t})\n\n\t\t// Guards run on the subscribe route too; route meta stays on `procedure`.\n\t\tconst guardOptions = Object.fromEntries(\n\t\t\tObject.entries(routeConfig).filter(([option]) => isGuard(option))\n\t\t)\n\t\tconst subscribe = fn({\n\t\t\t...guardOptions,\n\t\t\tprocedure: routeConfig.procedure,\n\t\t\ttags: routeConfig.tags,\n\t\t\tname: liveName,\n\t\t\tmethod: 'GET',\n\t\t\tinput,\n\t\t\tsummary: liveSummary,\n\t\t\tdescription: liveDescription,\n\t\t\thandler: async function* (params: RuntimeParams) {\n\t\t\t\t// Authorize and subscribe before the snapshot: a refused subscriber\n\t\t\t\t// gets nothing, and events published while it loads are queued.\n\t\t\t\tconst subscription = await channel.open({\n\t\t\t\t\tinput: params.input,\n\t\t\t\t\tcontext: params.context,\n\t\t\t\t\tsignal: params.signal\n\t\t\t\t})\n\t\t\t\ttry {\n\t\t\t\t\tlet initial: unknown\n\t\t\t\t\ttry {\n\t\t\t\t\t\tinitial = await runSnapshot(params)\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t// `fn.completed` logs it, at the level `isExpectedError` picks.\n\t\t\t\t\t\tthrow toSnapshotError(err, liveName)\n\t\t\t\t\t}\n\n\t\t\t\t\tconst rerun = (nextInput?: Record<string, unknown>) =>\n\t\t\t\t\t\trunSnapshot({ ...params, input: nextInput ?? params.input })\n\t\t\t\t\tconst apply = async (event: unknown, previous: unknown) => {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tlive.shouldUpdate &&\n\t\t\t\t\t\t\t!(await live.shouldUpdate({ ...params, event, previous }))\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\treturn undefined\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!live.transformerFn) return runSnapshot(params)\n\t\t\t\t\t\treturn live.transformerFn({ ...params, event, previous, rerun })\n\t\t\t\t\t}\n\n\t\t\t\t\tyield* streamLiveSnapshots({\n\t\t\t\t\t\tsource: subscription.events,\n\t\t\t\t\t\tinitial,\n\t\t\t\t\t\tcoalesceMs: live.coalesceMs,\n\t\t\t\t\t\tapply\n\t\t\t\t\t})\n\t\t\t\t} finally {\n\t\t\t\t\tsubscription.close()\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\n\t\treturn {\n\t\t\tprocedure,\n\t\t\tsubscribe,\n\t\t\tpublish,\n\t\t\tgetChannelName: channel.getChannelName\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"fn-live.js","sourceRoot":"","sources":["../../src/live/fn-live.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AnySchema, ErrorMap, Schema } from '@orpc/contract'\nimport { type AnyProcedure, ORPCError } from '@orpc/server'\nimport type { ZodType, z } from 'zod'\nimport { RAW_INPUT } from '../timing.js'\nimport { LIVE_GAP, positiveInteger } from './lifecycle.js'\nimport type { FnLogger } from '../logger.js'\nimport { errorMessageOf, type SpanLike } from '../otel.js'\nimport type {\n\tFnContext,\n\tFnDefinition,\n\tFnProcedure,\n\tFnRouteOptions,\n\tHandlerParams,\n\tMaybePromise,\n\tProcedureKey\n} from '../types.js'\nimport type {\n\tAuthFn,\n\tChannel,\n\tChannelDefinition,\n\tChannelOptions,\n\tChannelQueueOptions,\n\tObjectSchema,\n\tPublisherConfig\n} from './pub-sub.js'\n\n/** Marks a coalesce window that ended before the next event arrived. */\nconst TIMEOUT = Symbol('timeout')\n\nconst fnLivePatchMarker = Symbol('fnLive.patch')\n\n/**\n * Transformer result that splits the internal accumulator from the wire\n * payload: `state` becomes the `previous` snapshot for later events while only\n * `emit` is sent to the subscriber. Lets high-frequency streams avoid\n * re-serializing the full snapshot per event.\n */\nexport type FnLivePatch<TOutput, TEmit> = {\n\t[fnLivePatchMarker]: true\n\tstate: TOutput\n\temit: TEmit\n}\n\nexport function fnLivePatch<TOutput, TEmit>(\n\tstate: TOutput,\n\temit: TEmit\n): FnLivePatch<TOutput, TEmit> {\n\treturn { [fnLivePatchMarker]: true, state, emit }\n}\n\nfunction isFnLivePatch(value: unknown): value is FnLivePatch<unknown, unknown> {\n\treturn (\n\t\ttypeof value === 'object' && value !== null && fnLivePatchMarker in value\n\t)\n}\n\nexport type FnLiveConfig<\n\tTDef extends FnDefinition,\n\tTInput,\n\tTEventSchema extends ZodType,\n\tTOutput,\n\tTKey extends ProcedureKey<TDef>,\n\tTEmit = never,\n\tTErrors extends ErrorMap = Record<never, never>\n> = Omit<PublisherConfig, 'name'> &\n\tChannelQueueOptions & {\n\t\t/** Subscribe route name; default `${name}.live`. */\n\t\tname?: string\n\t\t/**\n\t\t * Validates reducer state without reapplying an output transform. Required with a\n\t\t * transformer. Its input may be looser than its output (e.g. branded IDs); it is\n\t\t * checked at runtime.\n\t\t */\n\t\tstateSchema?: Schema<unknown, TOutput>\n\t\t/** Validates patch payloads. Required when a transformer returns fnLivePatch. */\n\t\temitSchema?: Schema<unknown, TEmit>\n\t\t/** Optional access check before each update; idle streams keep their initial authorization. */\n\t\treauthorize?: AuthFn<TInput, FnContext<TDef, TKey>>\n\t\teventSchema: TEventSchema\n\t\tchannel: ChannelDefinition<\n\t\t\tTInput,\n\t\t\tz.output<TEventSchema>,\n\t\t\tFnContext<TDef, TKey>\n\t\t>\n\t\t/** Fold an event into the snapshot; without it every event re-runs the handler. */\n\t\ttransformerFn?: FnLiveConfigTransformer<\n\t\t\tTDef,\n\t\t\tTInput,\n\t\t\tTEventSchema,\n\t\t\tTOutput,\n\t\t\tTKey,\n\t\t\tTEmit,\n\t\t\tTErrors\n\t\t>\n\t\t/** Return false to skip an event. */\n\t\tshouldUpdate?: (\n\t\t\tparams: HandlerParams<TDef, TInput, TKey, TErrors> & {\n\t\t\t\tevent: z.output<TEventSchema>\n\t\t\t\tprevious: TOutput\n\t\t\t}\n\t\t) => MaybePromise<boolean>\n\t\tauthFn?: AuthFn<TInput, FnContext<TDef, TKey>>\n\t\t/** Log publish failures instead of throwing them into the publishing route. */\n\t\tsafePublish?: boolean\n\t\t/** Batch events arriving within this window into one snapshot update. */\n\t\tcoalesceMs?: number\n\t\t/** Maximum events collected in one coalescing batch (default 1000). */\n\t\tmaxBatchSize?: number\n\t\t/**\n\t\t * When a slow subscriber's queue overflows (drop-oldest), this marker is\n\t\t * enqueued INSTEAD of the dropped event so the client resyncs. Return\n\t\t * `null` to skip.\n\t\t */\n\t\toverflowMarker?: (input: TInput) => z.output<TEventSchema> | null\n\t\tsummary?: string\n\t\tdescription?: string\n\t} & (\n\t\t| { transformerFn?: undefined }\n\t\t| {\n\t\t\t\ttransformerFn: FnLiveConfigTransformer<\n\t\t\t\t\tTDef,\n\t\t\t\t\tTInput,\n\t\t\t\t\tTEventSchema,\n\t\t\t\t\tTOutput,\n\t\t\t\t\tTKey,\n\t\t\t\t\tTEmit,\n\t\t\t\t\tTErrors\n\t\t\t\t>\n\t\t\t\tstateSchema: Schema<unknown, TOutput>\n\t\t }\n\t) &\n\t([TEmit] extends [never] ? object : { emitSchema: Schema<unknown, TEmit> })\n\ntype FnLiveConfigTransformer<\n\tTDef extends FnDefinition,\n\tTInput,\n\tTEventSchema extends ZodType,\n\tTOutput,\n\tTKey extends ProcedureKey<TDef>,\n\tTEmit,\n\tTErrors extends ErrorMap\n> = (\n\tparams: HandlerParams<TDef, TInput, TKey, TErrors> & {\n\t\tevent: z.output<TEventSchema>\n\t\tprevious: TOutput\n\t\trerun: () => Promise<TOutput>\n\t}\n) => MaybePromise<TOutput | FnLivePatch<TOutput, TEmit> | undefined>\n\nexport type FnLiveReturn<\n\tTDef extends FnDefinition,\n\tTKey extends ProcedureKey<TDef>,\n\tTInput extends ObjectSchema,\n\tTOutputSchema extends Schema<unknown, unknown>,\n\tTOutput,\n\tTEventSchema extends ZodType,\n\tTEmit = never,\n\tTErrors extends ErrorMap = Record<never, never>\n> = {\n\tprocedure: FnProcedure<TDef, TKey, TInput, TOutputSchema, TErrors>\n\tsubscribe: FnProcedure<\n\t\tTDef,\n\t\tTKey,\n\t\tTInput,\n\t\tSchema<AsyncGenerator<TOutput | TEmit>, AsyncGenerator<TOutput | TEmit>>,\n\t\tTErrors\n\t>\n\tpublish: (event: z.input<TEventSchema>) => Promise<void>\n\tgetSubscriptionChannelName: (params: {\n\t\tinput: z.output<TInput>\n\t\tcontext: FnContext<TDef, TKey>\n\t}) => string\n\tgetPublishChannelName: (event: z.output<TEventSchema>) => string\n\t/** @deprecated Prefer the separate required-input resolver methods. */\n\tgetChannelName: (\n\t\tparams: Partial<z.output<TInput>> | Partial<z.output<TEventSchema>>,\n\t\tcontext?: FnContext<TDef, TKey>\n\t) => string\n}\n\n/**\n * A route plus a subscribe route that streams its result: the initial\n * snapshot, then an update for every event published on the channel.\n */\nexport interface FnLive<TDef extends FnDefinition> {\n\t<\n\t\tTInput extends ObjectSchema,\n\t\tTOutputSchema extends ZodType,\n\t\tTEventSchema extends ZodType,\n\t\tTKey extends ProcedureKey<TDef> = TDef['default'],\n\t\tTEmit = never,\n\t\tTErrors extends ErrorMap = Record<never, never>\n\t>(\n\t\toptions: {\n\t\t\tinput: TInput\n\t\t\toutput: TOutputSchema\n\t\t\thandler: (\n\t\t\t\tparams: HandlerParams<\n\t\t\t\t\tTDef,\n\t\t\t\t\tz.output<TInput>,\n\t\t\t\t\tNoInfer<TKey>,\n\t\t\t\t\tTErrors\n\t\t\t\t> & {\n\t\t\t\t\tpublish: (event: z.input<TEventSchema>) => Promise<void>\n\t\t\t\t}\n\t\t\t\t// The output schema parses what the handler returns: its input type.\n\t\t\t) => MaybePromise<z.input<TOutputSchema>>\n\t\t\tlive: FnLiveConfig<\n\t\t\t\tTDef,\n\t\t\t\tz.output<TInput>,\n\t\t\t\tTEventSchema,\n\t\t\t\tz.output<TOutputSchema>,\n\t\t\t\tNoInfer<TKey>,\n\t\t\t\tTEmit,\n\t\t\t\tTErrors\n\t\t\t>\n\t\t} & FnRouteOptions<TDef, TKey, z.output<TInput>, TErrors>\n\t): FnLiveReturn<\n\t\tTDef,\n\t\tTKey,\n\t\tTInput,\n\t\tTOutputSchema,\n\t\tz.output<TOutputSchema>,\n\t\tTEventSchema,\n\t\tTEmit,\n\t\tTErrors\n\t>\n\n\t<\n\t\tTInput extends ObjectSchema,\n\t\tTOutput,\n\t\tTEventSchema extends ZodType,\n\t\tTKey extends ProcedureKey<TDef> = TDef['default'],\n\t\tTEmit = never,\n\t\tTErrors extends ErrorMap = Record<never, never>\n\t>(\n\t\toptions: {\n\t\t\tinput: TInput\n\t\t\toutput?: undefined\n\t\t\thandler: (\n\t\t\t\tparams: HandlerParams<\n\t\t\t\t\tTDef,\n\t\t\t\t\tz.output<TInput>,\n\t\t\t\t\tNoInfer<TKey>,\n\t\t\t\t\tTErrors\n\t\t\t\t> & {\n\t\t\t\t\tpublish: (event: z.input<TEventSchema>) => Promise<void>\n\t\t\t\t}\n\t\t\t) => MaybePromise<TOutput>\n\t\t\tlive: FnLiveConfig<\n\t\t\t\tTDef,\n\t\t\t\tz.output<TInput>,\n\t\t\t\tTEventSchema,\n\t\t\t\tTOutput,\n\t\t\t\tNoInfer<TKey>,\n\t\t\t\tTEmit,\n\t\t\t\tTErrors\n\t\t\t>\n\t\t} & FnRouteOptions<TDef, TKey, z.output<TInput>, TErrors>\n\t): FnLiveReturn<\n\t\tTDef,\n\t\tTKey,\n\t\tTInput,\n\t\tSchema<TOutput, TOutput>,\n\t\tTOutput,\n\t\tTEventSchema,\n\t\tTEmit,\n\t\tTErrors\n\t>\n}\n\n/**\n * Fail a live subscription whose initial snapshot could not be built.\n *\n * An expected client failure - an `ORPCError` with a 4xx status, e.g. the\n * subscribed resource was not found or access was refused - reaches the\n * subscriber unchanged and is NOT logged as a server fault. Only 5xx and\n * unknown failures are logged. Unknown errors are wrapped as\n * `INTERNAL_SERVER_ERROR`.\n */\nexport function throwInitialSnapshotError(\n\terr: unknown,\n\tliveName: string,\n\tlogger: Pick<FnLogger, 'error'>,\n\t/** `createFn`'s `isExpectedError`; default: a 4xx `ORPCError`. */\n\tisExpected: (error: unknown) => boolean = (error) =>\n\t\terror instanceof ORPCError && error.status < 500\n): never {\n\tif (!isExpected(err)) {\n\t\tlogger.error('fnLive initial snapshot failed', {\n\t\t\tname: liveName,\n\t\t\terr: errorMessageOf(err)\n\t\t})\n\t}\n\tthrow toSnapshotError(err, liveName)\n}\n\n/** An `ORPCError` passes through; anything else becomes INTERNAL_SERVER_ERROR. */\nfunction toSnapshotError(\n\terr: unknown,\n\tliveName: string\n): ORPCError<string, unknown> {\n\tif (err instanceof ORPCError) return err\n\treturn new ORPCError('INTERNAL_SERVER_ERROR', {\n\t\tmessage: `Failed to load initial snapshot for ${liveName}`,\n\t\tcause: err\n\t})\n}\n\n/**\n * Drives a live subscription: yields the initial snapshot, then folds each\n * inbound event into the running snapshot via `apply`, yielding after every\n * change. With `coalesceMs`, events arriving within that window are batched so\n * bursty streams apply together.\n *\n * `apply` may return an {@link FnLivePatch} to keep the full snapshot as the\n * internal accumulator while yielding only the lighter `emit` payload.\n *\n * Invariant: there is never more than one outstanding `source.next()` read. On\n * a coalesce-window timeout the still-pending read is stashed in `pending` and\n * reused by the next `readNext()` - issuing a second concurrent read would\n * strand the in-flight event behind the next one (delivering it \"one behind\").\n */\nexport async function* streamLiveSnapshots<\n\tTEvent,\n\tTOutput,\n\tTEmit = never\n>(opts: {\n\tsource: AsyncIterator<TEvent>\n\t/** Maximum events retained in one coalescing batch. */\n\tmaxBatchSize?: number\n\tapplyBatch?: (\n\t\tevents: readonly TEvent[],\n\t\tprevious: TOutput\n\t) => MaybePromise<TOutput | undefined>\n\tinitial: TOutput\n\tcoalesceMs?: number | undefined\n\tapply: (\n\t\tevent: TEvent,\n\t\tprevious: TOutput\n\t) => MaybePromise<TOutput | FnLivePatch<TOutput, TEmit> | undefined>\n}): AsyncGenerator<TOutput | TEmit> {\n\tconst { source, initial, coalesceMs, apply } = opts\n\tconst maxBatchSize = positiveInteger(\n\t\topts.maxBatchSize ?? 1000,\n\t\t'maxBatchSize'\n\t)\n\tif (\n\t\tcoalesceMs !== undefined &&\n\t\t(!Number.isFinite(coalesceMs) || coalesceMs < 0)\n\t)\n\t\tthrow new RangeError('orpc-fn: coalesceMs must be finite and nonnegative')\n\n\tlet pending: Promise<IteratorResult<TEvent>> | null = null\n\tconst readNext = () => {\n\t\tconst read = pending ?? source.next()\n\t\tpending = null\n\t\treturn read\n\t}\n\n\tlet previous = initial\n\tyield previous\n\n\twhile (true) {\n\t\tconst current = await readNext()\n\t\tif (current.done) break\n\n\t\tconst batch: TEvent[] = [current.value]\n\n\t\tif (coalesceMs) {\n\t\t\tconst endAt = Date.now() + coalesceMs\n\t\t\twhile (Date.now() < endAt && batch.length < maxBatchSize) {\n\t\t\t\tconst remainingMs = endAt - Date.now()\n\t\t\t\tconst read = readNext()\n\t\t\t\tlet timer: ReturnType<typeof setTimeout> | undefined\n\t\t\t\tconst result = await Promise.race([\n\t\t\t\t\tread,\n\t\t\t\t\tnew Promise<typeof TIMEOUT>((resolve) => {\n\t\t\t\t\t\ttimer = setTimeout(resolve, remainingMs, TIMEOUT)\n\t\t\t\t\t})\n\t\t\t\t])\n\t\t\t\tclearTimeout(timer)\n\n\t\t\t\tif (result === TIMEOUT) {\n\t\t\t\t\t// Reuse the SAME in-flight read next iteration instead of starting\n\t\t\t\t\t// a new one - this is what prevents the \"one behind\" stranding.\n\t\t\t\t\tpending = read\n\t\t\t\t\tbreak\n\t\t\t\t}\n\n\t\t\t\tif (result.done) {\n\t\t\t\t\tpending = Promise.resolve(result)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tbatch.push(result.value)\n\t\t\t}\n\t\t}\n\n\t\tif (opts.applyBatch) {\n\t\t\tconst next = await opts.applyBatch(batch, previous)\n\t\t\tif (next !== undefined) {\n\t\t\t\tprevious = next\n\t\t\t\tyield previous\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tlet changed = false\n\t\tfor (const event of batch) {\n\t\t\tconst next = await apply(event, previous)\n\t\t\tif (next === undefined) continue\n\t\t\tif (isFnLivePatch(next)) {\n\t\t\t\tif (changed) {\n\t\t\t\t\tyield previous\n\t\t\t\t\tchanged = false\n\t\t\t\t}\n\t\t\t\tprevious = next.state as TOutput\n\t\t\t\tyield next.emit as TEmit\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tprevious = next\n\t\t\tchanged = true\n\t\t}\n\t\tif (changed) yield previous\n\t}\n}\n\ntype RuntimeParams = Record<string, unknown> & {\n\tinput: Record<string, unknown>\n\tcontext: unknown\n\tsignal: AbortSignal | undefined\n\tlogger: FnLogger\n\tcall: (procedure: AnyProcedure, input: unknown) => Promise<unknown>\n\t[RAW_INPUT]: unknown\n}\n\n/** `FnLiveConfig` with the generics erased: what the implementation reads. */\ntype RuntimeLiveConfig = Omit<ChannelOptions, 'name'> & {\n\tname?: string\n\tstateSchema?: AnySchema\n\temitSchema?: AnySchema\n\treauthorize?: AuthFn<Record<string, unknown>, unknown>\n\ttransformerFn?: (params: RuntimeParams & Record<string, unknown>) => unknown\n\tshouldUpdate?: (params: RuntimeParams & Record<string, unknown>) => unknown\n\tsafePublish?: boolean\n\tcoalesceMs?: number\n\tmaxBatchSize?: number\n\tsummary?: string\n\tdescription?: string\n}\n\n/**\n * @internal Wires `fnLive` onto an `fn` and channel runtime of the same\n * instance. `createFn` returns it typed as {@link FnLive}.\n */\nexport function createFnLive(runtime: {\n\t// biome-ignore lint/suspicious/noExplicitAny: runtime half of the typed `Fn`\n\tfn: (options: any) => AnyProcedure\n\tcreateChannel: (options: ChannelOptions) => Channel\n\tcreateLogger: (scope: string, span: SpanLike | undefined) => FnLogger\n\tisGuard: (option: string) => boolean\n}) {\n\tconst { fn, createChannel, isGuard } = runtime\n\tconst liveLogger = runtime.createLogger('fn-live', undefined)\n\n\treturn (\n\t\toptions: {\n\t\t\tlive: RuntimeLiveConfig\n\t\t\thandler: (params: RuntimeParams) => unknown\n\t\t\tinput: ZodType\n\t\t\toutput?: ZodType\n\t\t\tname: string\n\t\t\tprocedure?: string\n\t\t\tsummary?: string\n\t\t\tdescription?: string\n\t\t\ttags?: string[]\n\t\t} & Record<string, unknown>\n\t) => {\n\t\tconst { live, handler, input, output, name, ...routeConfig } = options\n\t\tif (live.transformerFn && !live.stateSchema)\n\t\t\tthrow new TypeError(\n\t\t\t\t'orpc-fn: live transformers require a stateSchema for parsed state'\n\t\t\t)\n\t\tif (\n\t\t\tlive.coalesceMs !== undefined &&\n\t\t\t(!Number.isFinite(live.coalesceMs) || live.coalesceMs < 0)\n\t\t)\n\t\t\tthrow new RangeError('orpc-fn: coalesceMs must be finite and nonnegative')\n\t\tif (live.maxBatchSize !== undefined)\n\t\t\tpositiveInteger(live.maxBatchSize, 'maxBatchSize')\n\t\tconst liveName = live.name ?? `${name}.live`\n\t\tconst liveSummary =\n\t\t\tlive.summary ?? `Live updates of ${routeConfig.summary ?? name}`\n\t\tconst liveDescription = live.description ?? routeConfig.description\n\n\t\t// `createChannel` reads only the channel keys of the live config.\n\t\tconst channel = createChannel({ ...live, name: liveName })\n\n\t\tconst publish = async (event: unknown) => {\n\t\t\tif (!live.safePublish) return channel.publish(event)\n\t\t\ttry {\n\t\t\t\tawait channel.publish(event)\n\t\t\t} catch (err) {\n\t\t\t\t// Live update failures must not roll back the route that emitted them,\n\t\t\t\t// but they should still be visible in logs.\n\t\t\t\tliveLogger.error('fnLive publish failed', {\n\t\t\t\t\tname: liveName,\n\t\t\t\t\terr: errorMessageOf(err)\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tconst runHandler = (params: RuntimeParams) =>\n\t\t\thandler({ ...params, publish })\n\n\t\tconst procedure = fn({\n\t\t\t...routeConfig,\n\t\t\tname,\n\t\t\tinput,\n\t\t\toutput,\n\t\t\thandler: runHandler\n\t\t})\n\n\t\tconst validate = async (schema: AnySchema, value: unknown) => {\n\t\t\tconst result = await schema['~standard'].validate(value)\n\t\t\tif (result.issues)\n\t\t\t\tthrow new ORPCError('INTERNAL_SERVER_ERROR', {\n\t\t\t\t\tmessage: 'Invalid live state or patch',\n\t\t\t\t\tcause: result.issues\n\t\t\t\t})\n\t\t\treturn result.value\n\t\t}\n\t\tconst runSnapshot = (params: RuntimeParams) =>\n\t\t\tparams.call(procedure, params[RAW_INPUT])\n\t\t// Generated streams inherit access policies and metadata; tool adapters reject streams.\n\n\t\tconst guardOptions = Object.fromEntries(\n\t\t\tObject.entries(routeConfig).filter(([option]) => isGuard(option))\n\t\t)\n\t\tconst subscribe = fn({\n\t\t\t...guardOptions,\n\t\t\tguardResolvers: routeConfig.guardResolvers,\n\t\t\terrors: routeConfig.errors,\n\t\t\tmeta: routeConfig.meta,\n\t\t\tstream: true,\n\t\t\tprocedure: routeConfig.procedure,\n\t\t\ttags: routeConfig.tags,\n\t\t\tname: liveName,\n\t\t\tmethod: 'GET',\n\t\t\tinput,\n\t\t\tsummary: liveSummary,\n\t\t\tdescription: liveDescription,\n\t\t\thandler: async function* (params: RuntimeParams) {\n\t\t\t\t// Authorize and subscribe before the snapshot: a refused subscriber\n\t\t\t\t// gets nothing, and events published while it loads are queued.\n\t\t\t\tconst subscription = await channel.open({\n\t\t\t\t\tinput: params.input,\n\t\t\t\t\tcontext: params.context,\n\t\t\t\t\tsignal: params.signal,\n\t\t\t\t\trecoverGaps: true\n\t\t\t\t})\n\t\t\t\ttry {\n\t\t\t\t\tif (subscription.isClosed()) return\n\t\t\t\t\tlet initial: unknown\n\t\t\t\t\ttry {\n\t\t\t\t\t\tinitial = await runSnapshot(params)\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t// `fn.completed` logs it, at the level `isExpectedError` picks.\n\t\t\t\t\t\tthrow toSnapshotError(err, liveName)\n\t\t\t\t\t}\n\n\t\t\t\t\tconst rerun = () => runSnapshot(params)\n\t\t\t\t\tconst authorize = async () => {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tlive.reauthorize &&\n\t\t\t\t\t\t\tlive.reauthorize !== true &&\n\t\t\t\t\t\t\t!(await live.reauthorize({\n\t\t\t\t\t\t\t\tinput: params.input,\n\t\t\t\t\t\t\t\tctx: params.context\n\t\t\t\t\t\t\t}))\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\tthrow new ORPCError('FORBIDDEN')\n\t\t\t\t\t}\n\t\t\t\t\tconst apply = async (event: unknown, previous: unknown) => {\n\t\t\t\t\t\tawait authorize()\n\t\t\t\t\t\tif (event === LIVE_GAP) return rerun()\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tlive.shouldUpdate &&\n\t\t\t\t\t\t\t!(await live.shouldUpdate({ ...params, event, previous }))\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\treturn undefined\n\t\t\t\t\t\tif (!live.transformerFn) return rerun()\n\t\t\t\t\t\tconst next = await live.transformerFn({\n\t\t\t\t\t\t\t...params,\n\t\t\t\t\t\t\tevent,\n\t\t\t\t\t\t\tprevious,\n\t\t\t\t\t\t\trerun\n\t\t\t\t\t\t})\n\t\t\t\t\t\tif (next === undefined) return undefined\n\t\t\t\t\t\tif (isFnLivePatch(next)) {\n\t\t\t\t\t\t\tif (!live.emitSchema)\n\t\t\t\t\t\t\t\tthrow new TypeError('orpc-fn: live patches require emitSchema')\n\t\t\t\t\t\t\treturn fnLivePatch(\n\t\t\t\t\t\t\t\tawait validate(live.stateSchema as AnySchema, next.state),\n\t\t\t\t\t\t\t\tawait validate(live.emitSchema, next.emit)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn validate(live.stateSchema as AnySchema, next)\n\t\t\t\t\t}\n\t\t\t\t\tconst applyBatch = live.transformerFn\n\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t: async (events: readonly unknown[], previous: unknown) => {\n\t\t\t\t\t\t\t\tawait authorize()\n\t\t\t\t\t\t\t\tlet invalidated = false\n\t\t\t\t\t\t\t\tfor (const event of events)\n\t\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t\tevent === LIVE_GAP ||\n\t\t\t\t\t\t\t\t\t\t!live.shouldUpdate ||\n\t\t\t\t\t\t\t\t\t\t(await live.shouldUpdate({ ...params, event, previous }))\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\tinvalidated = true\n\t\t\t\t\t\t\t\treturn invalidated ? rerun() : undefined\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\tyield* streamLiveSnapshots({\n\t\t\t\t\t\tsource: subscription.events,\n\t\t\t\t\t\tinitial,\n\t\t\t\t\t\tcoalesceMs: live.coalesceMs,\n\t\t\t\t\t\t...(live.maxBatchSize !== undefined\n\t\t\t\t\t\t\t? { maxBatchSize: live.maxBatchSize }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\tapply,\n\t\t\t\t\t\t...(applyBatch ? { applyBatch } : {})\n\t\t\t\t\t})\n\t\t\t\t} finally {\n\t\t\t\t\tsubscription.close()\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\n\t\treturn {\n\t\t\tprocedure,\n\t\t\tsubscribe,\n\t\t\tpublish,\n\t\t\tgetChannelName: channel.getChannelName,\n\t\t\tgetSubscriptionChannelName: channel.getSubscriptionChannelName,\n\t\t\tgetPublishChannelName: channel.getPublishChannelName\n\t\t}\n\t}\n}\n"]}
@@ -1,4 +1,4 @@
1
1
  export { type FnLive, type FnLiveConfig, type FnLivePatch, type FnLiveReturn, fnLivePatch, streamLiveSnapshots, throwInitialSnapshotError } from './fn-live.js';
2
- export { type AuthFn, type ChannelDefinition, type CreatePublisher, type CreatePubSub, createBoundedEventQueue, type FilterFn, type ObjectSchema, type Publisher, type PublisherConfig, type PublisherOptions, type PubSub, type PubSubOptions, type PubSubRuntimeOptions } from './pub-sub.js';
2
+ export { type AuthFn, type ChannelDefinition, type ChannelQueueOptions, type PubSubMetric, type CreatePublisher, type CreatePubSub, createBoundedEventQueue, type FilterFn, type ObjectSchema, type Publisher, type PublisherConfig, type PublisherOptions, type PubSub, type PubSubOptions, type PubSubRuntimeOptions } from './pub-sub.js';
3
3
  export { type BacklogOptions, backlogKey, type PubSubMessage, type PubSubTransport } from './transport.js';
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/live/index.ts"],"names":[],"mappings":"AACA,OAAO,EACN,KAAK,MAAM,EACX,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,WAAW,EACX,mBAAmB,EACnB,yBAAyB,EACzB,MAAM,cAAc,CAAA;AACrB,OAAO,EACN,KAAK,MAAM,EACX,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,uBAAuB,EACvB,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,MAAM,EACX,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,MAAM,cAAc,CAAA;AACrB,OAAO,EACN,KAAK,cAAc,EACnB,UAAU,EACV,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,MAAM,gBAAgB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/live/index.ts"],"names":[],"mappings":"AACA,OAAO,EACN,KAAK,MAAM,EACX,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,WAAW,EACX,mBAAmB,EACnB,yBAAyB,EACzB,MAAM,cAAc,CAAA;AACrB,OAAO,EACN,KAAK,MAAM,EACX,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,uBAAuB,EACvB,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,MAAM,EACX,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,MAAM,cAAc,CAAA;AACrB,OAAO,EACN,KAAK,cAAc,EACnB,UAAU,EACV,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,MAAM,gBAAgB,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/live/index.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,OAAO,EAKN,WAAW,EACX,mBAAmB,EACnB,yBAAyB,EACzB,MAAM,cAAc,CAAA;AACrB,OAAO,EAKN,uBAAuB,EASvB,MAAM,cAAc,CAAA;AACrB,OAAO,EAEN,UAAU,EAGV,MAAM,gBAAgB,CAAA","sourcesContent":["// `fnLive`, `createPubSub` and `createPublisher` come typed from `createFn`.\nexport {\n\ttype FnLive,\n\ttype FnLiveConfig,\n\ttype FnLivePatch,\n\ttype FnLiveReturn,\n\tfnLivePatch,\n\tstreamLiveSnapshots,\n\tthrowInitialSnapshotError\n} from './fn-live.js'\nexport {\n\ttype AuthFn,\n\ttype ChannelDefinition,\n\ttype CreatePublisher,\n\ttype CreatePubSub,\n\tcreateBoundedEventQueue,\n\ttype FilterFn,\n\ttype ObjectSchema,\n\ttype Publisher,\n\ttype PublisherConfig,\n\ttype PublisherOptions,\n\ttype PubSub,\n\ttype PubSubOptions,\n\ttype PubSubRuntimeOptions\n} from './pub-sub.js'\nexport {\n\ttype BacklogOptions,\n\tbacklogKey,\n\ttype PubSubMessage,\n\ttype PubSubTransport\n} from './transport.js'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/live/index.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,OAAO,EAKN,WAAW,EACX,mBAAmB,EACnB,yBAAyB,EACzB,MAAM,cAAc,CAAA;AACrB,OAAO,EAON,uBAAuB,EASvB,MAAM,cAAc,CAAA;AACrB,OAAO,EAEN,UAAU,EAGV,MAAM,gBAAgB,CAAA","sourcesContent":["// `fnLive`, `createPubSub` and `createPublisher` come typed from `createFn`.\nexport {\n\ttype FnLive,\n\ttype FnLiveConfig,\n\ttype FnLivePatch,\n\ttype FnLiveReturn,\n\tfnLivePatch,\n\tstreamLiveSnapshots,\n\tthrowInitialSnapshotError\n} from './fn-live.js'\nexport {\n\ttype AuthFn,\n\ttype ChannelDefinition,\n\ttype ChannelQueueOptions,\n\ttype PubSubMetric,\n\ttype CreatePublisher,\n\ttype CreatePubSub,\n\tcreateBoundedEventQueue,\n\ttype FilterFn,\n\ttype ObjectSchema,\n\ttype Publisher,\n\ttype PublisherConfig,\n\ttype PublisherOptions,\n\ttype PubSub,\n\ttype PubSubOptions,\n\ttype PubSubRuntimeOptions\n} from './pub-sub.js'\nexport {\n\ttype BacklogOptions,\n\tbacklogKey,\n\ttype PubSubMessage,\n\ttype PubSubTransport\n} from './transport.js'\n"]}
@@ -4,11 +4,14 @@ export interface IORedisLike {
4
4
  subscribe(...channels: string[]): Promise<unknown>;
5
5
  unsubscribe(...channels: string[]): Promise<unknown>;
6
6
  duplicate(): IORedisLike;
7
+ status?: string;
7
8
  disconnect(): void;
8
9
  on(event: 'message', listener: (channel: string, message: string) => void): unknown;
10
+ on(event: 'ready', listener: () => void): unknown;
9
11
  on(event: 'end', listener: () => void): unknown;
10
12
  on(event: 'error', listener: (error: Error) => void): unknown;
11
13
  off(event: 'message', listener: (channel: string, message: string) => void): unknown;
14
+ off(event: 'ready', listener: () => void): unknown;
12
15
  off(event: 'end', listener: () => void): unknown;
13
16
  off(event: 'error', listener: (error: Error) => void): unknown;
14
17
  }
@@ -24,6 +27,6 @@ export declare function ioredisTransport(client: IORedisLike, options?: {
24
27
  subscriber?: IORedisLike;
25
28
  onError?: (error: Error) => void;
26
29
  }): import("./transport.js").PubSubTransport & {
27
- close(): void;
30
+ close(): Promise<void>;
28
31
  };
29
32
  //# sourceMappingURL=ioredis.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ioredis.d.ts","sourceRoot":"","sources":["../../src/live/ioredis.ts"],"names":[],"mappings":"AAEA,iEAAiE;AACjE,MAAM,WAAW,WAAW;IAC3B,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAC1D,SAAS,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAClD,WAAW,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACpD,SAAS,IAAI,WAAW,CAAA;IACxB,UAAU,IAAI,IAAI,CAAA;IAClB,EAAE,CACD,KAAK,EAAE,SAAS,EAChB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,GAClD,OAAO,CAAA;IACV,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAA;IAC/C,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,CAAA;IAC7D,GAAG,CACF,KAAK,EAAE,SAAS,EAChB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,GAClD,OAAO,CAAA;IACV,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAA;IAChD,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,CAAA;CAC9D;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC/B,MAAM,EAAE,WAAW,EACnB,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,WAAW,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CAAO;;EAwC5E"}
1
+ {"version":3,"file":"ioredis.d.ts","sourceRoot":"","sources":["../../src/live/ioredis.ts"],"names":[],"mappings":"AAEA,iEAAiE;AACjE,MAAM,WAAW,WAAW;IAC3B,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAC1D,SAAS,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAClD,WAAW,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACpD,SAAS,IAAI,WAAW,CAAA;IACxB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,IAAI,IAAI,CAAA;IAClB,EAAE,CACD,KAAK,EAAE,SAAS,EAChB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,GAClD,OAAO,CAAA;IACV,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAA;IACjD,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAA;IAC/C,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,CAAA;IAC7D,GAAG,CACF,KAAK,EAAE,SAAS,EAChB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,GAClD,OAAO,CAAA;IACV,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAA;IAClD,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAA;IAChD,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,CAAA;CAC9D;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC/B,MAAM,EAAE,WAAW,EACnB,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,WAAW,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CAAO;;EAyD5E"}
@@ -15,10 +15,24 @@ export function ioredisTransport(client, options = {}) {
15
15
  const subscriber = options.subscriber ?? client.duplicate();
16
16
  const onMessage = (channel, message) => handlers.onMessage(channel, message);
17
17
  // Without a listener an ioredis 'error' event would crash the process.
18
- const onError = (error) => options.onError?.(error);
18
+ const onError = (error) => {
19
+ try {
20
+ options.onError?.(error);
21
+ }
22
+ catch {
23
+ /* Isolate telemetry. */
24
+ }
25
+ };
26
+ let readyOnce = subscriber.status === 'ready';
27
+ const onReady = () => {
28
+ if (readyOnce)
29
+ handlers.onReconnect();
30
+ readyOnce = true;
31
+ };
19
32
  // 'end' means ioredis stopped reconnecting.
20
33
  const onEnd = () => handlers.onLost(new Error('Redis subscriber connection ended'));
21
34
  const ours = new Set();
35
+ subscriber.on('ready', onReady);
22
36
  subscriber.on('message', onMessage);
23
37
  subscriber.on('error', onError);
24
38
  subscriber.on('end', onEnd);
@@ -27,19 +41,24 @@ export function ioredisTransport(client, options = {}) {
27
41
  ours.add(channel);
28
42
  return subscriber.subscribe(channel);
29
43
  },
44
+ resubscribe: (channel) => subscriber.subscribe(channel),
30
45
  unsubscribe: (channel) => {
31
46
  ours.delete(channel);
32
47
  return subscriber.unsubscribe(channel);
33
48
  },
34
49
  close() {
35
50
  // Detach first: a given subscriber outlives this transport's use.
51
+ subscriber.off('ready', onReady);
36
52
  subscriber.off('message', onMessage);
37
53
  subscriber.off('end', onEnd);
38
54
  if (owned)
39
55
  return subscriber.disconnect();
40
56
  subscriber.off('error', onError);
41
57
  if (ours.size > 0) {
42
- void subscriber.unsubscribe(...ours).catch(() => { });
58
+ return subscriber
59
+ .unsubscribe(...ours)
60
+ .then(() => { })
61
+ .catch(() => { });
43
62
  }
44
63
  }
45
64
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ioredis.js","sourceRoot":"","sources":["../../src/live/ioredis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAuBjD;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAC/B,MAAmB,EACnB,OAAO,GAAmE,EAAE;IAE5E,OAAO,oBAAoB,CAAC;QAC3B,IAAI,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC;QACtD,KAAK,CAAC,iBAAiB,CAAC,QAAQ;YAC/B,MAAM,KAAK,GAAG,CAAC,OAAO,CAAC,UAAU,CAAA;YACjC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,MAAM,CAAC,SAAS,EAAE,CAAA;YAC3D,MAAM,SAAS,GAAG,CAAC,OAAe,EAAE,OAAe,EAAE,EAAE,CACtD,QAAQ,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;YACrC,uEAAuE;YACvE,MAAM,OAAO,GAAG,CAAC,KAAY,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAA;YAC1D,4CAA4C;YAC5C,MAAM,KAAK,GAAG,GAAG,EAAE,CAClB,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC,CAAA;YAChE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;YAC9B,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;YACnC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;YAC/B,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;YAC3B,OAAO;gBACN,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE;oBACtB,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;oBACjB,OAAO,UAAU,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;gBACrC,CAAC;gBACD,WAAW,EAAE,CAAC,OAAO,EAAE,EAAE;oBACxB,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;oBACpB,OAAO,UAAU,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;gBACvC,CAAC;gBACD,KAAK;oBACJ,kEAAkE;oBAClE,UAAU,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;oBACpC,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;oBAC5B,IAAI,KAAK;wBAAE,OAAO,UAAU,CAAC,UAAU,EAAE,CAAA;oBACzC,UAAU,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;oBAChC,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;wBACnB,KAAK,UAAU,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;oBACrD,CAAC;gBACF,CAAC;aACD,CAAA;QACF,CAAC;KACD,CAAC,CAAA;AACH,CAAC","sourcesContent":["import { createRedisTransport } from './redis.js'\n\n/** The part of an ioredis `Redis` client this transport uses. */\nexport interface IORedisLike {\n\tcall(command: string, ...args: string[]): Promise<unknown>\n\tsubscribe(...channels: string[]): Promise<unknown>\n\tunsubscribe(...channels: string[]): Promise<unknown>\n\tduplicate(): IORedisLike\n\tdisconnect(): void\n\ton(\n\t\tevent: 'message',\n\t\tlistener: (channel: string, message: string) => void\n\t): unknown\n\ton(event: 'end', listener: () => void): unknown\n\ton(event: 'error', listener: (error: Error) => void): unknown\n\toff(\n\t\tevent: 'message',\n\t\tlistener: (channel: string, message: string) => void\n\t): unknown\n\toff(event: 'end', listener: () => void): unknown\n\toff(event: 'error', listener: (error: Error) => void): unknown\n}\n\n/**\n * `PubSubTransport` for ioredis. Subscriptions use a dedicated connection\n * (`client.duplicate()` unless `subscriber` is given); ioredis re-subscribes\n * after reconnects itself (`autoResubscribe`), so no `resubscribe` is needed. `onError` receives connection\n * errors that ioredis is already retrying.\n *\n * Call `close()` on shutdown to disconnect the subscriber it created.\n */\nexport function ioredisTransport(\n\tclient: IORedisLike,\n\toptions: { subscriber?: IORedisLike; onError?: (error: Error) => void } = {}\n) {\n\treturn createRedisTransport({\n\t\tsend: (command, args) => client.call(command, ...args),\n\t\tasync connectSubscriber(handlers) {\n\t\t\tconst owned = !options.subscriber\n\t\t\tconst subscriber = options.subscriber ?? client.duplicate()\n\t\t\tconst onMessage = (channel: string, message: string) =>\n\t\t\t\thandlers.onMessage(channel, message)\n\t\t\t// Without a listener an ioredis 'error' event would crash the process.\n\t\t\tconst onError = (error: Error) => options.onError?.(error)\n\t\t\t// 'end' means ioredis stopped reconnecting.\n\t\t\tconst onEnd = () =>\n\t\t\t\thandlers.onLost(new Error('Redis subscriber connection ended'))\n\t\t\tconst ours = new Set<string>()\n\t\t\tsubscriber.on('message', onMessage)\n\t\t\tsubscriber.on('error', onError)\n\t\t\tsubscriber.on('end', onEnd)\n\t\t\treturn {\n\t\t\t\tsubscribe: (channel) => {\n\t\t\t\t\tours.add(channel)\n\t\t\t\t\treturn subscriber.subscribe(channel)\n\t\t\t\t},\n\t\t\t\tunsubscribe: (channel) => {\n\t\t\t\t\tours.delete(channel)\n\t\t\t\t\treturn subscriber.unsubscribe(channel)\n\t\t\t\t},\n\t\t\t\tclose() {\n\t\t\t\t\t// Detach first: a given subscriber outlives this transport's use.\n\t\t\t\t\tsubscriber.off('message', onMessage)\n\t\t\t\t\tsubscriber.off('end', onEnd)\n\t\t\t\t\tif (owned) return subscriber.disconnect()\n\t\t\t\t\tsubscriber.off('error', onError)\n\t\t\t\t\tif (ours.size > 0) {\n\t\t\t\t\t\tvoid subscriber.unsubscribe(...ours).catch(() => {})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n}\n"]}
1
+ {"version":3,"file":"ioredis.js","sourceRoot":"","sources":["../../src/live/ioredis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AA0BjD;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAC/B,MAAmB,EACnB,OAAO,GAAmE,EAAE;IAE5E,OAAO,oBAAoB,CAAC;QAC3B,IAAI,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC;QACtD,KAAK,CAAC,iBAAiB,CAAC,QAAQ;YAC/B,MAAM,KAAK,GAAG,CAAC,OAAO,CAAC,UAAU,CAAA;YACjC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,MAAM,CAAC,SAAS,EAAE,CAAA;YAC3D,MAAM,SAAS,GAAG,CAAC,OAAe,EAAE,OAAe,EAAE,EAAE,CACtD,QAAQ,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;YACrC,uEAAuE;YACvE,MAAM,OAAO,GAAG,CAAC,KAAY,EAAE,EAAE;gBAChC,IAAI,CAAC;oBACJ,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAA;gBACzB,CAAC;gBAAC,MAAM,CAAC;oBACR,wBAAwB;gBACzB,CAAC;YACF,CAAC,CAAA;YACD,IAAI,SAAS,GAAG,UAAU,CAAC,MAAM,KAAK,OAAO,CAAA;YAC7C,MAAM,OAAO,GAAG,GAAG,EAAE;gBACpB,IAAI,SAAS;oBAAE,QAAQ,CAAC,WAAW,EAAE,CAAA;gBACrC,SAAS,GAAG,IAAI,CAAA;YACjB,CAAC,CAAA;YACD,4CAA4C;YAC5C,MAAM,KAAK,GAAG,GAAG,EAAE,CAClB,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC,CAAA;YAChE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;YAC9B,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;YAC/B,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;YACnC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;YAC/B,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;YAC3B,OAAO;gBACN,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE;oBACtB,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;oBACjB,OAAO,UAAU,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;gBACrC,CAAC;gBACD,WAAW,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,OAAO,CAAC;gBAC/D,WAAW,EAAE,CAAC,OAAO,EAAE,EAAE;oBACxB,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;oBACpB,OAAO,UAAU,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;gBACvC,CAAC;gBACD,KAAK;oBACJ,kEAAkE;oBAClE,UAAU,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;oBAChC,UAAU,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;oBACpC,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;oBAC5B,IAAI,KAAK;wBAAE,OAAO,UAAU,CAAC,UAAU,EAAE,CAAA;oBACzC,UAAU,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;oBAChC,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;wBACnB,OAAO,UAAU;6BACf,WAAW,CAAC,GAAG,IAAI,CAAC;6BACpB,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;6BACd,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;oBAClB,CAAC;gBACF,CAAC;aACD,CAAA;QACF,CAAC;KACD,CAAC,CAAA;AACH,CAAC","sourcesContent":["import { createRedisTransport } from './redis.js'\n\n/** The part of an ioredis `Redis` client this transport uses. */\nexport interface IORedisLike {\n\tcall(command: string, ...args: string[]): Promise<unknown>\n\tsubscribe(...channels: string[]): Promise<unknown>\n\tunsubscribe(...channels: string[]): Promise<unknown>\n\tduplicate(): IORedisLike\n\tstatus?: string\n\tdisconnect(): void\n\ton(\n\t\tevent: 'message',\n\t\tlistener: (channel: string, message: string) => void\n\t): unknown\n\ton(event: 'ready', listener: () => void): unknown\n\ton(event: 'end', listener: () => void): unknown\n\ton(event: 'error', listener: (error: Error) => void): unknown\n\toff(\n\t\tevent: 'message',\n\t\tlistener: (channel: string, message: string) => void\n\t): unknown\n\toff(event: 'ready', listener: () => void): unknown\n\toff(event: 'end', listener: () => void): unknown\n\toff(event: 'error', listener: (error: Error) => void): unknown\n}\n\n/**\n * `PubSubTransport` for ioredis. Subscriptions use a dedicated connection\n * (`client.duplicate()` unless `subscriber` is given); ioredis re-subscribes\n * after reconnects itself (`autoResubscribe`), so no `resubscribe` is needed. `onError` receives connection\n * errors that ioredis is already retrying.\n *\n * Call `close()` on shutdown to disconnect the subscriber it created.\n */\nexport function ioredisTransport(\n\tclient: IORedisLike,\n\toptions: { subscriber?: IORedisLike; onError?: (error: Error) => void } = {}\n) {\n\treturn createRedisTransport({\n\t\tsend: (command, args) => client.call(command, ...args),\n\t\tasync connectSubscriber(handlers) {\n\t\t\tconst owned = !options.subscriber\n\t\t\tconst subscriber = options.subscriber ?? client.duplicate()\n\t\t\tconst onMessage = (channel: string, message: string) =>\n\t\t\t\thandlers.onMessage(channel, message)\n\t\t\t// Without a listener an ioredis 'error' event would crash the process.\n\t\t\tconst onError = (error: Error) => {\n\t\t\t\ttry {\n\t\t\t\t\toptions.onError?.(error)\n\t\t\t\t} catch {\n\t\t\t\t\t/* Isolate telemetry. */\n\t\t\t\t}\n\t\t\t}\n\t\t\tlet readyOnce = subscriber.status === 'ready'\n\t\t\tconst onReady = () => {\n\t\t\t\tif (readyOnce) handlers.onReconnect()\n\t\t\t\treadyOnce = true\n\t\t\t}\n\t\t\t// 'end' means ioredis stopped reconnecting.\n\t\t\tconst onEnd = () =>\n\t\t\t\thandlers.onLost(new Error('Redis subscriber connection ended'))\n\t\t\tconst ours = new Set<string>()\n\t\t\tsubscriber.on('ready', onReady)\n\t\t\tsubscriber.on('message', onMessage)\n\t\t\tsubscriber.on('error', onError)\n\t\t\tsubscriber.on('end', onEnd)\n\t\t\treturn {\n\t\t\t\tsubscribe: (channel) => {\n\t\t\t\t\tours.add(channel)\n\t\t\t\t\treturn subscriber.subscribe(channel)\n\t\t\t\t},\n\t\t\t\tresubscribe: (channel: string) => subscriber.subscribe(channel),\n\t\t\t\tunsubscribe: (channel) => {\n\t\t\t\t\tours.delete(channel)\n\t\t\t\t\treturn subscriber.unsubscribe(channel)\n\t\t\t\t},\n\t\t\t\tclose() {\n\t\t\t\t\t// Detach first: a given subscriber outlives this transport's use.\n\t\t\t\t\tsubscriber.off('ready', onReady)\n\t\t\t\t\tsubscriber.off('message', onMessage)\n\t\t\t\t\tsubscriber.off('end', onEnd)\n\t\t\t\t\tif (owned) return subscriber.disconnect()\n\t\t\t\t\tsubscriber.off('error', onError)\n\t\t\t\t\tif (ours.size > 0) {\n\t\t\t\t\t\treturn subscriber\n\t\t\t\t\t\t\t.unsubscribe(...ours)\n\t\t\t\t\t\t\t.then(() => {})\n\t\t\t\t\t\t\t.catch(() => {})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n}\n"]}
@@ -0,0 +1,7 @@
1
+ /** Internal control message: live queries reload after loss; raw streams fail. */
2
+ export declare const LIVE_GAP: unique symbol;
3
+ export declare function positiveInteger(value: number, name: string): number;
4
+ export declare function safely(callback: (() => unknown) | undefined): void;
5
+ /** Abort and timeout only stop waiting; callers release late transport results. */
6
+ export declare function waitFor<T>(promise: Promise<T>, timeoutMs: number, signal: AbortSignal): Promise<T>;
7
+ //# sourceMappingURL=lifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../src/live/lifecycle.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,eAAO,MAAM,QAAQ,eAA4B,CAAA;AAEjD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAInE;AAED,wBAAgB,MAAM,CAAC,QAAQ,EAAE,CAAC,MAAM,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,CAMlE;AAED,mFAAmF;AACnF,wBAAsB,OAAO,CAAC,CAAC,EAC9B,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,WAAW,GACjB,OAAO,CAAC,CAAC,CAAC,CAqBZ"}
@@ -0,0 +1,36 @@
1
+ /** Internal control message: live queries reload after loss; raw streams fail. */
2
+ export const LIVE_GAP = Symbol('orpc-fn.liveGap');
3
+ export function positiveInteger(value, name) {
4
+ if (!Number.isSafeInteger(value) || value <= 0)
5
+ throw new RangeError(`orpc-fn: ${name} must be a positive safe integer`);
6
+ return value;
7
+ }
8
+ export function safely(callback) {
9
+ try {
10
+ callback?.();
11
+ }
12
+ catch {
13
+ /* Observability must not disrupt delivery. */
14
+ }
15
+ }
16
+ /** Abort and timeout only stop waiting; callers release late transport results. */
17
+ export async function waitFor(promise, timeoutMs, signal) {
18
+ signal.throwIfAborted();
19
+ let timer;
20
+ let abort = () => { };
21
+ try {
22
+ return await Promise.race([
23
+ promise,
24
+ new Promise((_resolve, reject) => {
25
+ abort = () => reject(signal.reason);
26
+ signal.addEventListener('abort', abort, { once: true });
27
+ timer = setTimeout(() => reject(new Error('orpc-fn: subscription initialization timed out')), timeoutMs);
28
+ })
29
+ ]);
30
+ }
31
+ finally {
32
+ clearTimeout(timer);
33
+ signal.removeEventListener('abort', abort);
34
+ }
35
+ }
36
+ //# sourceMappingURL=lifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../src/live/lifecycle.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAA;AAEjD,MAAM,UAAU,eAAe,CAAC,KAAa,EAAE,IAAY;IAC1D,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;QAC7C,MAAM,IAAI,UAAU,CAAC,YAAY,IAAI,kCAAkC,CAAC,CAAA;IACzE,OAAO,KAAK,CAAA;AACb,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,QAAqC;IAC3D,IAAI,CAAC;QACJ,QAAQ,EAAE,EAAE,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACR,8CAA8C;IAC/C,CAAC;AACF,CAAC;AAED,mFAAmF;AACnF,MAAM,CAAC,KAAK,UAAU,OAAO,CAC5B,OAAmB,EACnB,SAAiB,EACjB,MAAmB;IAEnB,MAAM,CAAC,cAAc,EAAE,CAAA;IACvB,IAAI,KAAgD,CAAA;IACpD,IAAI,KAAK,GAAG,GAAG,EAAE,GAAE,CAAC,CAAA;IACpB,IAAI,CAAC;QACJ,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC;YACzB,OAAO;YACP,IAAI,OAAO,CAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE;gBACvC,KAAK,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;gBACnC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;gBACvD,KAAK,GAAG,UAAU,CACjB,GAAG,EAAE,CACJ,MAAM,CAAC,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC,EACpE,SAAS,CACT,CAAA;YACF,CAAC,CAAC;SACF,CAAC,CAAA;IACH,CAAC;YAAS,CAAC;QACV,YAAY,CAAC,KAAK,CAAC,CAAA;QACnB,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;IAC3C,CAAC;AACF,CAAC","sourcesContent":["/** Internal control message: live queries reload after loss; raw streams fail. */\nexport const LIVE_GAP = Symbol('orpc-fn.liveGap')\n\nexport function positiveInteger(value: number, name: string): number {\n\tif (!Number.isSafeInteger(value) || value <= 0)\n\t\tthrow new RangeError(`orpc-fn: ${name} must be a positive safe integer`)\n\treturn value\n}\n\nexport function safely(callback: (() => unknown) | undefined): void {\n\ttry {\n\t\tcallback?.()\n\t} catch {\n\t\t/* Observability must not disrupt delivery. */\n\t}\n}\n\n/** Abort and timeout only stop waiting; callers release late transport results. */\nexport async function waitFor<T>(\n\tpromise: Promise<T>,\n\ttimeoutMs: number,\n\tsignal: AbortSignal\n): Promise<T> {\n\tsignal.throwIfAborted()\n\tlet timer: ReturnType<typeof setTimeout> | undefined\n\tlet abort = () => {}\n\ttry {\n\t\treturn await Promise.race([\n\t\t\tpromise,\n\t\t\tnew Promise<never>((_resolve, reject) => {\n\t\t\t\tabort = () => reject(signal.reason)\n\t\t\t\tsignal.addEventListener('abort', abort, { once: true })\n\t\t\t\ttimer = setTimeout(\n\t\t\t\t\t() =>\n\t\t\t\t\t\treject(new Error('orpc-fn: subscription initialization timed out')),\n\t\t\t\t\ttimeoutMs\n\t\t\t\t)\n\t\t\t})\n\t\t])\n\t} finally {\n\t\tclearTimeout(timer)\n\t\tsignal.removeEventListener('abort', abort)\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/live/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAErD;;;GAGG;AACH,wBAAgB,eAAe,IAAI,eAAe,GAAG;IACpD,oDAAoD;IACpD,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAA;CACtC,CAwCA"}
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/live/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAErD;;;GAGG;AACH,wBAAgB,eAAe,IAAI,eAAe,GAAG;IACpD,oDAAoD;IACpD,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAA;CACtC,CA4CA"}
@@ -6,6 +6,10 @@ export function memoryTransport() {
6
6
  const listeners = new Map();
7
7
  const backlogs = new Map();
8
8
  return {
9
+ async close() {
10
+ listeners.clear();
11
+ backlogs.clear();
12
+ },
9
13
  async publish(messages, backlog) {
10
14
  for (const { channel, payload } of messages) {
11
15
  if (backlog) {
@@ -1 +1 @@
1
- {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/live/memory.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,eAAe;IAI9B,MAAM,SAAS,GAAG,IAAI,GAAG,EAA0C,CAAA;IACnE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkD,CAAA;IAE1E,OAAO;QACN,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO;YAC9B,KAAK,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,QAAQ,EAAE,CAAC;gBAC7C,IAAI,OAAO,EAAE,CAAC;oBACb,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;oBACrC,MAAM,KAAK,GACV,OAAO,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;oBAC/D,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;oBACnB,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;oBACzD,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE;wBACrB,KAAK;wBACL,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI;qBACjD,CAAC,CAAA;gBACH,CAAC;gBACD,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;oBAC5D,cAAc,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAA;gBACxC,CAAC;YACF,CAAC;QACF,CAAC;QACD,KAAK,CAAC,WAAW,CAAC,OAAO;YACxB,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YACrC,OAAO,OAAO,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QAC3E,CAAC;QACD,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,QAAQ;YAChC,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,GAAG,EAAE,CAAA;YAC/C,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;YAC3B,sEAAsE;YACtE,MAAM,KAAK,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;YACpD,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;YACd,OAAO,KAAK,IAAI,EAAE;gBACjB,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;gBACjB,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC;oBAAE,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;YAC9C,CAAC,CAAA;QACF,CAAC;QACD,aAAa,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,IAAI,CAAC;KAC7D,CAAA;AACF,CAAC","sourcesContent":["import type { PubSubTransport } from './transport.js'\n\n/**\n * In-process transport for tests and single-process development. Delivery is\n * asynchronous (a microtask), like a real broker.\n */\nexport function memoryTransport(): PubSubTransport & {\n\t/** Active listeners per channel, for assertions. */\n\tlistenerCount(channel: string): number\n} {\n\tconst listeners = new Map<string, Set<(payload: string) => void>>()\n\tconst backlogs = new Map<string, { items: string[]; expiresAt: number }>()\n\n\treturn {\n\t\tasync publish(messages, backlog) {\n\t\t\tfor (const { channel, payload } of messages) {\n\t\t\t\tif (backlog) {\n\t\t\t\t\tconst current = backlogs.get(channel)\n\t\t\t\t\tconst items =\n\t\t\t\t\t\tcurrent && current.expiresAt > Date.now() ? current.items : []\n\t\t\t\t\titems.push(payload)\n\t\t\t\t\titems.splice(0, Math.max(0, items.length - backlog.size))\n\t\t\t\t\tbacklogs.set(channel, {\n\t\t\t\t\t\titems,\n\t\t\t\t\t\texpiresAt: Date.now() + backlog.ttlSeconds * 1000\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tfor (const listener of [...(listeners.get(channel) ?? [])]) {\n\t\t\t\t\tqueueMicrotask(() => listener(payload))\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tasync readBacklog(channel) {\n\t\t\tconst backlog = backlogs.get(channel)\n\t\t\treturn backlog && backlog.expiresAt > Date.now() ? [...backlog.items] : []\n\t\t},\n\t\tasync subscribe(channel, listener) {\n\t\t\tconst set = listeners.get(channel) ?? new Set()\n\t\t\tlisteners.set(channel, set)\n\t\t\t// Wrap so the same listener can subscribe twice and unsubscribe once.\n\t\t\tconst entry = (payload: string) => listener(payload)\n\t\t\tset.add(entry)\n\t\t\treturn async () => {\n\t\t\t\tset.delete(entry)\n\t\t\t\tif (set.size === 0) listeners.delete(channel)\n\t\t\t}\n\t\t},\n\t\tlistenerCount: (channel) => listeners.get(channel)?.size ?? 0\n\t}\n}\n"]}
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/live/memory.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,eAAe;IAI9B,MAAM,SAAS,GAAG,IAAI,GAAG,EAA0C,CAAA;IACnE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkD,CAAA;IAE1E,OAAO;QACN,KAAK,CAAC,KAAK;YACV,SAAS,CAAC,KAAK,EAAE,CAAA;YACjB,QAAQ,CAAC,KAAK,EAAE,CAAA;QACjB,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO;YAC9B,KAAK,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,QAAQ,EAAE,CAAC;gBAC7C,IAAI,OAAO,EAAE,CAAC;oBACb,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;oBACrC,MAAM,KAAK,GACV,OAAO,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;oBAC/D,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;oBACnB,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;oBACzD,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE;wBACrB,KAAK;wBACL,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI;qBACjD,CAAC,CAAA;gBACH,CAAC;gBACD,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;oBAC5D,cAAc,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAA;gBACxC,CAAC;YACF,CAAC;QACF,CAAC;QACD,KAAK,CAAC,WAAW,CAAC,OAAO;YACxB,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YACrC,OAAO,OAAO,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QAC3E,CAAC;QACD,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,QAAQ;YAChC,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,GAAG,EAAE,CAAA;YAC/C,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;YAC3B,sEAAsE;YACtE,MAAM,KAAK,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;YACpD,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;YACd,OAAO,KAAK,IAAI,EAAE;gBACjB,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;gBACjB,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC;oBAAE,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;YAC9C,CAAC,CAAA;QACF,CAAC;QACD,aAAa,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,IAAI,CAAC;KAC7D,CAAA;AACF,CAAC","sourcesContent":["import type { PubSubTransport } from './transport.js'\n\n/**\n * In-process transport for tests and single-process development. Delivery is\n * asynchronous (a microtask), like a real broker.\n */\nexport function memoryTransport(): PubSubTransport & {\n\t/** Active listeners per channel, for assertions. */\n\tlistenerCount(channel: string): number\n} {\n\tconst listeners = new Map<string, Set<(payload: string) => void>>()\n\tconst backlogs = new Map<string, { items: string[]; expiresAt: number }>()\n\n\treturn {\n\t\tasync close() {\n\t\t\tlisteners.clear()\n\t\t\tbacklogs.clear()\n\t\t},\n\t\tasync publish(messages, backlog) {\n\t\t\tfor (const { channel, payload } of messages) {\n\t\t\t\tif (backlog) {\n\t\t\t\t\tconst current = backlogs.get(channel)\n\t\t\t\t\tconst items =\n\t\t\t\t\t\tcurrent && current.expiresAt > Date.now() ? current.items : []\n\t\t\t\t\titems.push(payload)\n\t\t\t\t\titems.splice(0, Math.max(0, items.length - backlog.size))\n\t\t\t\t\tbacklogs.set(channel, {\n\t\t\t\t\t\titems,\n\t\t\t\t\t\texpiresAt: Date.now() + backlog.ttlSeconds * 1000\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tfor (const listener of [...(listeners.get(channel) ?? [])]) {\n\t\t\t\t\tqueueMicrotask(() => listener(payload))\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tasync readBacklog(channel) {\n\t\t\tconst backlog = backlogs.get(channel)\n\t\t\treturn backlog && backlog.expiresAt > Date.now() ? [...backlog.items] : []\n\t\t},\n\t\tasync subscribe(channel, listener) {\n\t\t\tconst set = listeners.get(channel) ?? new Set()\n\t\t\tlisteners.set(channel, set)\n\t\t\t// Wrap so the same listener can subscribe twice and unsubscribe once.\n\t\t\tconst entry = (payload: string) => listener(payload)\n\t\t\tset.add(entry)\n\t\t\treturn async () => {\n\t\t\t\tset.delete(entry)\n\t\t\t\tif (set.size === 0) listeners.delete(channel)\n\t\t\t}\n\t\t},\n\t\tlistenerCount: (channel) => listeners.get(channel)?.size ?? 0\n\t}\n}\n"]}
@@ -2,7 +2,7 @@ import type { Schema } from '@orpc/contract';
2
2
  import type { ZodObject, ZodRawShape, ZodType, z } from 'zod';
3
3
  import type { FnLogger } from '../logger.js';
4
4
  import { type SpanLike, type Tracing } from '../otel.js';
5
- import type { BuildProcedure, FnContext, FnDefinition, FnProcedure, MaybePromise, ProcedureKey, ProcedureOption } from '../types.js';
5
+ import type { GuardOptions, FnContext, FnDefinition, FnProcedure, FnRouteOptions, MaybePromise, ProcedureKey, ProcedureOption } from '../types.js';
6
6
  import type { PubSubTransport } from './transport.js';
7
7
  /** Any Zod object schema, including `.strict()`, `.passthrough()` and `.catchall()`. */
8
8
  export type ObjectSchema = ZodObject<ZodRawShape, z.core.$ZodObjectConfig>;
@@ -10,7 +10,13 @@ export type ObjectSchema = ZodObject<ZodRawShape, z.core.$ZodObjectConfig>;
10
10
  * A static channel name, or one derived from (partial) subscriber input or
11
11
  * event data.
12
12
  */
13
- export type ChannelDefinition<TInput, TEventData, TContext = unknown> = string | ((params: Partial<TInput> | Partial<TEventData>, context?: TContext) => string);
13
+ export type ChannelDefinition<TInput, TEventData, TContext = unknown> = string | {
14
+ subscribe: (params: {
15
+ input: TInput;
16
+ context: TContext;
17
+ }) => string;
18
+ publish: (event: TEventData) => string;
19
+ } | ((params: Partial<TInput> | Partial<TEventData>, context?: TContext) => string);
14
20
  /** Decides whether one event reaches one subscriber. */
15
21
  export type FilterFn<TInput, TEventData> = (params: {
16
22
  input: TInput;
@@ -43,7 +49,33 @@ export type PublisherConfig = {
43
49
  */
44
50
  mirrorChannel?: string;
45
51
  };
46
- export type PubSubOptions<TDef extends FnDefinition, TInputSchema extends ObjectSchema, TEventSchema extends ZodType, TKey extends ProcedureKey<TDef>> = PublisherConfig & {
52
+ /** Per-definition overrides of the factory queue bounds. */
53
+ export type ChannelQueueOptions = {
54
+ maxQueueSize?: number;
55
+ maxIngressSize?: number;
56
+ maxReplaySize?: number;
57
+ };
58
+ /** Synchronous observational events; failures cannot interrupt delivery. */
59
+ export type PubSubMetric = {
60
+ name: string;
61
+ channel: string;
62
+ } & ({
63
+ type: 'queue';
64
+ stage: 'ingress' | 'replay' | 'delivery';
65
+ depth: number;
66
+ limit: number;
67
+ } | {
68
+ type: 'drop';
69
+ stage: 'ingress' | 'replay' | 'delivery';
70
+ count: number;
71
+ } | {
72
+ type: 'reconnect';
73
+ } | {
74
+ type: 'parseError';
75
+ stage: 'ingress' | 'replay';
76
+ error: unknown;
77
+ });
78
+ export type PubSubOptions<TDef extends FnDefinition, TInputSchema extends ObjectSchema, TEventSchema extends ZodType, TKey extends ProcedureKey<TDef>> = PublisherConfig & ChannelQueueOptions & {
47
79
  channel: ChannelDefinition<z.output<TInputSchema>, z.output<TEventSchema>, FnContext<TDef, TKey>>;
48
80
  /** What the subscriber provides. */
49
81
  inputSchema: TInputSchema;
@@ -68,11 +100,16 @@ export type PubSub<TDef extends FnDefinition, TInputSchema extends ObjectSchema,
68
100
  publish: (data: z.input<TEventSchema>) => Promise<void>;
69
101
  /** Publish a batch in one atomic round-trip; items may target different channels. */
70
102
  publishMany: (items: readonly z.input<TEventSchema>[]) => Promise<void>;
103
+ getSubscriptionChannelName: (params: {
104
+ input: z.output<TInputSchema>;
105
+ context: FnContext<TDef, TKey>;
106
+ }) => string;
107
+ getPublishChannelName: (event: z.output<TEventSchema>) => string;
108
+ /** @deprecated Prefer the separate required-input resolver methods. */
71
109
  getChannelName: (params: Partial<z.output<TInputSchema>> | Partial<z.output<TEventSchema>>, context?: FnContext<TDef, TKey>) => string;
72
110
  };
73
- export type CreatePubSub<TDef extends FnDefinition> = <TInputSchema extends ObjectSchema, TEventSchema extends ZodType, TKey extends ProcedureKey<TDef> = TDef['default']>(options: PubSubOptions<TDef, TInputSchema, TEventSchema, NoInfer<TKey>> &
74
- /** Which `procedures` builder the subscribe route uses. */
75
- ProcedureOption<TDef, TKey>) => PubSub<TDef, TInputSchema, TEventSchema, TKey>;
111
+ export type CreatePubSub<TDef extends FnDefinition> = <TInputSchema extends ObjectSchema, TEventSchema extends ZodType, TKey extends ProcedureKey<TDef> = TDef['default']>(options: PubSubOptions<TDef, TInputSchema, TEventSchema, NoInfer<TKey>> & GuardOptions<TDef['guards']> & Pick<FnRouteOptions<TDef, TKey, z.output<TInputSchema>>, 'meta' | 'guardResolvers'> &
112
+ /** Which `procedures` builder the subscribe route uses. */ ProcedureOption<TDef, TKey>) => PubSub<TDef, TInputSchema, TEventSchema, TKey>;
76
113
  export type PublisherOptions<TEventSchema extends ZodType> = PublisherConfig & {
77
114
  /** Static channel name, or a resolver over (partial) parsed event data. */
78
115
  channel: string | ((params: Partial<z.output<TEventSchema>>) => string);
@@ -89,10 +126,16 @@ export type Publisher<TEventSchema extends ZodType> = {
89
126
  */
90
127
  export type CreatePublisher = <TEventSchema extends ZodType>(options: PublisherOptions<TEventSchema>) => Publisher<TEventSchema>;
91
128
  export type PubSubRuntimeOptions = {
92
- transport: PubSubTransport;
129
+ /** Queue depths, drops, successful reconnects and parse failures. */
130
+ onMetric?: (event: PubSubMetric) => void;
93
131
  /**
94
- * Called once per event dropped from a slow subscriber's queue. Events wait
95
- * there before the subscriber's filter runs, so drops count unfiltered events.
132
+ * The broker, or a function creating it on first use so importing routes
133
+ * opens no connection: `transport: () => bunRedisTransport(getRedis())`.
134
+ */
135
+ transport: PubSubTransport | (() => PubSubTransport);
136
+ /**
137
+ * Called per event dropped from ingress, replay or delivery queues.
138
+ * Delivery drops count events before subscriber filtering.
96
139
  */
97
140
  onDrop?: (count: number, info: {
98
141
  name: string;
@@ -100,10 +143,20 @@ export type PubSubRuntimeOptions = {
100
143
  }) => void;
101
144
  /** Per-subscriber queue bound before drop-oldest (default: 1000). */
102
145
  maxQueueSize?: number;
146
+ /** Pending raw messages per channel, before asynchronous parsing. */
147
+ maxIngressSize?: number;
148
+ /** Buffered live messages during replay. */
149
+ maxReplaySize?: number;
150
+ /** Broker subscription and backlog wait bound (default 10000ms). */
151
+ initializationTimeoutMs?: number;
152
+ /** Applied to channels, mirrors and therefore backlog keys. */
153
+ namespace?: string;
154
+ /** Close this transport only when its ownership is explicitly transferred. */
155
+ ownsTransport?: boolean;
103
156
  };
104
157
  /** @internal */
105
158
  export type LiveRuntimeOptions = {
106
- buildProcedure: BuildProcedure;
159
+ fn: (options: Record<string, unknown>) => import('@orpc/server').AnyProcedure;
107
160
  tracing: Tracing;
108
161
  createLogger: (scope: string, span: SpanLike | undefined) => FnLogger;
109
162
  pubsub?: PubSubRuntimeOptions | undefined;
@@ -130,6 +183,7 @@ export declare function createBoundedEventQueue<T>(opts: {
130
183
  createOverflowMarker?: () => T | null;
131
184
  /** Called once per dropped message (metrics/counters). */
132
185
  onDrop?: () => void;
186
+ onDepth?: (depth: number) => void;
133
187
  }): {
134
188
  readonly length: number;
135
189
  enqueue(data: T): void;
@@ -148,11 +202,12 @@ export declare function createSubscriberDelivery<T>(options: {
148
202
  overflowMarker?: (() => T | null) | undefined;
149
203
  onFilterError: (error: unknown) => void;
150
204
  onDrop: () => void;
205
+ onDepth?: (depth: number) => void;
151
206
  }): {
152
- push(data: T): void;
207
+ push(data: T, marker?: boolean): void;
153
208
  events: AsyncGenerator<T, void, unknown>;
154
209
  /** Stop delivering; a parked read ends at once. */
155
- close(): void;
210
+ close(error?: unknown): void;
156
211
  };
157
212
  type Input = Record<string, unknown>;
158
213
  /** An open subscription: registered, authorized and subscribed. */
@@ -161,9 +216,10 @@ export type LiveSubscription = {
161
216
  events: AsyncGenerator<unknown, void, unknown>;
162
217
  /** Release everything; safe to call more than once, and before `events` runs. */
163
218
  close: () => void;
219
+ isClosed: () => boolean;
164
220
  };
165
221
  /** @internal Untyped options; `PubSubOptions` is the typed surface. */
166
- export type ChannelOptions = PublisherConfig & {
222
+ export type ChannelOptions = PublisherConfig & ChannelQueueOptions & {
167
223
  channel: ChannelDefinition<Input, unknown>;
168
224
  eventSchema: ZodType;
169
225
  filterFn?: FilterFn<Input, unknown>;
@@ -177,14 +233,21 @@ export type Channel = {
177
233
  input: Input;
178
234
  context: unknown;
179
235
  signal: AbortSignal | undefined;
236
+ recoverGaps?: boolean;
180
237
  }) => Promise<LiveSubscription>;
181
238
  publish: (data: unknown) => Promise<void>;
182
239
  publishMany: (items: readonly unknown[]) => Promise<void>;
183
240
  getChannelName: (params: Input, context?: unknown) => string;
241
+ getSubscriptionChannelName: (params: {
242
+ input: Input;
243
+ context: unknown;
244
+ }) => string;
245
+ getPublishChannelName: (event: Input) => string;
184
246
  };
185
247
  /** @internal */
186
248
  export declare function createLiveRuntime(options: LiveRuntimeOptions): {
187
249
  createChannel: (channelOptions: ChannelOptions) => Channel;
250
+ shutdown: () => Promise<void>;
188
251
  createPubSub: (pubsubOptions: ChannelOptions & {
189
252
  inputSchema: ZodType;
190
253
  procedure?: string;
@@ -196,6 +259,11 @@ export declare function createLiveRuntime(options: LiveRuntimeOptions): {
196
259
  publish: (data: unknown) => Promise<void>;
197
260
  publishMany: (items: readonly unknown[]) => Promise<void>;
198
261
  getChannelName: (params: Input, context?: unknown) => string;
262
+ getSubscriptionChannelName: (params: {
263
+ input: Input;
264
+ context: unknown;
265
+ }) => string;
266
+ getPublishChannelName: (event: Input) => string;
199
267
  };
200
268
  createPublisher: (publisherOptions: PublisherOptions<ZodType>) => {
201
269
  publish: (data: unknown) => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"pub-sub.d.ts","sourceRoot":"","sources":["../../src/live/pub-sub.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pub-sub.d.ts","sourceRoot":"","sources":["../../src/live/pub-sub.ts"],"names":[],"mappings":"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"}