@shivaedev/effect-trpc 0.6.0 → 0.7.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 (172) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +309 -186
  3. package/dist/{client/rejection.d.ts → rejectionDecoding.d.ts} +4 -4
  4. package/dist/rejectionDecoding.d.ts.map +1 -0
  5. package/dist/{client/rejection.js → rejectionDecoding.js} +6 -4
  6. package/dist/rejectionDecoding.js.map +1 -0
  7. package/dist/server/EffectProcedureBuilder.d.ts +35 -0
  8. package/dist/server/EffectProcedureBuilder.d.ts.map +1 -0
  9. package/dist/server/EffectProcedureBuilder.js +38 -0
  10. package/dist/server/EffectProcedureBuilder.js.map +1 -0
  11. package/dist/{request-signal.d.ts → server/RequestSignal.d.ts} +1 -1
  12. package/dist/server/RequestSignal.d.ts.map +1 -0
  13. package/dist/{request-signal.js → server/RequestSignal.js} +1 -1
  14. package/dist/server/RequestSignal.js.map +1 -0
  15. package/dist/server/adapter.d.ts +29 -0
  16. package/dist/server/adapter.d.ts.map +1 -0
  17. package/dist/{adapter.js → server/adapter.js} +3 -3
  18. package/dist/server/adapter.js.map +1 -0
  19. package/dist/server/errors.d.ts +11 -0
  20. package/dist/server/errors.d.ts.map +1 -0
  21. package/dist/server/errors.js +27 -0
  22. package/dist/server/errors.js.map +1 -0
  23. package/dist/server/internal/captureStackTrace.d.ts +2 -0
  24. package/dist/server/internal/captureStackTrace.d.ts.map +1 -0
  25. package/dist/{internal/stack-trace.js → server/internal/captureStackTrace.js} +4 -4
  26. package/dist/server/internal/captureStackTrace.js.map +1 -0
  27. package/dist/{internal/context-bridge.d.ts → server/internal/contextBridge.d.ts} +4 -4
  28. package/dist/server/internal/contextBridge.d.ts.map +1 -0
  29. package/dist/{internal/context-bridge.js → server/internal/contextBridge.js} +3 -3
  30. package/dist/server/internal/contextBridge.js.map +1 -0
  31. package/dist/server/internal/loose.d.ts +4 -0
  32. package/dist/server/internal/loose.d.ts.map +1 -0
  33. package/dist/server/internal/loose.js.map +1 -0
  34. package/dist/server/internal/makeProcedureHandler.d.ts +6 -0
  35. package/dist/server/internal/makeProcedureHandler.d.ts.map +1 -0
  36. package/dist/{internal/procedure-handler.js → server/internal/makeProcedureHandler.js} +3 -3
  37. package/dist/server/internal/makeProcedureHandler.js.map +1 -0
  38. package/dist/server/internal/makeSubscriptionHandler.d.ts +7 -0
  39. package/dist/server/internal/makeSubscriptionHandler.d.ts.map +1 -0
  40. package/dist/{internal/subscription-handler.js → server/internal/makeSubscriptionHandler.js} +7 -5
  41. package/dist/server/internal/makeSubscriptionHandler.js.map +1 -0
  42. package/dist/server/internal/procedureTypes.d.ts +23 -0
  43. package/dist/server/internal/procedureTypes.d.ts.map +1 -0
  44. package/dist/server/internal/procedureTypes.js +2 -0
  45. package/dist/server/internal/procedureTypes.js.map +1 -0
  46. package/dist/server/internal/runtime.d.ts +20 -0
  47. package/dist/server/internal/runtime.d.ts.map +1 -0
  48. package/dist/server/internal/runtime.js +94 -0
  49. package/dist/server/internal/runtime.js.map +1 -0
  50. package/dist/{rejection.d.ts → server/rejection.d.ts} +5 -5
  51. package/dist/server/rejection.d.ts.map +1 -0
  52. package/dist/{rejection.js → server/rejection.js} +7 -3
  53. package/dist/server/rejection.js.map +1 -0
  54. package/dist/{rejection-formatter.d.ts → server/rejectionFormatter.d.ts} +6 -6
  55. package/dist/server/rejectionFormatter.d.ts.map +1 -0
  56. package/dist/{rejection-formatter.js → server/rejectionFormatter.js} +13 -9
  57. package/dist/server/rejectionFormatter.js.map +1 -0
  58. package/dist/server/requestServices.d.ts +7 -0
  59. package/dist/server/requestServices.d.ts.map +1 -0
  60. package/dist/server/requestServices.js +8 -0
  61. package/dist/server/requestServices.js.map +1 -0
  62. package/dist/{testing/any-test-layer.d.ts → server/testing/AnyTestLayer.d.ts} +1 -1
  63. package/dist/server/testing/AnyTestLayer.d.ts.map +1 -0
  64. package/dist/server/testing/AnyTestLayer.js +2 -0
  65. package/dist/server/testing/AnyTestLayer.js.map +1 -0
  66. package/dist/server/testing/caller.d.ts +12 -0
  67. package/dist/server/testing/caller.d.ts.map +1 -0
  68. package/dist/server/testing/caller.js +48 -0
  69. package/dist/server/testing/caller.js.map +1 -0
  70. package/dist/server/testing/types.d.ts +36 -0
  71. package/dist/server/testing/types.d.ts.map +1 -0
  72. package/dist/server/testing/types.js.map +1 -0
  73. package/dist/server/testing/vitest.d.ts +6 -0
  74. package/dist/server/testing/vitest.d.ts.map +1 -0
  75. package/dist/{testing → server/testing}/vitest.js +8 -6
  76. package/dist/server/testing/vitest.js.map +1 -0
  77. package/dist/server/types.d.ts.map +1 -0
  78. package/dist/{testing → server}/types.js.map +1 -1
  79. package/docs/north-star.md +48 -0
  80. package/docs/roadmap.md +33 -0
  81. package/package.json +198 -22
  82. package/src/{client/rejection.ts → rejectionDecoding.ts} +7 -5
  83. package/src/server/EffectProcedureBuilder.ts +134 -0
  84. package/src/{request-signal.ts → server/RequestSignal.ts} +0 -1
  85. package/src/server/adapter.ts +83 -0
  86. package/src/server/errors.ts +26 -0
  87. package/src/{internal/stack-trace.ts → server/internal/captureStackTrace.ts} +3 -4
  88. package/src/{internal/context-bridge.ts → server/internal/contextBridge.ts} +4 -8
  89. package/src/server/internal/loose.ts +12 -0
  90. package/src/{internal/procedure-handler.ts → server/internal/makeProcedureHandler.ts} +8 -10
  91. package/src/{internal/subscription-handler.ts → server/internal/makeSubscriptionHandler.ts} +12 -13
  92. package/src/server/internal/procedureTypes.ts +35 -0
  93. package/src/server/internal/runtime.ts +131 -0
  94. package/src/{rejection.ts → server/rejection.ts} +22 -19
  95. package/src/{rejection-formatter.ts → server/rejectionFormatter.ts} +25 -18
  96. package/src/server/requestServices.ts +23 -0
  97. package/src/{testing/any-test-layer.ts → server/testing/AnyTestLayer.ts} +0 -1
  98. package/src/{testing → server/testing}/caller.ts +28 -33
  99. package/src/server/testing/types.ts +55 -0
  100. package/src/{testing → server/testing}/vitest.ts +17 -17
  101. package/src/{types.ts → server/types.ts} +0 -6
  102. package/dist/adapter.d.ts +0 -29
  103. package/dist/adapter.d.ts.map +0 -1
  104. package/dist/adapter.js.map +0 -1
  105. package/dist/client/rejection.d.ts.map +0 -1
  106. package/dist/client/rejection.js.map +0 -1
  107. package/dist/errors.d.ts +0 -11
  108. package/dist/errors.d.ts.map +0 -1
  109. package/dist/errors.js +0 -11
  110. package/dist/errors.js.map +0 -1
  111. package/dist/internal/context-bridge.d.ts.map +0 -1
  112. package/dist/internal/context-bridge.js.map +0 -1
  113. package/dist/internal/loose.d.ts +0 -4
  114. package/dist/internal/loose.d.ts.map +0 -1
  115. package/dist/internal/loose.js.map +0 -1
  116. package/dist/internal/procedure-handler.d.ts +0 -6
  117. package/dist/internal/procedure-handler.d.ts.map +0 -1
  118. package/dist/internal/procedure-handler.js.map +0 -1
  119. package/dist/internal/procedure-types.d.ts +0 -23
  120. package/dist/internal/procedure-types.d.ts.map +0 -1
  121. package/dist/internal/procedure-types.js +0 -2
  122. package/dist/internal/procedure-types.js.map +0 -1
  123. package/dist/internal/runtime.d.ts +0 -20
  124. package/dist/internal/runtime.d.ts.map +0 -1
  125. package/dist/internal/runtime.js +0 -85
  126. package/dist/internal/runtime.js.map +0 -1
  127. package/dist/internal/stack-trace.d.ts +0 -2
  128. package/dist/internal/stack-trace.d.ts.map +0 -1
  129. package/dist/internal/stack-trace.js.map +0 -1
  130. package/dist/internal/subscription-handler.d.ts +0 -7
  131. package/dist/internal/subscription-handler.d.ts.map +0 -1
  132. package/dist/internal/subscription-handler.js.map +0 -1
  133. package/dist/procedure.d.ts +0 -36
  134. package/dist/procedure.d.ts.map +0 -1
  135. package/dist/procedure.js +0 -38
  136. package/dist/procedure.js.map +0 -1
  137. package/dist/rejection-formatter.d.ts.map +0 -1
  138. package/dist/rejection-formatter.js.map +0 -1
  139. package/dist/rejection.d.ts.map +0 -1
  140. package/dist/rejection.js.map +0 -1
  141. package/dist/request-services.d.ts +0 -7
  142. package/dist/request-services.d.ts.map +0 -1
  143. package/dist/request-services.js +0 -4
  144. package/dist/request-services.js.map +0 -1
  145. package/dist/request-signal.d.ts.map +0 -1
  146. package/dist/request-signal.js.map +0 -1
  147. package/dist/testing/any-test-layer.d.ts.map +0 -1
  148. package/dist/testing/any-test-layer.js +0 -2
  149. package/dist/testing/any-test-layer.js.map +0 -1
  150. package/dist/testing/caller.d.ts +0 -12
  151. package/dist/testing/caller.d.ts.map +0 -1
  152. package/dist/testing/caller.js +0 -42
  153. package/dist/testing/caller.js.map +0 -1
  154. package/dist/testing/types.d.ts +0 -36
  155. package/dist/testing/types.d.ts.map +0 -1
  156. package/dist/testing/vitest.d.ts +0 -6
  157. package/dist/testing/vitest.d.ts.map +0 -1
  158. package/dist/testing/vitest.js.map +0 -1
  159. package/dist/types.d.ts.map +0 -1
  160. package/dist/types.js.map +0 -1
  161. package/src/adapter.ts +0 -72
  162. package/src/errors.ts +0 -19
  163. package/src/internal/loose.ts +0 -14
  164. package/src/internal/procedure-types.ts +0 -44
  165. package/src/internal/runtime.ts +0 -134
  166. package/src/procedure.ts +0 -142
  167. package/src/request-services.ts +0 -23
  168. package/src/testing/types.ts +0 -63
  169. /package/dist/{internal → server/internal}/loose.js +0 -0
  170. /package/dist/{testing → server/testing}/types.js +0 -0
  171. /package/dist/{types.d.ts → server/types.d.ts} +0 -0
  172. /package/dist/{types.js → server/types.js} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shivaedev/effect-trpc",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Effect-native procedures and testing for tRPC",
5
5
  "homepage": "https://github.com/ShivaeDev/platform/tree/main/packages/effect-trpc#readme",
6
6
  "bugs": {
@@ -15,49 +15,225 @@
15
15
  "sideEffects": false,
16
16
  "type": "module",
17
17
  "imports": {
18
- "#test/*": "./test/*",
18
+ "#test/*": "./src/test-support/*",
19
19
  "#*.ts": {
20
20
  "source": "./src/*.ts",
21
21
  "types": "./dist/*.d.ts",
22
22
  "default": "./dist/*.js"
23
+ },
24
+ "#adapter.ts": {
25
+ "source": "./src/server/adapter.ts",
26
+ "types": "./dist/server/adapter.d.ts",
27
+ "default": "./dist/server/adapter.js"
28
+ },
29
+ "#errors.ts": {
30
+ "source": "./src/server/errors.ts",
31
+ "types": "./dist/server/errors.d.ts",
32
+ "default": "./dist/server/errors.js"
33
+ },
34
+ "#internal/context-bridge.ts": {
35
+ "source": "./src/server/internal/contextBridge.ts",
36
+ "types": "./dist/server/internal/contextBridge.d.ts",
37
+ "default": "./dist/server/internal/contextBridge.js"
38
+ },
39
+ "#internal/loose.ts": {
40
+ "source": "./src/server/internal/loose.ts",
41
+ "types": "./dist/server/internal/loose.d.ts",
42
+ "default": "./dist/server/internal/loose.js"
43
+ },
44
+ "#internal/procedure-handler.ts": {
45
+ "source": "./src/server/internal/makeProcedureHandler.ts",
46
+ "types": "./dist/server/internal/makeProcedureHandler.d.ts",
47
+ "default": "./dist/server/internal/makeProcedureHandler.js"
48
+ },
49
+ "#internal/procedure-types.ts": {
50
+ "source": "./src/server/internal/procedureTypes.ts",
51
+ "types": "./dist/server/internal/procedureTypes.d.ts",
52
+ "default": "./dist/server/internal/procedureTypes.js"
53
+ },
54
+ "#internal/runtime.ts": {
55
+ "source": "./src/server/internal/runtime.ts",
56
+ "types": "./dist/server/internal/runtime.d.ts",
57
+ "default": "./dist/server/internal/runtime.js"
58
+ },
59
+ "#internal/stack-trace.ts": {
60
+ "source": "./src/server/internal/captureStackTrace.ts",
61
+ "types": "./dist/server/internal/captureStackTrace.d.ts",
62
+ "default": "./dist/server/internal/captureStackTrace.js"
63
+ },
64
+ "#internal/subscription-handler.ts": {
65
+ "source": "./src/server/internal/makeSubscriptionHandler.ts",
66
+ "types": "./dist/server/internal/makeSubscriptionHandler.d.ts",
67
+ "default": "./dist/server/internal/makeSubscriptionHandler.js"
68
+ },
69
+ "#procedure.ts": {
70
+ "source": "./src/server/EffectProcedureBuilder.ts",
71
+ "types": "./dist/server/EffectProcedureBuilder.d.ts",
72
+ "default": "./dist/server/EffectProcedureBuilder.js"
73
+ },
74
+ "#rejection-formatter.ts": {
75
+ "source": "./src/server/rejectionFormatter.ts",
76
+ "types": "./dist/server/rejectionFormatter.d.ts",
77
+ "default": "./dist/server/rejectionFormatter.js"
78
+ },
79
+ "#rejection.ts": {
80
+ "source": "./src/server/rejection.ts",
81
+ "types": "./dist/server/rejection.d.ts",
82
+ "default": "./dist/server/rejection.js"
83
+ },
84
+ "#request-services.ts": {
85
+ "source": "./src/server/requestServices.ts",
86
+ "types": "./dist/server/requestServices.d.ts",
87
+ "default": "./dist/server/requestServices.js"
88
+ },
89
+ "#request-signal.ts": {
90
+ "source": "./src/server/RequestSignal.ts",
91
+ "types": "./dist/server/RequestSignal.d.ts",
92
+ "default": "./dist/server/RequestSignal.js"
93
+ },
94
+ "#testing/any-test-layer.ts": {
95
+ "source": "./src/server/testing/AnyTestLayer.ts",
96
+ "types": "./dist/server/testing/AnyTestLayer.d.ts",
97
+ "default": "./dist/server/testing/AnyTestLayer.js"
98
+ },
99
+ "#testing/caller.ts": {
100
+ "source": "./src/server/testing/caller.ts",
101
+ "types": "./dist/server/testing/caller.d.ts",
102
+ "default": "./dist/server/testing/caller.js"
103
+ },
104
+ "#testing/types.ts": {
105
+ "source": "./src/server/testing/types.ts",
106
+ "types": "./dist/server/testing/types.d.ts",
107
+ "default": "./dist/server/testing/types.js"
108
+ },
109
+ "#testing/vitest.ts": {
110
+ "source": "./src/server/testing/vitest.ts",
111
+ "types": "./dist/server/testing/vitest.d.ts",
112
+ "default": "./dist/server/testing/vitest.js"
113
+ },
114
+ "#types.ts": {
115
+ "source": "./src/server/types.ts",
116
+ "types": "./dist/server/types.d.ts",
117
+ "default": "./dist/server/types.js"
23
118
  }
24
119
  },
25
120
  "exports": {
26
- "./*.ts": {
27
- "types": "./dist/*.d.ts",
28
- "source": "./src/*.ts",
29
- "import": "./dist/*.js",
30
- "default": "./dist/*.js"
121
+ "./package.json": "./package.json",
122
+ "./client/rejection.ts": {
123
+ "types": "./dist/rejectionDecoding.d.ts",
124
+ "source": "./src/rejectionDecoding.ts",
125
+ "import": "./dist/rejectionDecoding.js",
126
+ "default": "./dist/rejectionDecoding.js"
127
+ },
128
+ "./adapter.ts": {
129
+ "types": "./dist/server/adapter.d.ts",
130
+ "source": "./src/server/adapter.ts",
131
+ "import": "./dist/server/adapter.js",
132
+ "default": "./dist/server/adapter.js"
133
+ },
134
+ "./errors.ts": {
135
+ "types": "./dist/server/errors.d.ts",
136
+ "source": "./src/server/errors.ts",
137
+ "import": "./dist/server/errors.js",
138
+ "default": "./dist/server/errors.js"
139
+ },
140
+ "./procedure.ts": {
141
+ "types": "./dist/server/EffectProcedureBuilder.d.ts",
142
+ "source": "./src/server/EffectProcedureBuilder.ts",
143
+ "import": "./dist/server/EffectProcedureBuilder.js",
144
+ "default": "./dist/server/EffectProcedureBuilder.js"
145
+ },
146
+ "./rejection-formatter.ts": {
147
+ "types": "./dist/server/rejectionFormatter.d.ts",
148
+ "source": "./src/server/rejectionFormatter.ts",
149
+ "import": "./dist/server/rejectionFormatter.js",
150
+ "default": "./dist/server/rejectionFormatter.js"
151
+ },
152
+ "./rejection.ts": {
153
+ "types": "./dist/server/rejection.d.ts",
154
+ "source": "./src/server/rejection.ts",
155
+ "import": "./dist/server/rejection.js",
156
+ "default": "./dist/server/rejection.js"
31
157
  },
32
- "./internal/*": null,
33
- "./package.json": "./package.json"
158
+ "./rejectionDecoding.ts": {
159
+ "types": "./dist/rejectionDecoding.d.ts",
160
+ "source": "./src/rejectionDecoding.ts",
161
+ "import": "./dist/rejectionDecoding.js",
162
+ "default": "./dist/rejectionDecoding.js"
163
+ },
164
+ "./request-services.ts": {
165
+ "types": "./dist/server/requestServices.d.ts",
166
+ "source": "./src/server/requestServices.ts",
167
+ "import": "./dist/server/requestServices.js",
168
+ "default": "./dist/server/requestServices.js"
169
+ },
170
+ "./request-signal.ts": {
171
+ "types": "./dist/server/RequestSignal.d.ts",
172
+ "source": "./src/server/RequestSignal.ts",
173
+ "import": "./dist/server/RequestSignal.js",
174
+ "default": "./dist/server/RequestSignal.js"
175
+ },
176
+ "./testing/any-test-layer.ts": {
177
+ "types": "./dist/server/testing/AnyTestLayer.d.ts",
178
+ "source": "./src/server/testing/AnyTestLayer.ts",
179
+ "import": "./dist/server/testing/AnyTestLayer.js",
180
+ "default": "./dist/server/testing/AnyTestLayer.js"
181
+ },
182
+ "./testing/caller.ts": {
183
+ "types": "./dist/server/testing/caller.d.ts",
184
+ "source": "./src/server/testing/caller.ts",
185
+ "import": "./dist/server/testing/caller.js",
186
+ "default": "./dist/server/testing/caller.js"
187
+ },
188
+ "./testing/types.ts": {
189
+ "types": "./dist/server/testing/types.d.ts",
190
+ "source": "./src/server/testing/types.ts",
191
+ "import": "./dist/server/testing/types.js",
192
+ "default": "./dist/server/testing/types.js"
193
+ },
194
+ "./testing/vitest.ts": {
195
+ "types": "./dist/server/testing/vitest.d.ts",
196
+ "source": "./src/server/testing/vitest.ts",
197
+ "import": "./dist/server/testing/vitest.js",
198
+ "default": "./dist/server/testing/vitest.js"
199
+ },
200
+ "./types.ts": {
201
+ "types": "./dist/server/types.d.ts",
202
+ "source": "./src/server/types.ts",
203
+ "import": "./dist/server/types.js",
204
+ "default": "./dist/server/types.js"
205
+ }
34
206
  },
35
207
  "files": [
36
208
  "dist",
37
209
  "src",
210
+ "!src/**/*.test.ts",
211
+ "!src/**/*.spec.ts",
212
+ "!src/**/test-support",
38
213
  "CHANGELOG.md",
214
+ "docs",
39
215
  "README.md"
40
216
  ],
41
217
  "dependencies": {
42
- "@shivaedev/effect-test": "0.2.0"
218
+ "@shivaedev/effect-test": "0.4.0"
43
219
  },
44
220
  "devDependencies": {
45
- "@effect/vitest": "4.0.0-rc.112",
46
- "@shivaedev/effect-contract": "0.3.0",
47
- "@shivaedev/quality": "0.9.0",
48
- "@trpc/client": "11.18.0",
49
- "@trpc/server": "11.18.0",
50
- "@types/node": "24.10.1",
221
+ "@effect/vitest": "4.0.4",
222
+ "@shivaedev/effect-contract": "0.5.0",
223
+ "@shivaedev/quality": "0.20.0",
224
+ "@trpc/client": "11.19.0",
225
+ "@trpc/server": "11.19.0",
226
+ "@types/node": "24.19.1",
51
227
  "@typescript/native": "npm:typescript@7.0.2",
52
- "effect": "4.0.0-rc.112",
228
+ "effect": "4.0.4",
53
229
  "superjson": "2.2.6",
54
230
  "typescript": "npm:@typescript/typescript6@6.0.2",
55
- "vitest": "4.1.9"
231
+ "vitest": "5.0.3"
56
232
  },
57
233
  "peerDependencies": {
58
- "@effect/vitest": "4.0.0-rc.112",
59
- "@trpc/server": "11.18.0",
60
- "effect": "4.0.0-rc.112"
234
+ "@effect/vitest": "4.0.4",
235
+ "@trpc/server": "11.19.0",
236
+ "effect": "4.0.4"
61
237
  },
62
238
  "peerDependenciesMeta": {
63
239
  "@effect/vitest": {
@@ -72,7 +248,7 @@
72
248
  "provenance": true
73
249
  },
74
250
  "scripts": {
75
- "build": "node --eval \"import('node:fs').then(({ rmSync }) => rmSync('dist', { force: true, recursive: true }))\" && tsc6 --project tsconfig.build.json",
251
+ "build": "node --eval \"import('node:fs').then(({ rmSync }) => rmSync('dist', { force: true, recursive: true }))\" && tsc --project tsconfig.build.json",
76
252
  "ready": "pnpm typecheck && pnpm test && pnpm build",
77
253
  "test": "vitest run",
78
254
  "typecheck": "tsc --noEmit"
@@ -9,11 +9,13 @@ export type EncodedRejection = typeof EncodedRejection.Type;
9
9
 
10
10
  const decodeCarrier = Schema.decodeUnknownOption(Schema.Struct({ data: Schema.Struct({ rejection: EncodedRejection }) }));
11
11
 
12
- export const rejectionOf = (error: unknown): Option.Option<EncodedRejection> => Option.map(decodeCarrier(error), ({ data }) => data.rejection);
12
+ export function rejectionOf(error: unknown): Option.Option<EncodedRejection> {
13
+ return Option.map(decodeCarrier(error), ({ data }) => data.rejection);
14
+ }
13
15
 
14
- export const decodeRejection = <S extends Schema.ConstraintDecoder<{ readonly _tag: string }>>(
15
- schema: S,
16
- ): ((error: unknown) => Option.Option<S["Type"]>) => {
16
+ export function decodeRejection<TSchema extends Schema.ConstraintDecoder<{ readonly _tag: string }>>(
17
+ schema: TSchema,
18
+ ): (error: unknown) => Option.Option<TSchema["Type"]> {
17
19
  const decode = Schema.decodeUnknownOption(schema);
18
20
  return (error) => Option.flatMap(rejectionOf(error), (rejection) => decode(rejection));
19
- };
21
+ }
@@ -0,0 +1,134 @@
1
+ import type { TRPCMutationProcedure, TRPCQueryProcedure, TRPCSubscriptionProcedure } from "@trpc/server";
2
+ import { Schema } from "effect";
3
+ import { makeProcedureHandler } from "#internal/procedure-handler.ts";
4
+ import type {
5
+ DefaultValue,
6
+ EffectProcedureResolver,
7
+ EffectSubscriptionResolver,
8
+ IntersectIfDefined,
9
+ ProcedureBuilderSurface,
10
+ ResolverContext,
11
+ } from "#internal/procedure-types.ts";
12
+ import type { RuntimeBridge } from "#internal/runtime.ts";
13
+ import { captureStackTrace } from "#internal/stack-trace.ts";
14
+ import { makeSubscriptionHandler } from "#internal/subscription-handler.ts";
15
+ import type { EffectProcedureRequestServices } from "./requestServices.ts";
16
+
17
+ interface ProcedureParts<TContext, TMeta, TContextOverrides, TProvidedServices, TLayerError, TRuntimeRequirements> {
18
+ readonly builder: ProcedureBuilderSurface<ResolverContext<TContext, TMeta, TContextOverrides>>;
19
+ readonly requestServices: EffectProcedureRequestServices<ResolverContext<TContext, TMeta, TContextOverrides>, TProvidedServices, TLayerError>;
20
+ readonly runtime: RuntimeBridge<TRuntimeRequirements>;
21
+ readonly subscriptionBuilder: ProcedureBuilderSurface<ResolverContext<TContext, TMeta, TContextOverrides>>;
22
+ readonly subscriptionOutput?: Schema.ConstraintDecoder<unknown> | undefined;
23
+ }
24
+ export class EffectProcedureBuilder<
25
+ TContext,
26
+ TMeta,
27
+ TContextOverrides,
28
+ TInputIn,
29
+ TInputOut,
30
+ TOutputIn,
31
+ TOutputOut,
32
+ TProvidedServices,
33
+ TLayerError,
34
+ TRuntimeRequirements,
35
+ > {
36
+ readonly #parts: ProcedureParts<TContext, TMeta, TContextOverrides, TProvidedServices, TLayerError, TRuntimeRequirements>;
37
+ constructor(parts: ProcedureParts<TContext, TMeta, TContextOverrides, TProvidedServices, TLayerError, TRuntimeRequirements>) {
38
+ this.#parts = parts;
39
+ }
40
+ input<TSchemaValue extends Schema.ConstraintDecoder<unknown>>(
41
+ schema: TSchemaValue,
42
+ ): EffectProcedureBuilder<
43
+ TContext,
44
+ TMeta,
45
+ TContextOverrides,
46
+ IntersectIfDefined<TInputIn, TSchemaValue["Encoded"]>,
47
+ IntersectIfDefined<TInputOut, TSchemaValue["Type"]>,
48
+ TOutputIn,
49
+ TOutputOut,
50
+ TProvidedServices,
51
+ TLayerError,
52
+ TRuntimeRequirements
53
+ > {
54
+ const parser = Schema.toStandardSchemaV1(schema);
55
+ return new EffectProcedureBuilder({
56
+ ...this.#parts,
57
+ builder: this.#parts.builder.input(parser),
58
+ subscriptionBuilder: this.#parts.subscriptionBuilder.input(parser),
59
+ });
60
+ }
61
+ output<TSchemaValue extends Schema.ConstraintDecoder<unknown>>(
62
+ schema: TSchemaValue,
63
+ ): EffectProcedureBuilder<
64
+ TContext,
65
+ TMeta,
66
+ TContextOverrides,
67
+ TInputIn,
68
+ TInputOut,
69
+ IntersectIfDefined<TOutputIn, TSchemaValue["Encoded"]>,
70
+ IntersectIfDefined<TOutputOut, TSchemaValue["Type"]>,
71
+ TProvidedServices,
72
+ TLayerError,
73
+ TRuntimeRequirements
74
+ > {
75
+ return new EffectProcedureBuilder({
76
+ ...this.#parts,
77
+ builder: this.#parts.builder.output(Schema.toStandardSchemaV1(schema)),
78
+ subscriptionOutput: schema,
79
+ });
80
+ }
81
+ query<TOutput>(
82
+ resolver: EffectProcedureResolver<
83
+ DefaultValue<TInputOut, undefined>,
84
+ TProvidedServices | NoInfer<TRuntimeRequirements>,
85
+ DefaultValue<TOutputIn, TOutput>
86
+ >,
87
+ ): TRPCQueryProcedure<{
88
+ input: DefaultValue<TInputIn, void>;
89
+ output: DefaultValue<TOutputOut, TOutput>;
90
+ meta: TMeta;
91
+ }>;
92
+ query(resolver: EffectProcedureResolver<never, TProvidedServices | TRuntimeRequirements, unknown>): unknown {
93
+ return this.#parts.builder.query(this.#handler("query", resolver));
94
+ }
95
+ mutation<TOutput>(
96
+ resolver: EffectProcedureResolver<
97
+ DefaultValue<TInputOut, undefined>,
98
+ TProvidedServices | NoInfer<TRuntimeRequirements>,
99
+ DefaultValue<TOutputIn, TOutput>
100
+ >,
101
+ ): TRPCMutationProcedure<{
102
+ input: DefaultValue<TInputIn, void>;
103
+ output: DefaultValue<TOutputOut, TOutput>;
104
+ meta: TMeta;
105
+ }>;
106
+ mutation(resolver: EffectProcedureResolver<never, TProvidedServices | TRuntimeRequirements, unknown>): unknown {
107
+ return this.#parts.builder.mutation(this.#handler("mutation", resolver));
108
+ }
109
+ subscription<TOutput>(
110
+ resolver: EffectSubscriptionResolver<
111
+ DefaultValue<TInputOut, undefined>,
112
+ TProvidedServices | NoInfer<TRuntimeRequirements>,
113
+ DefaultValue<TOutputIn, TOutput>
114
+ >,
115
+ ): TRPCSubscriptionProcedure<{
116
+ input: DefaultValue<TInputIn, void>;
117
+ output: AsyncIterable<DefaultValue<TOutputOut, TOutput>, void, unknown>;
118
+ meta: TMeta;
119
+ }>;
120
+ subscription(resolver: EffectSubscriptionResolver<never, TProvidedServices | TRuntimeRequirements, unknown>): unknown {
121
+ return this.#parts.subscriptionBuilder.subscription(
122
+ makeSubscriptionHandler(
123
+ this.#parts.runtime,
124
+ resolver,
125
+ this.#parts.requestServices,
126
+ { captureStackTrace: captureStackTrace(), type: "subscription" },
127
+ this.#parts.subscriptionOutput,
128
+ ),
129
+ );
130
+ }
131
+ #handler(type: "mutation" | "query", resolver: EffectProcedureResolver<never, TProvidedServices | TRuntimeRequirements, unknown>) {
132
+ return makeProcedureHandler(this.#parts.runtime, resolver, this.#parts.requestServices, { captureStackTrace: captureStackTrace(), type });
133
+ }
134
+ }
@@ -1,3 +1,2 @@
1
1
  import { Context } from "effect";
2
-
3
2
  export const RequestSignal = Context.Reference<AbortSignal | undefined>("@shivaedev/effect-trpc/RequestSignal", { defaultValue: () => undefined });
@@ -0,0 +1,83 @@
1
+ import type { TRPCProcedureBuilder } from "@trpc/server";
2
+ import type { Context, Effect, Exit } from "effect";
3
+ import { makeContextBridge } from "#internal/context-bridge.ts";
4
+ import { looseBuilder } from "#internal/loose.ts";
5
+ import type { ResolverContext } from "#internal/procedure-types.ts";
6
+ import { makeRuntimeBridge } from "#internal/runtime.ts";
7
+ import { EffectProcedureBuilder } from "./EffectProcedureBuilder.ts";
8
+ import type { EffectProcedureRequestServices } from "./requestServices.ts";
9
+ import type { EffectTRPCErrorMapper, EffectTRPCInstrument, EffectTRPCStreamInstrument } from "./types.ts";
10
+
11
+ export interface MakeEffectTRPCOptions<TRequirements, TRuntimeError> {
12
+ readonly instrument?: EffectTRPCInstrument;
13
+ readonly instrumentStream?: EffectTRPCStreamInstrument;
14
+ readonly mapError?: EffectTRPCErrorMapper;
15
+ readonly runtime: EffectTRPCRuntime<TRequirements, TRuntimeError>;
16
+ }
17
+ export interface EffectTRPCRuntime<TRequirements, TRuntimeError> {
18
+ readonly contextEffect: Effect.Effect<Context.Context<TRequirements>, TRuntimeError>;
19
+ readonly currentServices?: () => Context.Context<never> | undefined;
20
+ readonly runPromise: <TValue, TError>(
21
+ effect: Effect.Effect<TValue, TError, TRequirements>,
22
+ options?: {
23
+ readonly signal?: AbortSignal;
24
+ },
25
+ ) => Promise<TValue>;
26
+ readonly runPromiseExit: <TValue, TError>(
27
+ effect: Effect.Effect<TValue, TError, TRequirements>,
28
+ options?: {
29
+ readonly signal?: AbortSignal;
30
+ },
31
+ ) => Promise<Exit.Exit<TValue, TError | TRuntimeError>>;
32
+ readonly runWithServices?: <TServices, TValue>(services: Context.Context<TServices>, evaluate: () => TValue) => TValue;
33
+ }
34
+ export interface EffectTRPCAdapter<TRequirements> {
35
+ readonly procedure: <TContext, TMeta, TContextOverrides, TInputIn, TInputOut, TOutputIn, TOutputOut, TProvidedServices, TLayerError>(
36
+ builder: TRPCProcedureBuilder<TContext, TMeta, TContextOverrides, TInputIn, TInputOut, TOutputIn, TOutputOut, false>,
37
+ requestServices: EffectProcedureRequestServices<ResolverContext<TContext, TMeta, TContextOverrides>, TProvidedServices, TLayerError>,
38
+ ) => EffectProcedureBuilder<
39
+ TContext,
40
+ TMeta,
41
+ TContextOverrides,
42
+ TInputIn,
43
+ TInputOut,
44
+ TOutputIn,
45
+ TOutputOut,
46
+ TProvidedServices,
47
+ TLayerError,
48
+ TRequirements
49
+ >;
50
+ readonly runWithServices: <TServices, TValue>(services: Context.Context<TServices>, evaluate: () => TValue) => TValue;
51
+ }
52
+ export function makeEffectTRPC<TRequirements, TRuntimeError = never>(
53
+ options: MakeEffectTRPCOptions<TRequirements, TRuntimeError>,
54
+ ): EffectTRPCAdapter<TRequirements> {
55
+ const contextBridge = makeContextBridge(options.runtime);
56
+ const runtime = makeRuntimeBridge(options.runtime, contextBridge, options);
57
+ return {
58
+ procedure: <TContext, TMeta, TContextOverrides, TInputIn, TInputOut, TOutputIn, TOutputOut, TProvidedServices, TLayerError>(
59
+ builder: TRPCProcedureBuilder<TContext, TMeta, TContextOverrides, TInputIn, TInputOut, TOutputIn, TOutputOut, false>,
60
+ requestServices: EffectProcedureRequestServices<ResolverContext<TContext, TMeta, TContextOverrides>, TProvidedServices, TLayerError>,
61
+ ) => {
62
+ const loose = looseBuilder(builder);
63
+ return new EffectProcedureBuilder<
64
+ TContext,
65
+ TMeta,
66
+ TContextOverrides,
67
+ TInputIn,
68
+ TInputOut,
69
+ TOutputIn,
70
+ TOutputOut,
71
+ TProvidedServices,
72
+ TLayerError,
73
+ TRequirements
74
+ >({
75
+ builder: loose,
76
+ requestServices,
77
+ runtime,
78
+ subscriptionBuilder: loose,
79
+ });
80
+ },
81
+ runWithServices: contextBridge.run,
82
+ };
83
+ }
@@ -0,0 +1,26 @@
1
+ import { TRPCError } from "@trpc/server";
2
+ import { Effect } from "effect";
3
+ export function fail(code: TRPCError["code"], message: string, cause?: unknown): Effect.Effect<never, TRPCError> {
4
+ return Effect.fail(new TRPCError({ cause, code, message }));
5
+ }
6
+ export function badRequest(message: string, cause?: unknown) {
7
+ return fail("BAD_REQUEST", message, cause);
8
+ }
9
+ export function unauthorized(message: string, cause?: unknown) {
10
+ return fail("UNAUTHORIZED", message, cause);
11
+ }
12
+ export function forbidden(message: string, cause?: unknown) {
13
+ return fail("FORBIDDEN", message, cause);
14
+ }
15
+ export function notFound(message: string, cause?: unknown) {
16
+ return fail("NOT_FOUND", message, cause);
17
+ }
18
+ export function conflict(message: string, cause?: unknown) {
19
+ return fail("CONFLICT", message, cause);
20
+ }
21
+ export function preconditionFailed(message: string, cause?: unknown) {
22
+ return fail("PRECONDITION_FAILED", message, cause);
23
+ }
24
+ export function internalServerError(message: string, cause?: unknown) {
25
+ return fail("INTERNAL_SERVER_ERROR", message, cause);
26
+ }
@@ -1,9 +1,8 @@
1
- export const captureStackTrace = (): (() => string | undefined) => {
1
+ export function captureStackTrace(): () => string | undefined {
2
2
  const limit = Error.stackTraceLimit;
3
3
  Error.stackTraceLimit = 3;
4
- const traceError = new Error();
4
+ const traceError = new Error("Procedure definition");
5
5
  Error.stackTraceLimit = limit;
6
-
7
6
  let cache: false | string = false;
8
7
  return () => {
9
8
  if (cache !== false) {
@@ -16,4 +15,4 @@ export const captureStackTrace = (): (() => string | undefined) => {
16
15
  }
17
16
  return undefined;
18
17
  };
19
- };
18
+ }
@@ -1,26 +1,22 @@
1
1
  import { AsyncLocalStorage } from "node:async_hooks";
2
2
  import type { Context } from "effect";
3
-
4
3
  export interface ContextBridge {
5
4
  readonly current: () => Context.Context<never> | undefined;
6
- readonly run: <Services, Value>(services: Context.Context<Services>, evaluate: () => Value) => Value;
5
+ readonly run: <TServices, TValue>(services: Context.Context<TServices>, evaluate: () => TValue) => TValue;
7
6
  }
8
-
9
- export const makeContextBridge = (shared?: {
7
+ export function makeContextBridge(shared?: {
10
8
  readonly currentServices?: ContextBridge["current"];
11
9
  readonly runWithServices?: ContextBridge["run"];
12
- }): ContextBridge => {
10
+ }): ContextBridge {
13
11
  if (shared?.currentServices !== undefined && shared.runWithServices !== undefined) {
14
12
  return {
15
13
  current: shared.currentServices,
16
14
  run: shared.runWithServices,
17
15
  };
18
16
  }
19
-
20
17
  const storage = new AsyncLocalStorage<Context.Context<never>>();
21
-
22
18
  return {
23
19
  current: () => storage.getStore(),
24
20
  run: (services, evaluate) => storage.run(services, evaluate),
25
21
  };
26
- };
22
+ }
@@ -0,0 +1,12 @@
1
+ import type { ProcedureBuilderOf, ProcedureBuilderSurface, ResolverContext } from "./procedureTypes.ts";
2
+ export function looseBuilder<TContext, TMeta, TContextOverrides, TInputIn, TInputOut, TOutputIn, TOutputOut>(
3
+ builder: ProcedureBuilderOf<TContext, TMeta, TContextOverrides, TInputIn, TInputOut, TOutputIn, TOutputOut>,
4
+ ): ProcedureBuilderSurface<ResolverContext<TContext, TMeta, TContextOverrides>>;
5
+ export function looseBuilder(builder: unknown): unknown {
6
+ return builder;
7
+ }
8
+ // tRPC runs the procedure's input parsers before the resolver, so the resolver receives the input it declared.
9
+ export function acceptParsedInput<TResult>(resolver: (input: never) => TResult): (input: unknown) => TResult;
10
+ export function acceptParsedInput(resolver: unknown): unknown {
11
+ return resolver;
12
+ }
@@ -2,18 +2,16 @@ import { Effect } from "effect";
2
2
  import type { EffectProcedureRequestServices } from "#request-services.ts";
3
3
  import type { ProcedureInfo } from "#types.ts";
4
4
  import { acceptParsedInput } from "./loose.ts";
5
- import type { EffectProcedureResolver, ProcedureInvocation } from "./procedure-types.ts";
5
+ import type { EffectProcedureResolver, ProcedureInvocation } from "./procedureTypes.ts";
6
6
  import type { RuntimeBridge } from "./runtime.ts";
7
-
8
- export const makeProcedureHandler = <RuntimeRequirements, Context, ProvidedServices, LayerError>(
9
- runtime: RuntimeBridge<RuntimeRequirements>,
10
- resolver: EffectProcedureResolver<never, ProvidedServices | NoInfer<RuntimeRequirements>, unknown>,
11
- requestServices: EffectProcedureRequestServices<Context, ProvidedServices, LayerError>,
7
+ export function makeProcedureHandler<TRuntimeRequirements, TContext, TProvidedServices, TLayerError>(
8
+ runtime: RuntimeBridge<TRuntimeRequirements>,
9
+ resolver: EffectProcedureResolver<never, TProvidedServices | NoInfer<TRuntimeRequirements>, unknown>,
10
+ requestServices: EffectProcedureRequestServices<TContext, TProvidedServices, TLayerError>,
12
11
  procedure: Omit<ProcedureInfo, "path">,
13
- ) => {
12
+ ) {
14
13
  const tracedResolver = Effect.fnUntraced(acceptParsedInput(resolver));
15
-
16
- return async (invocation: ProcedureInvocation<Context>) => {
14
+ return async (invocation: ProcedureInvocation<TContext>) => {
17
15
  const info = { ...procedure, path: invocation.path };
18
16
  const provided = Effect.suspend(() =>
19
17
  runtime.instrument(tracedResolver(invocation.input), info).pipe(Effect.provide(requestServices.layer(invocation.ctx))),
@@ -23,4 +21,4 @@ export const makeProcedureHandler = <RuntimeRequirements, Context, ProvidedServi
23
21
  ...(invocation.signal === undefined ? {} : { signal: invocation.signal }),
24
22
  });
25
23
  };
26
- };
24
+ }