@replit/river 0.208.3 → 0.209.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 (59) hide show
  1. package/README.md +36 -1
  2. package/dist/{adapter-ChksXKVN.d.ts → adapter-Cp7_gIVA.d.ts} +1 -1
  3. package/dist/{adapter-Cuc4JtfV.d.cts → adapter-DjiEwOYi.d.cts} +1 -1
  4. package/dist/{chunk-M2B4PVR5.js → chunk-LPWARXI3.js} +2 -2
  5. package/dist/{chunk-JC4XN6NC.js → chunk-RATCBAZE.js} +199 -170
  6. package/dist/chunk-RATCBAZE.js.map +1 -0
  7. package/dist/{chunk-3WYK5ZRT.js → chunk-TVN2TB6X.js} +2 -2
  8. package/dist/{chunk-3WYK5ZRT.js.map → chunk-TVN2TB6X.js.map} +1 -1
  9. package/dist/client-BzJwq-hg.d.ts +54 -0
  10. package/dist/client-aETS93z1.d.cts +54 -0
  11. package/dist/codec/index.d.cts +3 -3
  12. package/dist/codec/index.d.ts +3 -3
  13. package/dist/codec/index.js +2 -2
  14. package/dist/{connection-Donr3JRB.d.ts → connection-b1wd5XrC.d.ts} +3 -3
  15. package/dist/{connection-BF4zg6Qv.d.cts → connection-hUWlS-hg.d.cts} +3 -3
  16. package/dist/{index-D8IOd3LG.d.ts → index-CSM8soK7.d.ts} +1 -1
  17. package/dist/{index-C9tpZjBN.d.cts → index-D9R6UTMl.d.cts} +1 -1
  18. package/dist/logging/index.d.cts +2 -2
  19. package/dist/logging/index.d.ts +2 -2
  20. package/dist/{message-Di94OL80.d.cts → message-Dlsh5WDF.d.cts} +1 -1
  21. package/dist/{message-Di94OL80.d.ts → message-Dlsh5WDF.d.ts} +1 -1
  22. package/dist/router/index.cjs +199 -170
  23. package/dist/router/index.cjs.map +1 -1
  24. package/dist/router/index.d.cts +21 -18
  25. package/dist/router/index.d.ts +21 -18
  26. package/dist/router/index.js +3 -3
  27. package/dist/server-BBgDVOzk.d.cts +72 -0
  28. package/dist/server-DZ0Yzmpf.d.ts +72 -0
  29. package/dist/services-DBvjc-Mq.d.ts +1010 -0
  30. package/dist/services-DC_uol9A.d.cts +1010 -0
  31. package/dist/testUtil/index.cjs +1 -1
  32. package/dist/testUtil/index.cjs.map +1 -1
  33. package/dist/testUtil/index.d.cts +9 -7
  34. package/dist/testUtil/index.d.ts +9 -7
  35. package/dist/testUtil/index.js +2 -2
  36. package/dist/testUtil/index.js.map +1 -1
  37. package/dist/transport/impls/ws/client.cjs +1 -1
  38. package/dist/transport/impls/ws/client.cjs.map +1 -1
  39. package/dist/transport/impls/ws/client.d.cts +6 -5
  40. package/dist/transport/impls/ws/client.d.ts +6 -5
  41. package/dist/transport/impls/ws/client.js +3 -3
  42. package/dist/transport/impls/ws/server.cjs +1 -1
  43. package/dist/transport/impls/ws/server.cjs.map +1 -1
  44. package/dist/transport/impls/ws/server.d.cts +8 -8
  45. package/dist/transport/impls/ws/server.d.ts +8 -8
  46. package/dist/transport/impls/ws/server.js +3 -3
  47. package/dist/transport/impls/ws/server.js.map +1 -1
  48. package/dist/transport/index.cjs +1 -1
  49. package/dist/transport/index.cjs.map +1 -1
  50. package/dist/transport/index.d.cts +7 -74
  51. package/dist/transport/index.d.ts +7 -74
  52. package/dist/transport/index.js +2 -2
  53. package/dist/transport-CxjUaGhi.d.cts +577 -0
  54. package/dist/transport-DwEB67zY.d.ts +577 -0
  55. package/package.json +1 -1
  56. package/dist/chunk-JC4XN6NC.js.map +0 -1
  57. package/dist/transport-CCaWx1Rb.d.cts +0 -1566
  58. package/dist/transport-CZb3vdB4.d.ts +0 -1566
  59. /package/dist/{chunk-M2B4PVR5.js.map → chunk-LPWARXI3.js.map} +0 -0
@@ -27,13 +27,13 @@ __export(router_exports, {
27
27
  Procedure: () => Procedure,
28
28
  RIVER_VERSION: () => version,
29
29
  ReaderErrorSchema: () => ReaderErrorSchema,
30
- ServiceSchema: () => ServiceSchema,
31
30
  UNCAUGHT_ERROR_CODE: () => UNCAUGHT_ERROR_CODE,
32
31
  UNEXPECTED_DISCONNECT_CODE: () => UNEXPECTED_DISCONNECT_CODE,
33
32
  createClient: () => createClient,
34
33
  createClientHandshakeOptions: () => createClientHandshakeOptions,
35
34
  createServer: () => createServer,
36
35
  createServerHandshakeOptions: () => createServerHandshakeOptions,
36
+ createServiceSchema: () => createServiceSchema,
37
37
  flattenErrorType: () => flattenErrorType,
38
38
  serializeSchema: () => serializeSchema,
39
39
  serializeSchemaV1Compat: () => serializeSchemaV1Compat
@@ -146,182 +146,184 @@ function serializeSchema(services, handshakeSchema) {
146
146
  }
147
147
  return schema;
148
148
  }
149
- var ServiceSchema = class _ServiceSchema {
150
- /**
151
- * Factory function for creating a fresh state.
152
- */
153
- initializeState;
154
- /**
155
- * The procedures for this service.
156
- */
157
- procedures;
158
- /**
159
- * @param config - The configuration for this service.
160
- * @param procedures - The procedures for this service.
161
- */
162
- constructor(config, procedures) {
163
- this.initializeState = config.initializeState;
164
- this.procedures = procedures;
165
- }
166
- /**
167
- * Creates a {@link ServiceScaffold}, which can be used to define procedures
168
- * that can then be merged into a {@link ServiceSchema}, via the scaffold's
169
- * `finalize` method.
170
- *
171
- * There are two patterns that work well with this method. The first is using
172
- * it to separate the definition of procedures from the definition of the
173
- * service's configuration:
174
- * ```ts
175
- * const MyServiceScaffold = ServiceSchema.scaffold({
176
- * initializeState: () => ({ count: 0 }),
177
- * });
178
- *
179
- * const incrementProcedures = MyServiceScaffold.procedures({
180
- * increment: Procedure.rpc({
181
- * requestInit: Type.Object({ amount: Type.Number() }),
182
- * responseData: Type.Object({ current: Type.Number() }),
183
- * async handler(ctx, init) {
184
- * ctx.state.count += init.amount;
185
- * return Ok({ current: ctx.state.count });
186
- * }
187
- * }),
188
- * })
189
- *
190
- * const MyService = MyServiceScaffold.finalize({
191
- * ...incrementProcedures,
192
- * // you can also directly define procedures here
193
- * });
194
- * ```
195
- * This might be really handy if you have a very large service and you're
196
- * wanting to split it over multiple files. You can define the scaffold
197
- * in one file, and then import that scaffold in other files where you
198
- * define procedures - and then finally import the scaffolds and your
199
- * procedure objects in a final file where you finalize the scaffold into
200
- * a service schema.
201
- *
202
- * The other way is to use it like in a builder pattern:
203
- * ```ts
204
- * const MyService = ServiceSchema
205
- * .scaffold({ initializeState: () => ({ count: 0 }) })
206
- * .finalize({
207
- * increment: Procedure.rpc({
208
- * requestInit: Type.Object({ amount: Type.Number() }),
209
- * responseData: Type.Object({ current: Type.Number() }),
210
- * async handler(ctx, init) {
211
- * ctx.state.count += init.amount;
212
- * return Ok({ current: ctx.state.count });
213
- * }
214
- * }),
215
- * })
216
- * ```
217
- * Depending on your preferences, this may be a more appealing way to define
218
- * a schema versus using the {@link ServiceSchema.define} method.
219
- */
220
- static scaffold(config) {
221
- return new ServiceScaffold(config);
222
- }
223
- // actual implementation
224
- static define(configOrProcedures, maybeProcedures) {
225
- let config;
226
- let procedures;
227
- if ("initializeState" in configOrProcedures && typeof configOrProcedures.initializeState === "function") {
228
- if (!maybeProcedures) {
229
- throw new Error("Expected procedures to be defined");
149
+ function createServiceSchema() {
150
+ return class ServiceSchema {
151
+ /**
152
+ * Factory function for creating a fresh state.
153
+ */
154
+ initializeState;
155
+ /**
156
+ * The procedures for this service.
157
+ */
158
+ procedures;
159
+ /**
160
+ * @param config - The configuration for this service.
161
+ * @param procedures - The procedures for this service.
162
+ */
163
+ constructor(config, procedures) {
164
+ this.initializeState = config.initializeState;
165
+ this.procedures = procedures;
166
+ }
167
+ /**
168
+ * Creates a {@link ServiceScaffold}, which can be used to define procedures
169
+ * that can then be merged into a {@link ServiceSchema}, via the scaffold's
170
+ * `finalize` method.
171
+ *
172
+ * There are two patterns that work well with this method. The first is using
173
+ * it to separate the definition of procedures from the definition of the
174
+ * service's configuration:
175
+ * ```ts
176
+ * const MyServiceScaffold = ServiceSchema.scaffold({
177
+ * initializeState: () => ({ count: 0 }),
178
+ * });
179
+ *
180
+ * const incrementProcedures = MyServiceScaffold.procedures({
181
+ * increment: Procedure.rpc({
182
+ * requestInit: Type.Object({ amount: Type.Number() }),
183
+ * responseData: Type.Object({ current: Type.Number() }),
184
+ * async handler(ctx, init) {
185
+ * ctx.state.count += init.amount;
186
+ * return Ok({ current: ctx.state.count });
187
+ * }
188
+ * }),
189
+ * })
190
+ *
191
+ * const MyService = MyServiceScaffold.finalize({
192
+ * ...incrementProcedures,
193
+ * // you can also directly define procedures here
194
+ * });
195
+ * ```
196
+ * This might be really handy if you have a very large service and you're
197
+ * wanting to split it over multiple files. You can define the scaffold
198
+ * in one file, and then import that scaffold in other files where you
199
+ * define procedures - and then finally import the scaffolds and your
200
+ * procedure objects in a final file where you finalize the scaffold into
201
+ * a service schema.
202
+ *
203
+ * The other way is to use it like in a builder pattern:
204
+ * ```ts
205
+ * const MyService = ServiceSchema
206
+ * .scaffold({ initializeState: () => ({ count: 0 }) })
207
+ * .finalize({
208
+ * increment: Procedure.rpc({
209
+ * requestInit: Type.Object({ amount: Type.Number() }),
210
+ * responseData: Type.Object({ current: Type.Number() }),
211
+ * async handler(ctx, init) {
212
+ * ctx.state.count += init.amount;
213
+ * return Ok({ current: ctx.state.count });
214
+ * }
215
+ * }),
216
+ * })
217
+ * ```
218
+ * Depending on your preferences, this may be a more appealing way to define
219
+ * a schema versus using the {@link ServiceSchema.define} method.
220
+ */
221
+ static scaffold(config) {
222
+ return new ServiceScaffold(config);
223
+ }
224
+ // actual implementation
225
+ static define(configOrProcedures, maybeProcedures) {
226
+ let config;
227
+ let procedures;
228
+ if ("initializeState" in configOrProcedures && typeof configOrProcedures.initializeState === "function") {
229
+ if (!maybeProcedures) {
230
+ throw new Error("Expected procedures to be defined");
231
+ }
232
+ config = configOrProcedures;
233
+ procedures = maybeProcedures;
234
+ } else {
235
+ config = { initializeState: () => ({}) };
236
+ procedures = configOrProcedures;
230
237
  }
231
- config = configOrProcedures;
232
- procedures = maybeProcedures;
233
- } else {
234
- config = { initializeState: () => ({}) };
235
- procedures = configOrProcedures;
238
+ return new ServiceSchema(config, procedures);
236
239
  }
237
- return new _ServiceSchema(config, procedures);
238
- }
239
- /**
240
- * Serializes this schema's procedures into a plain object that is JSON compatible.
241
- */
242
- serialize() {
243
- return {
244
- procedures: Object.fromEntries(
245
- Object.entries(this.procedures).map(([procName, procDef]) => [
246
- procName,
247
- {
248
- init: Strict(procDef.requestInit),
249
- output: Strict(procDef.responseData),
250
- errors: getSerializedProcErrors(procDef),
251
- // Only add `description` field if the type declares it.
252
- ..."description" in procDef ? { description: procDef.description } : {},
253
- type: procDef.type,
254
- // Only add the `input` field if the type declares it.
255
- ..."requestData" in procDef ? {
256
- input: Strict(procDef.requestData)
257
- } : {}
258
- }
259
- ])
260
- )
261
- };
262
- }
263
- // TODO remove once clients migrate to v2
264
- /**
265
- * Same as {@link ServiceSchema.serialize}, but with a format that is compatible with
266
- * protocol v1. This is useful to be able to continue to generate schemas for older
267
- * clients as they are still supported.
268
- */
269
- serializeV1Compat() {
270
- return {
271
- procedures: Object.fromEntries(
272
- Object.entries(this.procedures).map(
273
- ([procName, procDef]) => {
274
- if (procDef.type === "rpc" || procDef.type === "subscription") {
240
+ /**
241
+ * Serializes this schema's procedures into a plain object that is JSON compatible.
242
+ */
243
+ serialize() {
244
+ return {
245
+ procedures: Object.fromEntries(
246
+ Object.entries(this.procedures).map(([procName, procDef]) => [
247
+ procName,
248
+ {
249
+ init: Strict(procDef.requestInit),
250
+ output: Strict(procDef.responseData),
251
+ errors: getSerializedProcErrors(procDef),
252
+ // Only add `description` field if the type declares it.
253
+ ..."description" in procDef ? { description: procDef.description } : {},
254
+ type: procDef.type,
255
+ // Only add the `input` field if the type declares it.
256
+ ..."requestData" in procDef ? {
257
+ input: Strict(procDef.requestData)
258
+ } : {}
259
+ }
260
+ ])
261
+ )
262
+ };
263
+ }
264
+ // TODO remove once clients migrate to v2
265
+ /**
266
+ * Same as {@link ServiceSchema.serialize}, but with a format that is compatible with
267
+ * protocol v1. This is useful to be able to continue to generate schemas for older
268
+ * clients as they are still supported.
269
+ */
270
+ serializeV1Compat() {
271
+ return {
272
+ procedures: Object.fromEntries(
273
+ Object.entries(this.procedures).map(
274
+ ([procName, procDef]) => {
275
+ if (procDef.type === "rpc" || procDef.type === "subscription") {
276
+ return [
277
+ procName,
278
+ {
279
+ // BACKWARDS COMPAT: map init to input for protocolv1
280
+ // this is the only change needed to make it compatible.
281
+ input: Strict(procDef.requestInit),
282
+ output: Strict(procDef.responseData),
283
+ errors: getSerializedProcErrors(procDef),
284
+ // Only add `description` field if the type declares it.
285
+ ..."description" in procDef ? { description: procDef.description } : {},
286
+ type: procDef.type
287
+ }
288
+ ];
289
+ }
275
290
  return [
276
291
  procName,
277
292
  {
278
- // BACKWARDS COMPAT: map init to input for protocolv1
279
- // this is the only change needed to make it compatible.
280
- input: Strict(procDef.requestInit),
293
+ init: Strict(procDef.requestInit),
281
294
  output: Strict(procDef.responseData),
282
295
  errors: getSerializedProcErrors(procDef),
283
296
  // Only add `description` field if the type declares it.
284
297
  ..."description" in procDef ? { description: procDef.description } : {},
285
- type: procDef.type
298
+ type: procDef.type,
299
+ input: Strict(procDef.requestData)
286
300
  }
287
301
  ];
288
302
  }
289
- return [
290
- procName,
291
- {
292
- init: Strict(procDef.requestInit),
293
- output: Strict(procDef.responseData),
294
- errors: getSerializedProcErrors(procDef),
295
- // Only add `description` field if the type declares it.
296
- ..."description" in procDef ? { description: procDef.description } : {},
297
- type: procDef.type,
298
- input: Strict(procDef.requestData)
299
- }
300
- ];
301
- }
303
+ )
302
304
  )
303
- )
304
- };
305
- }
306
- /**
307
- * Instantiates this schema into a {@link Service} object.
308
- *
309
- * You probably don't need this, usually the River server will handle this
310
- * for you.
311
- */
312
- instantiate(extendedContext) {
313
- const state = this.initializeState(extendedContext);
314
- const dispose = async () => {
315
- await state[Symbol.asyncDispose]?.();
316
- state[Symbol.dispose]?.();
317
- };
318
- return Object.freeze({
319
- state,
320
- procedures: this.procedures,
321
- [Symbol.asyncDispose]: dispose
322
- });
323
- }
324
- };
305
+ };
306
+ }
307
+ /**
308
+ * Instantiates this schema into a {@link Service} object.
309
+ *
310
+ * You probably don't need this, usually the River server will handle this
311
+ * for you.
312
+ */
313
+ instantiate(extendedContext) {
314
+ const state = this.initializeState(extendedContext);
315
+ const dispose = async () => {
316
+ await state[Symbol.asyncDispose]?.();
317
+ state[Symbol.dispose]?.();
318
+ };
319
+ return Object.freeze({
320
+ state,
321
+ procedures: this.procedures,
322
+ [Symbol.asyncDispose]: dispose
323
+ });
324
+ }
325
+ };
326
+ }
325
327
  function getSerializedProcErrors(procDef) {
326
328
  if (!("responseError" in procDef) || procDef.responseError[import_typebox2.Kind] === "Never") {
327
329
  return Strict(ReaderErrorSchema);
@@ -384,7 +386,10 @@ var ServiceScaffold = class {
384
386
  * ```
385
387
  */
386
388
  finalize(procedures) {
387
- return ServiceSchema.define(this.config, procedures);
389
+ return createServiceSchema().define(
390
+ this.config,
391
+ procedures
392
+ );
388
393
  }
389
394
  };
390
395
 
@@ -964,6 +969,9 @@ function createClient(transport, serverId, providedClientOptions = {}) {
964
969
  }, []);
965
970
  }
966
971
  function handleProc(procType, transport, serverId, init, serviceName, procedureName, abortSignal) {
972
+ if (transport.getStatus() === "closed") {
973
+ return getPreClosedReturnForProc(procType);
974
+ }
967
975
  const session = transport.sessions.get(serverId) ?? transport.createUnconnectedSession(serverId);
968
976
  const sessionScopedSend = transport.getSessionBoundSendFn(
969
977
  serverId,
@@ -1140,13 +1148,33 @@ function handleProc(procType, transport, serverId, init, serviceName, procedureN
1140
1148
  if (procClosesWithInit) {
1141
1149
  reqWritable.close();
1142
1150
  }
1151
+ return getReturnForProc(procType, resReadable, reqWritable, transport.log);
1152
+ }
1153
+ function getPreClosedReturnForProc(procType) {
1154
+ const readable = new ReadableImpl();
1155
+ const err = Err({
1156
+ code: UNEXPECTED_DISCONNECT_CODE,
1157
+ message: `transport is closed`
1158
+ });
1159
+ readable._pushValue(err);
1160
+ readable._triggerClose();
1161
+ const writable = new WritableImpl({
1162
+ writeCb: () => {
1163
+ },
1164
+ closeCb: () => {
1165
+ }
1166
+ });
1167
+ writable.close();
1168
+ return getReturnForProc(procType, readable, writable);
1169
+ }
1170
+ function getReturnForProc(procType, resReadable, reqWritable, log) {
1143
1171
  if (procType === "subscription") {
1144
1172
  return {
1145
1173
  resReadable
1146
1174
  };
1147
1175
  }
1148
1176
  if (procType === "rpc") {
1149
- return getSingleMessage(resReadable, transport.log);
1177
+ return getSingleMessage(resReadable, log);
1150
1178
  }
1151
1179
  if (procType === "upload") {
1152
1180
  let didFinalize = false;
@@ -1160,7 +1188,7 @@ function handleProc(procType, transport, serverId, init, serviceName, procedureN
1160
1188
  if (!reqWritable.isClosed()) {
1161
1189
  reqWritable.close();
1162
1190
  }
1163
- return getSingleMessage(resReadable, transport.log);
1191
+ return getSingleMessage(resReadable, log);
1164
1192
  }
1165
1193
  };
1166
1194
  }
@@ -1211,8 +1239,9 @@ var RiverServer = class {
1211
1239
  this.middlewares = middlewares;
1212
1240
  this.services = instances;
1213
1241
  this.contextMap = /* @__PURE__ */ new Map();
1242
+ extendedContext = extendedContext ?? {};
1214
1243
  for (const [name, service] of Object.entries(services)) {
1215
- const instance = service.instantiate(extendedContext ?? {});
1244
+ const instance = service.instantiate(extendedContext);
1216
1245
  instances[name] = instance;
1217
1246
  this.contextMap.set(instance, {
1218
1247
  ...extendedContext,
@@ -1895,7 +1924,7 @@ function createServerHandshakeOptions(schema, validate) {
1895
1924
  }
1896
1925
 
1897
1926
  // package.json
1898
- var version = "0.208.3";
1927
+ var version = "0.209.0";
1899
1928
  // Annotate the CommonJS export names for ESM import in node:
1900
1929
  0 && (module.exports = {
1901
1930
  CANCEL_CODE,
@@ -1905,13 +1934,13 @@ var version = "0.208.3";
1905
1934
  Procedure,
1906
1935
  RIVER_VERSION,
1907
1936
  ReaderErrorSchema,
1908
- ServiceSchema,
1909
1937
  UNCAUGHT_ERROR_CODE,
1910
1938
  UNEXPECTED_DISCONNECT_CODE,
1911
1939
  createClient,
1912
1940
  createClientHandshakeOptions,
1913
1941
  createServer,
1914
1942
  createServerHandshakeOptions,
1943
+ createServiceSchema,
1915
1944
  flattenErrorType,
1916
1945
  serializeSchema,
1917
1946
  serializeSchemaV1Compat