@@ -55,6 +55,7 @@ import type {
5555import type { ClientDbView } from './db_view.ts' ;
5656import type { UntypedTableDef } from '../lib/table.ts' ;
5757import { toCamelCase , toPascalCase } from '../lib/util.ts' ;
58+ import type { ProceduresView } from './procedures.ts' ;
5859
5960export {
6061 DbConnectionBuilder ,
@@ -137,13 +138,20 @@ export class DbConnectionImpl<RemoteModule extends UntypedRemoteModule>
137138 */
138139 setReducerFlags : SetReducerFlags < RemoteModule > ;
139140
141+ /**
142+ * The accessor field to access the reducers in the database and associated
143+ * callback functions.
144+ */
145+ procedures : ProceduresView < RemoteModule > ;
146+
140147 /**
141148 * The `ConnectionId` of the connection to to the database.
142149 */
143150 connectionId : ConnectionId = ConnectionId . random ( ) ;
144151
145152 // These fields are meant to be strictly private.
146153 #queryId = 0 ;
154+ #requestId = 0 ;
147155 #emitter: EventEmitter < ConnectionEvent > ;
148156 #reducerEmitter: EventEmitter < string , ReducerEventCallback < RemoteModule > > =
149157 new EventEmitter ( ) ;
@@ -198,6 +206,7 @@ export class DbConnectionImpl<RemoteModule extends UntypedRemoteModule>
198206 this . db = this . #makeDbView( remoteModule ) ;
199207 this . reducers = this . #makeReducers( remoteModule ) ;
200208 this . setReducerFlags = this . #makeSetReducerFlags( remoteModule ) ;
209+ this . procedures = this . #makeProcedures( remoteModule ) ;
201210
202211 this . wsPromise = createWSFn ( {
203212 url,
@@ -237,6 +246,8 @@ export class DbConnectionImpl<RemoteModule extends UntypedRemoteModule>
237246 return queryId ;
238247 } ;
239248
249+ #getNextRequestId = ( ) => this . #requestId++ ;
250+
240251 #makeDbView( def : RemoteModule ) : ClientDbView < RemoteModule > {
241252 const view = Object . create ( null ) as ClientDbView < RemoteModule > ;
242253
@@ -310,6 +321,45 @@ export class DbConnectionImpl<RemoteModule extends UntypedRemoteModule>
310321 return out ;
311322 }
312323
324+ #makeProcedures( def : RemoteModule ) : ProceduresView < RemoteModule > {
325+ const out : Record < string , unknown > = { } ;
326+
327+ for ( const reducer of def . reducers ) {
328+ const key = toCamelCase ( reducer . name ) ;
329+
330+ ( out as any ) [ key ] = ( params : InferTypeOfRow < typeof reducer . params > ) => {
331+ this . callReducerWithParams (
332+ reducer . name ,
333+ reducer . paramsType ,
334+ params ,
335+ flags
336+ ) ;
337+ } ;
338+
339+ const onReducerEventKey = `on${ toPascalCase ( reducer . name ) } ` ;
340+ ( out as any ) [ onReducerEventKey ] = (
341+ callback : ReducerEventCallback <
342+ RemoteModule ,
343+ InferTypeOfRow < typeof reducer . params >
344+ >
345+ ) => {
346+ this . onReducer ( reducer . name , callback ) ;
347+ } ;
348+
349+ const offReducerEventKey = `removeOn${ toPascalCase ( reducer . name ) } ` ;
350+ ( out as any ) [ offReducerEventKey ] = (
351+ callback : ReducerEventCallback <
352+ RemoteModule ,
353+ InferTypeOfRow < typeof reducer . params >
354+ >
355+ ) => {
356+ this . offReducer ( reducer . name , callback ) ;
357+ } ;
358+ }
359+
360+ return out as ReducersView < RemoteModule > ;
361+ }
362+
313363 #makeEventContext(
314364 event : Event <
315365 ReducerEventInfo <
@@ -916,6 +966,43 @@ export class DbConnectionImpl<RemoteModule extends UntypedRemoteModule>
916966 this . callReducer ( reducerName , argsBuffer , flags ) ;
917967 }
918968
969+ /**
970+ * Call a reducer on your SpacetimeDB module.
971+ *
972+ * @param procedureName The name of the reducer to call
973+ * @param argsBuffer The arguments to pass to the reducer
974+ */
975+ callProcedure ( procedureName : string , argsBuffer : Uint8Array ) : void {
976+ const message = ClientMessage . CallProcedure ( {
977+ procedure : procedureName ,
978+ args : argsBuffer ,
979+ // The TypeScript SDK doesn't currently track `request_id`s,
980+ // so always use 0.
981+ requestId : 0 ,
982+ // reserved for future use - 0 is the only valid value
983+ flags : 0 ,
984+ } ) ;
985+ this . #sendMessage( message ) ;
986+ }
987+
988+ /**
989+ * Call a reducer on your SpacetimeDB module with typed arguments.
990+ * @param reducerSchema The schema of the reducer to call
991+ * @param callReducerFlags The flags for the reducer call
992+ * @param params The arguments to pass to the reducer
993+ */
994+ callProcedureWithParams (
995+ procedureName : string ,
996+ paramsType : ProductType ,
997+ params : object ,
998+ flags : CallReducerFlags
999+ ) {
1000+ const writer = new BinaryWriter ( 1024 ) ;
1001+ ProductType . serializeValue ( writer , paramsType , params ) ;
1002+ const argsBuffer = writer . getBuffer ( ) ;
1003+ this . callProcedure ( procedureName , argsBuffer , flags ) ;
1004+ }
1005+
9191006 /**
9201007 * Close the current connection.
9211008 *
0 commit comments